Go Down

Topic: Meet a problem about reading data from MPU9150 based on Arduino DUE (Read 2979 times) previous topic - next topic


I wrote a program for reading date from MPU9150 based on UNO and everything was fine.
Recently I use DUE with the same program, but I receive nothing..
I don't where the problem is, could anyone help me?

Code: [Select]
//-----------------MPU Sensor Register define-------------
#define MPU9150_AD0 0x68
//data read only register
#define accelXHreg 0x3B
#define accelXLreg 0x3C
#define accelYHreg 0x3D
#define accelYLreg 0x3E
#define accelZHreg 0x3F
#define accelZLreg 0x40
#define tempH      0x41
#define tempL      0x42
#define gyroXHreg 0x43
#define gyroXLreg 0x44
#define gyroYHreg 0x45
#define gyroYLreg 0x46
#define gyroZHreg 0x47
#define gyroXLreg 0x48

//control r/w register
#define SELF_TEST_X     0x0D
#define SELF_TEST_Y     0x0E
#define SELF_TEST_Z     0x0F
#define SELF_TEST_A     0x10
#define SMPLRT_DIV      0x19    
#define CONFIG          0x1A
#define GYRO_CONFIG     0x1B
#define ACCEL_CONFIG    0x1C
#define FF_THR          0x1D
#define FF_DUR          0x1E

#define MOT_THR         0x1F
#define MOT_DUR         0x20

#define ZRMOT_THR       0x21
#define ZRMOT_DUR       0x22
#define FIFO_EN         0x23
#define I2C_MST_CTRL    0x24

#define I2C_SLV0_ADDR   0x25
#define I2C_SLV0_REG    0x26
#define I2C_SLV0_CTRL   0x27

#define I2C_SLV1_ADDR   0x28
#define I2C_SLV1_REG    0x29
#define I2C_SLV1_CTRL   0x2A

#define I2C_SLV2_ADDR   0x2B
#define I2C_SLV2_REG    0x2C
#define I2C_SLV2_CTRL   0x2D

#define I2C_SLV3_ADDR   0x2E
#define I2C_SLV3_REG    0x2F
#define I2C_SLV3_CTRL   0x30

#define I2C_SLV4_ADDR   0x31
#define I2C_SLV4_REG    0x32
#define I2C_SLV4_DO     0x33
#define I2C_SLV4_CTRL   0x34
#define I2C_SLV4_DI     0x35

#define I2C_MST_STATUS  0x36        //read
#define INT_PIN_CFG     0x37
#define INT_ENABLE      0x38
#define INT_STATUS      0x3A

#define MOT_DETECT_STATUS   0x61    //read

#define I2C_SLV0_DO     0x63
#define I2C_SLV1_DO     0x64
#define I2C_SLV2_DO     0x65
#define I2C_SLV3_DO     0x66

#define I2C_MST_DELAY_CTRL  0x67
#define SIGNAL_PATH_RESET   0x68
#define MOT_DETECT_CTRL     0x69

#define USER_CTRL       0x6A
#define PWR_MGMT_1      0x6B
#define PWR_MGMT_2      0x6C
#define FIFO_COUNTH     0x72
#define FIFO_COUNTL     0x73

#define FIFO_R_W        0x74
#define WHO_AM_I        0x75

// register map for magnet to meter
#define WIA             0x00    //magnet sensor ID
//global variable
unsigned char dataPack[14];
void setup()
 int error=0;
 pinMode(13, OUTPUT);
 //---who am i check
 //Serial.println(F("Done initial!"));
 //Serial.println(F("Waiting for your command..."));
void loop()
 uint8_t i;
 unsigned char AX_1;
 unsigned char AX_2;
 unsigned int AX_val;
 int signed_AX;
 float float_AX;
 float AX;
 unsigned char AY_1;
 unsigned char AY_2;
 unsigned int AY_val;
 int signed_AY;
 float float_AY;
 float AY;
 unsigned char AZ_1;
 unsigned char AZ_2;
 unsigned int AZ_val;
 int signed_AZ;
 float float_AZ;
 float AZ;
 unsigned char GX_1;
 unsigned char GX_2;
 unsigned int GX_val;
 int signed_GX;
 float float_GX;
 float GX;
 unsigned char GY_1;
 unsigned char GY_2;
 unsigned int GY_val;
 int signed_GY;
 float float_GY;
 float GY;
 unsigned char GZ_1;
 unsigned char GZ_2;
 unsigned int GZ_val;
 int signed_GZ;
 float float_GZ;
 float GZ;
   MPU9150_read (accelXHreg, (char *)&dataPack, 14);  //data will be put in the d
   AX_1 = dataPack[0];
   AX_2 = dataPack[1];
   AY_1 = dataPack[2];
   AY_2 = dataPack[3];
   AZ_1 = dataPack[4];
   AZ_2 = dataPack[5];
   GX_1 = dataPack[8];
   GX_2 = dataPack[9];
   GY_1 = dataPack[10];
   GY_2 = dataPack[11];
   GZ_1 = dataPack[12];
   GZ_2 = dataPack[13];
   AX_val = AX_1 * 256 + AX_2;
   AY_val = AY_1 * 256 + AY_2;
   AZ_val = AZ_1 * 256 + AZ_2;
   GX_val = GX_1 * 256 + GX_2;
   GY_val = GY_1 * 256 + GY_2;
   GZ_val = GZ_1 * 256 + GZ_2;
   signed_AX = int(AX_val);
   float_AX = float(signed_AX);
   signed_AY = int(AY_val);
   float_AY = float(signed_AY);
   signed_AZ = int(AZ_val);
   float_AZ = float(signed_AZ);
   //-------------------------------signed_AX = int(AX_val);
   signed_GX = int(GX_val);
   float_GX = float(signed_GX);
   signed_GY = int(GY_val);
   float_GY = float(signed_GY);
   signed_GZ = int(GZ_val);
   float_GZ = float(signed_GZ);
   AX = float_AX * 8 / 65535;  
   AY = float_AY * 8 / 65535;  
   AZ = float_AZ * 8 / 65535;  
   GX = float_GX * 1000 / 65535;  
   GY = float_GY * 1000 / 65535;  
   GZ = float_GZ * 1000 / 65535;
