title: C I2C code to read sensor data from MPU9150 not working
body: <p>I am trying to read the MPU9150 sensor data over I2C using an LPC1343 microcontroller. I have developed the following C code, however, I receive zero when reading the value of say accelerometer X low bits. Here is my code:</p>
  <pre><code>/////////////// MPU9150 I2C CODE /////////////////////
   #define MPU9150_SELF_TEST_X        0x0D   // R/W
  #define MPU9150_SELF_TEST_Y        0x0E   // R/W
  #define MPU9150_SELF_TEST_Z        0x0F   // R/W
  #define MPU9150_SELF_TEST_A        0x10   // R/W
  #define MPU9150_SMPLRT_DIV         0x19   // R/W
  #define MPU9150_CONFIG             0x1A   // R/W
  #define MPU9150_GYRO_CONFIG        0x1B   // R/W
  #define MPU9150_ACCEL_CONFIG       0x1C   // R/W
  #define MPU9150_FF_THR             0x1D   // R/W
  #define MPU9150_FF_DUR             0x1E   // R/W
  #define MPU9150_MOT_THR            0x1F   // R/W
  #define MPU9150_MOT_DUR            0x20   // R/W
  #define MPU9150_ZRMOT_THR          0x21   // R/W
  #define MPU9150_ZRMOT_DUR          0x22   // R/W
  #define MPU9150_FIFO_EN            0x23   // R/W
  #define MPU9150_I2C_MST_CTRL       0x24   // R/W
  #define MPU9150_I2C_SLV0_ADDR      0x25   // R/W
  #define MPU9150_I2C_SLV0_REG       0x26   // R/W
  #define MPU9150_I2C_SLV0_CTRL      0x27   // R/W
  #define MPU9150_I2C_SLV1_ADDR      0x28   // R/W
  #define MPU9150_I2C_SLV1_REG       0x29   // R/W
  #define MPU9150_I2C_SLV1_CTRL      0x2A   // R/W
  #define MPU9150_I2C_SLV2_ADDR      0x2B   // R/W
  #define MPU9150_I2C_SLV2_REG       0x2C   // R/W
  #define MPU9150_I2C_SLV2_CTRL      0x2D   // R/W
  #define MPU9150_I2C_SLV3_ADDR      0x2E   // R/W
  #define MPU9150_I2C_SLV3_REG       0x2F   // R/W
  #define MPU9150_I2C_SLV3_CTRL      0x30   // R/W
  #define MPU9150_I2C_SLV4_ADDR      0x31   // R/W
  #define MPU9150_I2C_SLV4_REG       0x32   // R/W
  #define MPU9150_I2C_SLV4_DO        0x33   // R/W
  #define MPU9150_I2C_SLV4_CTRL      0x34   // R/W
  #define MPU9150_I2C_SLV4_DI        0x35   // R  
  #define MPU9150_I2C_MST_STATUS     0x36   // R
  #define MPU9150_INT_PIN_CFG        0x37   // R/W
  #define MPU9150_INT_ENABLE         0x38   // R/W
  #define MPU9150_INT_STATUS         0x3A   // R  
  #define MPU9150_ACCEL_XOUT_H       0x3B   // R  
  #define MPU9150_ACCEL_XOUT_L       0x3C   // R  
  #define MPU9150_ACCEL_YOUT_H       0x3D   // R  
  #define MPU9150_ACCEL_YOUT_L       0x3E   // R  
  #define MPU9150_ACCEL_ZOUT_H       0x3F   // R  
  #define MPU9150_ACCEL_ZOUT_L       0x40   // R  
  #define MPU9150_TEMP_OUT_H         0x41   // R  
  #define MPU9150_TEMP_OUT_L         0x42   // R  
  #define MPU9150_GYRO_XOUT_H        0x43   // R  
  #define MPU9150_GYRO_XOUT_L        0x44   // R  
  #define MPU9150_GYRO_YOUT_H        0x45   // R  
  #define MPU9150_GYRO_YOUT_L        0x46   // R  
  #define MPU9150_GYRO_ZOUT_H        0x47   // R  
  #define MPU9150_GYRO_ZOUT_L        0x48   // R  
  #define MPU9150_EXT_SENS_DATA_00   0x49   // R  
  #define MPU9150_EXT_SENS_DATA_01   0x4A   // R  
  #define MPU9150_EXT_SENS_DATA_02   0x4B   // R  
  #define MPU9150_EXT_SENS_DATA_03   0x4C   // R  
  #define MPU9150_EXT_SENS_DATA_04   0x4D   // R  
  #define MPU9150_EXT_SENS_DATA_05   0x4E   // R  
  #define MPU9150_EXT_SENS_DATA_06   0x4F   // R  
  #define MPU9150_EXT_SENS_DATA_07   0x50   // R  
  #define MPU9150_EXT_SENS_DATA_08   0x51   // R  
  #define MPU9150_EXT_SENS_DATA_09   0x52   // R  
  #define MPU9150_EXT_SENS_DATA_10   0x53   // R  
  #define MPU9150_EXT_SENS_DATA_11   0x54   // R  
  #define MPU9150_EXT_SENS_DATA_12   0x55   // R  
  #define MPU9150_EXT_SENS_DATA_13   0x56   // R  
  #define MPU9150_EXT_SENS_DATA_14   0x57   // R  
  #define MPU9150_EXT_SENS_DATA_15   0x58   // R  
  #define MPU9150_EXT_SENS_DATA_16   0x59   // R  
  #define MPU9150_EXT_SENS_DATA_17   0x5A   // R  
  #define MPU9150_EXT_SENS_DATA_18   0x5B   // R  
  #define MPU9150_EXT_SENS_DATA_19   0x5C   // R  
  #define MPU9150_EXT_SENS_DATA_20   0x5D   // R  
  #define MPU9150_EXT_SENS_DATA_21   0x5E   // R  
  #define MPU9150_EXT_SENS_DATA_22   0x5F   // R  
  #define MPU9150_EXT_SENS_DATA_23   0x60   // R  
  #define MPU9150_MOT_DETECT_STATUS  0x61   // R  
  #define MPU9150_I2C_SLV0_DO        0x63   // R/W
  #define MPU9150_I2C_SLV1_DO        0x64   // R/W
  #define MPU9150_I2C_SLV2_DO        0x65   // R/W
  #define MPU9150_I2C_SLV3_DO        0x66   // R/W
  #define MPU9150_I2C_MST_DELAY_CTRL 0x67   // R/W
  #define MPU9150_SIGNAL_PATH_RESET  0x68   // R/W
  #define MPU9150_MOT_DETECT_CTRL    0x69   // R/W
  #define MPU9150_USER_CTRL          0x6A   // R/W
  #define MPU9150_PWR_MGMT_1         0x6B   // R/W
  #define MPU9150_PWR_MGMT_2         0x6C   // R/W
  #define MPU9150_FIFO_COUNTH        0x72   // R/W
  #define MPU9150_FIFO_COUNTL        0x73   // R/W
  #define MPU9150_FIFO_R_W           0x74   // R/W
  #define MPU9150_WHO_AM_I           0x75   // R
  
  //MPU9150 Compass
  #define MPU9150_CMPS_XOUT_L        0x4A   // R
  #define MPU9150_CMPS_XOUT_H        0x4B   // R
  #define MPU9150_CMPS_YOUT_L        0x4C   // R
  #define MPU9150_CMPS_YOUT_H        0x4D   // R
  #define MPU9150_CMPS_ZOUT_L        0x4E   // R
  #define MPU9150_CMPS_ZOUT_H        0x4F   // R
  
  #define MPU9150_READBIT 0x01 
  
  // I2C address 0x69 could be 0x68 depends on your wiring. 
  int MPU9150_ADDRESS = 0x68;
  
  typedef enum
  {
    MPU9150_ERROR_OK = 0,                // Everything executed normally
    MPU9150_ERROR_I2CINIT = 1,               // Unable to initialise I2C
    MPU9150_ERROR_I2CBUSY = 2,               // I2C already in use
    MPU9150_ERROR_NOCONNECTION = 3,          // Unable to read device ID during init
    MPU9150_ERROR_LAST = 4
  }
  MPU9150Error_t;
  
  MPU9150Error_t MPU9150Init(void);
  MPU9150Error_t MPU9150GetDeviceID(uint8_t *id);
  MPU9150Error_t MPU9150GetXYZ(int16_t *accX, int16_t *accY, int16_t *accZ, int16_t *gyroX, int16_t *gyroY, int16_t *gyroZ);
  
  extern volatile uint8_t   I2CMasterBuffer[I2C_BUFSIZE];
  extern volatile uint8_t   I2CSlaveBuffer[I2C_BUFSIZE];
  extern volatile uint32_t  I2CReadLength, I2CWriteLength;
  
  static bool _MPU9150Initialised = false;
  
  /**************************************************************************/
  /*! 
      @brief  Sends a single command byte over I2C
  */
  /**************************************************************************/
  static MPU9150Error_t MPU9150Write8 (uint8_t reg, uint8_t value)
  {
    MPU9150Error_t error = MPU9150_ERROR_OK;
  
    // Clear write buffers
    uint32_t i;
    for ( i = 0; i &lt; I2C_BUFSIZE; i++ )
    {
      I2CMasterBuffer[i] = 0x00;
    }
  
    I2CWriteLength = 3;
    I2CReadLength = 0;
    I2CMasterBuffer[0] = MPU9150_ADDRESS;       // I2C device address
    I2CMasterBuffer[1] = reg;                   // Register
    I2CMasterBuffer[2] = value;
    i2cEngine();
  
    // ToDo: Add in proper I2C error-checking
    return error;
  }
  
  /**************************************************************************/
  /*! 
      @brief  Reads a 16 bit values over I2C
  */
  /**************************************************************************/
  static MPU9150Error_t MPU9150Read8(uint8_t reg, uint8_t *value)
  {
    MPU9150Error_t error = MPU9150_ERROR_OK;
  
    // Clear write buffers
    uint32_t i;
    for ( i = 0; i &lt; I2C_BUFSIZE; i++ )
    {
      I2CMasterBuffer[i] = 0x00;
    }
  
    I2CWriteLength = 2;
    I2CReadLength = 1;
    I2CMasterBuffer[0] = MPU9150_ADDRESS;         // I2C device address
    I2CMasterBuffer[1] = reg;                     // Command register
    // Append address w/read bit
    I2CMasterBuffer[2] = MPU9150_ADDRESS | MPU9150_READBIT;  
    i2cEngine();
  
    // Shift values to create properly formed integer
    *value = I2CSlaveBuffer[0];
  
    // ToDo: Add in proper I2C error-checking
    return error;
  }
  
  /**************************************************************************/
  /*! 
      @brief  Initialises the I2C block
  */
  /**************************************************************************/
  MPU9150Error_t MPU9150Init(void)
  {
    
    MPU9150Error_t error = MPU9150_ERROR_OK;
  
    // Initialise I2C
    if (i2cInit(I2CMASTER) == false)
    {
      return MPU9150_ERROR_I2CINIT;    /* Fatal error */
    }
  
    error = MPU9150Write8(MPU9150_PWR_MGMT_1, 0);
    //TODO - MPU9150_setupCompass(); if we want mag
  
    _MPU9150Initialised = true;
    return error;
  }
  
  /**************************************************************************/
  /*! 
      @brief  Gets the latest X/Y/Z values
  */
  /**************************************************************************/
  MPU9150Error_t MPU9150GetXYZ(int16_t *accX, int16_t *accY, int16_t *accZ, int16_t *gyroX, int16_t *gyroY, int16_t *gyroZ )
  {
    MPU9150Error_t error = MPU9150_ERROR_OK;
  
    uint8_t L = 0; uint8_t H = 0;
    
    error += MPU9150Read8(MPU9150_ACCEL_XOUT_L, &amp;L);
    error += MPU9150Read8(MPU9150_ACCEL_XOUT_H, &amp;H);
    *accX = (H&lt;&lt;8)+L; 
    
    error += MPU9150Read8(MPU9150_ACCEL_YOUT_L, &amp;L);
    error += MPU9150Read8(MPU9150_ACCEL_YOUT_H, &amp;H);
    *accY = (H&lt;&lt;8)+L;
    
    error += MPU9150Read8(MPU9150_ACCEL_ZOUT_L, &amp;L);
    error += MPU9150Read8(MPU9150_ACCEL_ZOUT_H, &amp;H);
    *accZ = (H&lt;&lt;8)+L;
    
    error += MPU9150Read8(MPU9150_GYRO_XOUT_L, &amp;L);
    error += MPU9150Read8(MPU9150_GYRO_XOUT_H, &amp;H);
    *gyroX = (H&lt;&lt;8)+L;
    
    error += MPU9150Read8(MPU9150_GYRO_YOUT_L, &amp;L);
    error += MPU9150Read8(MPU9150_GYRO_YOUT_H, &amp;H);
    *gyroY = (H&lt;&lt;8)+L;
    
    error += MPU9150Read8(MPU9150_GYRO_ZOUT_L, &amp;L);
    error += MPU9150Read8(MPU9150_GYRO_ZOUT_H, &amp;H);
    *gyroZ = (H&lt;&lt;8)+L;
    
    return error;
  }
  </code></pre>
  <p>And in my main function I am testing it as follows:</p>
  <pre><code>I2Cerr = MPU9150Init(); 
  
  //now in my while(1) loop:
  
  I2Cerr = MPU9150GetXYZ(&amp;aX, &amp;aY, &amp;aZ, &amp;gX, &amp;gY, &amp;gZ);
  uint8_t test = 55;
  I2Cerr =  MPU9150Read8(MPU9150_ACCEL_XOUT_L, &amp;test); //always reads 0 into &amp;arg???
  </code></pre>
  <p>For reference, the code base I started from is <a href="https://github.com/microbuilder/LPC1343CodeBase" rel="nofollow noreferrer">https://github.com/microbuilder/LPC1343CodeBase</a></p>
  <p>I am modifying an example I2C driver from an LPC example using the ADXL345 accelerometer: <a href="https://github.com/microbuilder/LPC1343CodeBase/blob/master/drivers/sensors/adxl345/adxl345.c" rel="nofollow noreferrer">https://github.com/microbuilder/LPC1343CodeBase/blob/master/drivers/sensors/adxl345/adxl345.c</a> as well as using MPU9150 specifics from this example Arduino code: <a href="http://playground.arduino.cc/Main/MPU-9150" rel="nofollow noreferrer">http://playground.arduino.cc/Main/MPU-9150</a></p>
  <p>This is a rather involved firmware question.</p>
  <h2>Edit</h2>
  <p>I am adding in the code for the i2cEngine() function:</p>
  <pre><code>uint32_t i2cEngine( void ) 
  {
    I2CMasterState = I2CSTATE_IDLE;
    RdIndex = 0;
    WrIndex = 0;
    if ( I2CStart() != TRUE )
    {
      I2CStop();
      return ( FALSE );
    }
  
    /* wait until the state is a terminal state */
    while (I2CMasterState &lt; 0x100);
  
    return ( I2CMasterState );
  }
  </code></pre>