cancel
Showing results for 
Search instead for 
Did you mean: 

LSM303AGR accelerometer readings problem

V. Gaillot
Associate
Posted on April 19, 2017 at 14:25

Hi all,

I'm trying to interface a LSM303AGR, to get the magnetometer and accelerometer values in I2C.

The component is responding well to whoami requests (both compass and magnetometer parts), I manage to get mag values but the accelerometer values seems to be stuck.

Here are my init parameters:

   

/*

REBOOT

ACCELEROMETER

MEMORY

CONTENT

*/

   

I2C_Write_reg

(

I2C2

,

I2C_LSM3_ACC_ADRESS

<<

1

,

I2C_LSM3_CTRL_REG5_A

,

0x80

);

   

RTC_wait_ms

(

6

);

   

/*

REBOOT

MAGNETOMETER

MEMORY

CONTENT

*/

   

I2C_Write_reg

(

I2C2

,

I2C_LSM3_MAG_ADRESS

<<

1

,

I2C_LSM3_CFG_REG_A_M

,

0x40

);

   

RTC_wait_ms

(

6

);

   

(

void

)

I2C_Read

(

I2C2

,

I2C_LSM3_ACC_ADRESS

<<

1

,

0

,

I2C_LSM3_WHO_AM_I_ACC

,

&

whoamiacc

,

1

);

   

if

(

whoamiacc

!=

0x33

)

FAIL

(

'LSM303AGR

accelerometer

side

isn't

responding'

);

   

else

{

       

/*

ACCELEROMETER

INITIALIZATIONS

*/

       

I2C_Write_reg

(

I2C2

,

I2C_LSM3_ACC_ADRESS

<<

1

,

I2C_LSM3_CTRL_REG1_A

,

0x57

);

       

I2C_Write_reg

(

I2C2

,

I2C_LSM3_ACC_ADRESS

<<

1

,

I2C_LSM3_CTRL_REG2_A

,

0x00

);

       

I2C_Write_reg

(

I2C2

,

I2C_LSM3_ACC_ADRESS

<<

1

,

I2C_LSM3_CTRL_REG3_A

,

0x00

);

       

I2C_Write_reg

(

I2C2

,

I2C_LSM3_ACC_ADRESS

<<

1

,

I2C_LSM3_CTRL_REG4_A

,

0x98

);

//BDU

ON

+/-4G

Range

and

High

res

ON

       

I2C_Write_reg

(

I2C2

,

I2C_LSM3_ACC_ADRESS

<<

1

,

I2C_LSM3_CTRL_REG5_A

,

0x00

);

   

}

   

(

void

)

I2C_Read

(

I2C2

,

I2C_LSM3_MAG_ADRESS

<<

1

,

0

,

I2C_LSM3_WHO_AM_I_MAG

,

&

whoamimag

,

1

);

   

if

(

whoamimag

!=

0x40

)

FAIL

(

'LSM303AGR

magnetometer

side

isn't

responding'

);

   

else

{

       

/*

MAGNETOMETER

INITIALIZATIONS

*/

       

I2C_Write_reg

(

I2C2

,

I2C_LSM3_MAG_ADRESS

<<

1

,

I2C_LSM3_CFG_REG_A_M

,

0x8C

);

   

//

   

I2C_Write_reg(I2C2,I2C_LSM3_MAG_ADRESS

<<

1,I2C_LSM3_CFG_REG_B_M,0x02);

   

}

My reading fonction for the accelerometer is the following:

   

uint8_t

drdy

=

0

;

   

uint8_t

x_accel

[

2

]

=

{

0

};

   

uint8_t

y_accel

[

2

]

=

{

0

};

   

uint8_t

z_accel

[

2

]

=

{

0

};

   

I2C_Read

(

I2C2

,

I2C_LSM3_ACC_ADRESS

<<

1

,

0

,

I2C_LSM3_STATUS_REG_A

,

&

drdy

,

1

);

   

if

((

drdy

&

0x01

)

==

0x01

)

I2C_Read

(

I2C2

,

I2C_LSM3_ACC_ADRESS

<<

1

,

0

,

I2C_LSM3_OUT_Y_L_A

,

y_accel

,

2

);

   

if

((

drdy

&

0x02

)

==

0x02

) I2C_Read

(

I2C2

,

I2C_LSM3_ACC_ADRESS

<<

1

,

0

,

I2C_LSM3_OUT_Z_L_A

,

z_accel

,

2

);

   

if

((

drdy

&

0x04

)

==

0x04

)

I2C_Read

(

I2C2

,

I2C_LSM3_ACC_ADRESS

<<

1

,

0

,

I2C_LSM3_OUT_X_L_A

,

x_accel

,

2

);

