jrowberg / i2cdevlib

I2C device library collection for AVR/Arduino or other C++-based MCUs
http://www.i2cdevlib.com
3.92k stars 7.52k forks source link

MPU6050 connection failed but can still read values? #428

Open Philogy opened 5 years ago

Philogy commented 5 years ago

accelgyro.testConnection() seems to return false but my GY-521 break out board seems to be connected properly and later when running accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); it seems to read the values just fine. Could anyone please help me?

petersondmg commented 5 years ago

Same here

xyz2k8 commented 5 years ago

accelgyro.testConnection() seems to return false but my GY-521 break out board seems to be connected properly and later when running accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); it seems to read the values just fine. Could anyone please help me?

I also encountered this problem, have you solved it?

sylvanoMTL commented 4 years ago

Same here, I am using the ESP32 library https://github.com/ElectronicCats/mpu6050 which was adapted from teh i2cDev Library. I have exactly the same issue when using the RAW example. Connection Failed, but I have data that make sense when I observe them using the serial plotter. I checked the I2c address with a scanner and I am using the 0x68 by default. I tried to use Pull-up resistor as recommended on some forum (10 kOhm) but did not work.

When testing the DMP V6.12 programme, I still have the Failed connection and The DMP error code is 1

Has anyone be able to overcome this issue?

sylvanoMTL commented 4 years ago

I do not know how I sorted out the error code 1. Now facing the infinite calibration problem

stanislawix commented 2 years ago

I do not know how I sorted out the error code 1. Now facing the infinite calibration problem

cmon give us a clue xd

ZHomeSlice commented 2 years ago

Some Thoughts ESP32 is a 3.3v device GY-521 is a 5V breakout board with a voltage regulator to produce 3.3V (See Schematic) GY-521 Schematic

You will want to bypass the voltage regulator if you only have a 3.3V source otherwise your MPU6050 will be supplied with < 3.3V

@stanislawix "Now facing the infinite calibration problem" How the calibration routine works: The goal is to zero out all readings after removing gravity from the Z-axis. Each cycle the error from zero is calculated. an Integral routine is used to adjust the offsets which after about 1ms delay allows for a new reading with the corrected output. This repeats thousands of times over a few seconds to achieve calibration.

If Gravity is influencing another axis besides Z With the bottom of the MPU6050 facing down the offsets can't achieve enough influence to compensate for the error thus an infinite calibration problem. Another possibility is the initial offset values are so skewed that the routine can't find the correct direction to adjust.

try starting with:

  // supply your own gyro offsets here, scaled for min sensitivity
  mpu.setXGyroOffset(0);
  mpu.setYGyroOffset(0);
  mpu.setZGyroOffset(0);
  mpu.setXAccelOffset(0);
  mpu.setYAccelOffset(0);
  mpu.setZAccelOffset(0);

all offsets set to zero and then running the calibration routine with the MPU6050 flat. once the calibration is successfully finished new offsets just for this MPU will be generated which should replace the ones we zeroed out. Now calibrations in the future with this MPU will be much faster and more accurate because only fine-tuning caused by temperature changes will be necessary. ZHomeSlice

Infinite Calibration detection you will see a "*" appear in your serial output.

    if((c == 99) && eSum > 1000){   // Error is still to great to continue 
        c = 0;
        Serial.write('*');
    }

Calibration routine for reference:

void MPU6050_Base::PID(uint8_t ReadAddress, float kP,float kI, uint8_t Loops){
    uint8_t SaveAddress = (ReadAddress == 0x3B)?((getDeviceID() < 0x38 )? 0x06:0x77):0x13;

    int16_t  Data;
    float Reading;
    int16_t BitZero[3];
    uint8_t shift =(SaveAddress == 0x77)?3:2;
    float Error, PTerm, ITerm[3];
    int16_t eSample;
    uint32_t eSum;
    uint16_t gravity = 8192; // prevent uninitialized compiler warning
    if (ReadAddress == 0x3B) gravity = 16384 >> getFullScaleAccelRange();
    Serial.write('>');
    for (int i = 0; i < 3; i++) {
        I2Cdev::readWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data, I2Cdev::readTimeout, wireObj); // reads 1 or more 16 bit integers (Word)
        Reading = Data;
        if(SaveAddress != 0x13){
            BitZero[i] = Data & 1;                                       // Capture Bit Zero to properly handle Accelerometer calibration
            ITerm[i] = ((float)Reading) * 8;
            } else {
            ITerm[i] = Reading * 4;
        }
    }
    for (int L = 0; L < Loops; L++) {
        eSample = 0;
        for (int c = 0; c < 100; c++) {// 100 PI Calculations
            eSum = 0;
            for (int i = 0; i < 3; i++) {
                I2Cdev::readWords(devAddr, ReadAddress + (i * 2), 1, (uint16_t *)&Data, I2Cdev::readTimeout, wireObj); // reads 1 or more 16 bit integers (Word)
                Reading = Data;
                if ((ReadAddress == 0x3B)&&(i == 2)) Reading -= gravity;    //remove Gravity
                Error = -Reading;
                eSum += abs(Reading);
                PTerm = kP * Error;
                ITerm[i] += (Error * 0.001) * kI;               // Integral term 1000 Calculations a second = 0.001
                if(SaveAddress != 0x13){
                    Data = round((PTerm + ITerm[i] ) / 8);      //Compute PID Output
                    Data = ((Data)&0xFFFE) |BitZero[i];         // Insert Bit0 Saved at beginning
                } else Data = round((PTerm + ITerm[i] ) / 4);   //Compute PID Output
                I2Cdev::writeWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data, wireObj);
            }
            if((c == 99) && eSum > 1000){                       // Error is still to great to continue 
                c = 0;
                Serial.write('*');
            }
            if((eSum * ((ReadAddress == 0x3B)?.05: 1)) < 5) eSample++;  // Successfully found offsets prepare to  advance
            if((eSum < 100) && (c > 10) && (eSample >= 10)) break;      // Advance to next Loop
            delay(1);
        }
        Serial.write('.');
        kP *= .75;
        kI *= .75;
        for (int i = 0; i < 3; i++){
            if(SaveAddress != 0x13) {
                Data = round((ITerm[i] ) / 8);      //Compute PID Output
                Data = ((Data)&0xFFFE) |BitZero[i]; // Insert Bit0 Saved at beginning
            } else Data = round((ITerm[i]) / 4);
            I2Cdev::writeWords(devAddr, SaveAddress + (i * shift), 1, (uint16_t *)&Data, wireObj);
        }
    }
    resetFIFO();
    resetDMP();
}