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:
/////////////// 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 < 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 < 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, &L);
error += MPU9150Read8(MPU9150_ACCEL_XOUT_H, &H);
*accX = (H<<8)+L;
error += MPU9150Read8(MPU9150_ACCEL_YOUT_L, &L);
error += MPU9150Read8(MPU9150_ACCEL_YOUT_H, &H);
*accY = (H<<8)+L;
error += MPU9150Read8(MPU9150_ACCEL_ZOUT_L, &L);
error += MPU9150Read8(MPU9150_ACCEL_ZOUT_H, &H);
*accZ = (H<<8)+L;
error += MPU9150Read8(MPU9150_GYRO_XOUT_L, &L);
error += MPU9150Read8(MPU9150_GYRO_XOUT_H, &H);
*gyroX = (H<<8)+L;
error += MPU9150Read8(MPU9150_GYRO_YOUT_L, &L);
error += MPU9150Read8(MPU9150_GYRO_YOUT_H, &H);
*gyroY = (H<<8)+L;
error += MPU9150Read8(MPU9150_GYRO_ZOUT_L, &L);
error += MPU9150Read8(MPU9150_GYRO_ZOUT_H, &H);
*gyroZ = (H<<8)+L;
return error;
}
And in my main function I am testing it as follows:
I2Cerr = MPU9150Init();
//now in my while(1) loop:
I2Cerr = MPU9150GetXYZ(&aX, &aY, &aZ, &gX, &gY, &gZ);
uint8_t test = 55;
I2Cerr = MPU9150Read8(MPU9150_ACCEL_XOUT_L, &test); //always reads 0 into &arg???
For reference, the code base I started from is https://github.com/microbuilder/LPC1343CodeBase
I am modifying an example I2C driver from an LPC example using the ADXL345 accelerometer: https://github.com/microbuilder/LPC1343CodeBase/blob/master/drivers/sensors/adxl345/adxl345.c as well as using MPU9150 specifics from this example Arduino code: http://playground.arduino.cc/Main/MPU-9150
This is a rather involved firmware question, so many thanks for any help on what could be going wrong.
EDIT - adding in the code for the i2cEngine() function:
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 < 0x100);
return ( I2CMasterState );
}
i2cEngine()
? It seems suspicious to me that inMPU9150Read8()
you setI2CWriteLength = 2
but then you loadI2CMasterBuffer[]
with three bytes. Doesi2cEngine()
send that third byte for the read operation? – kkrambo