I get the exact same answer at every reading:

x_accel

[

0

]

= 0xA0

x_accel

[

1

]

= 0xA0

y_accel

[

0

]

= 0xC0

y_accel

[

1

]

= 0xC0

z_accel

[

0

]

= 0x40

z_accel

[

1

]

= 0x40

Am I doing something wrong in the initializations? I would like the accelerometer to be in +/-4G range, 100Hz, without FIFO and in High res mode.

The I2C_Read function seems to work well, my function reading the magnetometer works fine.

Thank you!

3 REPLIES 3
Miroslav BATEK
ST Employee
Posted on April 19, 2017 at 21:25

I think, the address of output registers is not automaticaly incremented, when you are reading multiple bytes. So you are reading only the low byte and due to enabled BDU, the data are not updated. Please check chapter 6.1.1 in datasheet.

If the MSb of the

register address

is ‘1’, the register address is automatically increased to allow multiple data read/writes.

You can also check only the ZYXDA bit in status register a then read data for all axis in one multiple read, read 6bytes starting from OUT_X_L_A (28h).

Miroslav BATEK
ST Employee
Posted on April 20, 2017 at 10:03

I think if the High and Low bytes are the same, then you are reading the same register.

Can you please set the MSB bit of registers address to one, so I2C_LSM3_OUT_X_L_A = 0xA8, I2C_LSM3_OUT_Y_L_A = 0xAA, I2C_LSM3_OUT_Y_L_A = 0xAC to be sure the address will be incremented.

Another option how to confirm my theory is disable BDU in CTRL_REG4, then the values should change even if you don't read High byte of output register.

Posted on April 20, 2017 at 09:32

Hi Miroslav,

Thank you for your time. My function to read the magnetometer values is very similar to the one I use for the accelerometer:

void

read_LSM303AGR_mag

(

float

*

MAG_XYZ_AXIS

){

   

int16_t

MAG_XYZ_AXIS_raw

[

3

]

=

{

0

};

   

uint8_t

drdy

=

0

;

   

uint8_t

x_mag

[

2

]

=

{

0

};

   

uint8_t

y_mag

[

2

]

=

{

0

};

   

uint8_t

z_mag

[

2

]

=

{

0

};

   

I2C_Read

(

I2C2

,

I2C_LSM3_MAG_ADRESS

<<

1

,

0

,

I2C_LSM3_STATUS_REG_M

,

&

drdy

,

1

);

   

if

((

drdy

&

0x01

)

==

0x01

){

       

I2C_Read

(

I2C2

,

I2C_LSM3_MAG_ADRESS

<<

1

,

0

,

I2C_LSM3_OUTX_L_REG_M

,

x_mag

,

2

);

       

MAG_XYZ_AXIS_raw

[

0

]=

(

x_mag

[

1

]

<<

8

)

|

x_mag

[

0

];

       

/*

Convert

to

Gauss

*/

       

MAG_XYZ_AXIS

[

0

]

=

(

float

)

MAG_XYZ_AXIS_raw

[

0

]*

1.5

/

1000

;

   

}

   

if

((

drdy

&

0x02

)

==

0x02

){

       

I2C_Read

(

I2C2

,

I2C_LSM3_MAG_ADRESS

<<

1

,

0

,

I2C_LSM3_OUTY_L_REG_M

,

y_mag

,

2

);

       

MAG_XYZ_AXIS_raw

[

1

]=

(

y_mag

[

1

]

<<

8

)

|

y_mag

[

0

];

       

/*

Convert

to

Gauss

*/

       

MAG_XYZ_AXIS

[

1

]

=

(

float

)

MAG_XYZ_AXIS_raw

[

1

]*

1.5

/

1000

;

   

}

   

if

((

drdy

&

0x04

)

==

0x04

){

       

I2C_Read

(

I2C2

,

I2C_LSM3_MAG_ADRESS

<<

1

,

0

,

I2C_LSM3_OUTZ_L_REG_M

,

z_mag

,

2

);

       

MAG_XYZ_AXIS_raw

[

2

]=

(

z_mag

[

1

]

<<

8

)

|

z_mag

[

0

];

       

/*

Convert

to

Gauss

*/

       

MAG_XYZ_AXIS

[

2

]

=

(

float

)

MAG_XYZ_AXIS_raw

[

2

]*

1.5

/

1000

;

   

}

}

This one is working perfectly, the address is auto-incremented and I get correct results. I tried to only read once the ZYXDA bit, and do one reading per byte as it wasn't auto-incremented, and I get the same result as above (same value for H & L bytes of each axis). I don't really get what's happening there, it looks like the sensor is stuck and always send the same value, but it should be at least a different values for High and Low bytes.