//-------------------------READ----Multiple read--------------------//i2c auto increase reg_add
int MPU9150_read(int reg_first_addr, char *buffer, int size)
 int i, n, error;
 n = Wire.write(reg_first_addr);     if (n != 1)  return (-10);
 n = Wire.endTransmission(false);    if (n != 0)  return (n);
 Wire.requestFrom(MPU9150_AD0, size, true);  // Third parameter is true: relase I2C-bus after data is read.
 i = 0;
 while(Wire.available() && i<size)
 if ( i != size)  return (-11);
 return (0);  // return : no error
//-------------------------WHO AM I-----------------
void MPU9150_Who_Am_I()
 int error=0;
 char c;
 error = MPU9150_read (WHO_AM_I, &c, 1);
 Serial.print(F("WHO_AM_I : "));
 Serial.print(F(", error = "));
int MPU9150_write(int reg_addr, const uint8_t *pData, int size)
 int n, error;
 n = Wire.write(reg_addr);    
 if (n != 1) return (-20);
 n = Wire.write(pData, size);
 if (n != size) return (-21);
 error = Wire.endTransmission(true);
 if (error != 0)
 return (error);  
 return (0);        
int MPU9150_write_reg(int reg, uint8_t data)
 int error;
 error = MPU9150_write(reg, &data, 1);
 return (error);
void MPU9150_Init(void)
 //  No sleep, set clock source PLL with gyroX ----important
   MPU9150_write_reg(SMPLRT_DIV, 0x07);            //

   MPU9150_write_reg(CONFIG, 0b00000001);          //set Lowpass filter DLPF_CFG=1

   MPU9150_write_reg(GYRO_CONFIG, 0b00010000);     //disable gyro self test, set gyro range +-1000 deg/sec ASF_SEL=1

   MPU9150_write_reg(ACCEL_CONFIG, 0b00001001);    //disable accel self test, set range +-4g AFS_SEL=1 // high_pass_filter 5Hz

   MPU9150_write_reg(FF_THR,0x00);     //free fall threshold =0

   MPU9150_write_reg(FF_DUR, 0x00);    //free fall duration

   MPU9150_write_reg(MOT_THR,0x00);    //motion detection threshold =0 ---------important

   MPU9150_write_reg(MOT_DUR,0x00);    //motion detection duration =0

   MPU9150_write_reg(ZRMOT_THR,0x00);  //zero motion detection threshold =0;

   MPU9150_write_reg(ZRMOT_DUR,0x00);  //zero motion detection duration =0

   MPU9150_write_reg(FIFO_EN,0x00);    //disable all sensor go to FIFO ----------inportant

//Auxiliary i2c setup


   MPU9150_write_reg(INT_ENABLE,0x00);    //disable all interupt-------------------important




Wire.endTransmission(False) is the problem.  It's different for the DUE (in its current form).

Search this forum for these issues.

Be prepared to do some coding...



The problem is that the Due Wire library (1.5.4R2) does not support repeated starts. As stated by chriskner, the Due Wire library ignores the false in Wire.endTransmission(False) statement. In the UNO, MEGA and other 8 bits AVR MCU's, a repeated start was fudged by doing an incomplete write (without the stop) and then immediately doing a read. In the ARM based AVRs this is not possible as a write will never complete without its stop. Fortunately the underlying Atmel SAM TWI library that is used by Wire does support repeated starts. It requires the addition of a new function to the Wire library , Wire.cpp, to expose the underlying TWI function and its function prototype in Wire.h.
The Wire.cpp and Wire.h Wire are located at:

Add to Wire.cpp:
Code: [Select]

// Added function to provide repeated starts
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t reg_address, uint8_t reg_address_length) {
if (quantity > BUFFER_LENGTH)
quantity = BUFFER_LENGTH;

// perform blocking read into buffer
int readed = 0;
    TWI_StartRead(twi, address, reg_address, reg_address_length);  // request register and read
do {
// Stop condition must be set during the reception of last byte
if (readed + 1 == quantity)
TWI_SendSTOPCondition( twi);

TWI_WaitByteReceived(twi, RECV_TIMEOUT);
rxBuffer[readed++] = TWI_ReadByte(twi);
} while (readed < quantity);
TWI_WaitTransferComplete(twi, RECV_TIMEOUT);

// set rx buffer iterator vars
rxBufferIndex = 0;
rxBufferLength = readed;

return readed;

Add to Wire.h:
Code: [Select]

uint8_t requestFrom(uint8_t , uint8_t , uint8_t , uint8_t); // allow repeated starts and multi-byte reg addresses

To use the new function replace:
Code: [Select]

  n = Wire.write(reg_first_addr);     if (n != 1)  return (-10);
  n = Wire.endTransmission(false);    if (n != 0)  return (n);
  Wire.requestFrom(MPU9150_AD0, size, true);  // Third parameter is true: relase I2C-bus after data is read.

Code: [Select]

Wire.requestFrom(MPU9150_AD0, size, reg_first_addr ,1);

The last function parameter allows multi-byte register addresses, in most cases it will be set to 1.

Go Up