arduinoesp32mpu6050

Arduino Wire Library returning Error Code 7 (which is not defined in the library)


I'm using an ESP32 to try to read from an IMU, the MPU-6050. I'm using the code that is available on the Arduino web site with a slight variation; I'm checking the error code on endTransmission and am printing it (I started to do this because I was getting all zero values back from my calls to read the MPU registers). On the very first call to initialize the MPU I receive a success error code. But for ever call after that I receive error code 7. What's odd is when I trace through the Wire library I find that there is no error code 7 defined. The function in question only has 4 possible return values and 7 isn't one of them.

Here is the entirity of the code.

    #include<Wire.h>
    const int MPU_addr=0x68;  // I2C address of the MPU-6050
    int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
    int initialError;
    void setup(){
      Wire.begin();
      Wire.beginTransmission(MPU_addr);
      Wire.write(0x6B);  // PWR_MGMT_1 register
      Wire.write(0);     // set to zero (wakes up the MPU-6050)
      initialError = Wire.endTransmission(true);
      Serial.begin(9600);

    }
    void loop(){
      int error ;
      Wire.beginTransmission(MPU_addr);
      Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
      error = Wire.endTransmission(false);
      if(error)
      {
        Serial.print("Errors: ");
        Serial.print(initialError);
        Serial.print(" ");
        Serial.println(error);
      }
      else {
        Wire.requestFrom(MPU_addr,14,true);  // request a total of 14 registers
        AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)    
        AcY=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
        AcZ=Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
        Tmp=Wire.read()<<8|Wire.read();  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
        GyX=Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
        GyY=Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
        GyZ=Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
        Serial.print("AcX = "); Serial.print(AcX);
        Serial.print(" | AcY = "); Serial.print(AcY);
        Serial.print(" | AcZ = "); Serial.print(AcZ);
        Serial.print(" | Tmp = "); Serial.print(Tmp/340.00+36.53);  //equation for temperature in degrees C from datasheet
        Serial.print(" | GyX = "); Serial.print(GyX);
        Serial.print(" | GyY = "); Serial.print(GyY);
        Serial.print(" | GyZ = "); Serial.println(GyZ);
        delay(333);
      }
    }

initialError is zero (success), the other error is 7 ( ? ). Anyone have any idea what is going on here and how to correct?


Solution

  • I found the problem. Well, it's not really a problem as much as a different implementation.

    The EPS32 is using a different implementation of the Wire library. It has other return values that the one packaged with the Arduino software does not.

                    typedef enum {
                        I2C_ERROR_OK=0,
                        I2C_ERROR_DEV,      // 1
                        I2C_ERROR_ACK,     // 2
                        I2C_ERROR_TIMEOUT, // 3
                        I2C_ERROR_BUS,     // 4
                        I2C_ERROR_BUSY,    // 5
                        I2C_ERROR_MEMORY,  // 6
                        I2C_ERROR_CONTINUE,// 7
                        I2C_ERROR_NO_BEGIN // 8
                    } i2c_err_t;
    

    Error code 7 means the requests are queued. They haven't been sent. Anytime a call to Wire::EndTransmission is called with false on this implementation instead of actually sending a request the requests is just queued. When endTransmission is called with true as an argument (or with no qrgument) all of the requests are sent at once.

    Another implication of this difference in implementation is code that treats non-zero values as errors won't necessarily work properly since not all non-zero values are really error codes.

    For my case I can just use Wire::endTransmission(true). For others running into this problem your solution may require more considerations and possible changes in logic.