Skip to main content
Niccolò Ferrari
Associate
May 30, 2017
Question

LSM303AGR mems reading problems.

  • May 30, 2017
  • 1 reply
  • 1766 views
Posted on May 30, 2017 at 11:39

I'm working on LSM303AGR mems and I've some reading problems: when I read x, y, z accelerometer registers in 'normal mode' I get lots of 0 and sometimes a correct value (z value have to be about 1G, not 0), when I set 'low-power' mode everything works good.

Any ideas?

Thank you.

NF

P.S. Attached I leave two example: work.png is in 'low-power mode', the other is in 'normal mode'.

#mems #i2c #accelerometer #sensor #lsm303agr #read
This topic has been closed for replies.

1 reply

ST Employee
May 30, 2017
Posted on May 30, 2017 at 13:19

Can you share your source code?

Niccolò Ferrari
Associate
May 31, 2017
Posted on May 31, 2017 at 00:19

Here the code:

int main() {

    uint64_t i = 0;

    int16_t dx = 0, dy = 0, dz = 0;

    byte data = 0x00, b = 0x00, hx = 0x00, lx = 0x00, hy = 0x00, ly = 0x00, hz = 0x00, lz = 0x00;

    double fx = 0., fy = 0., fz = 0.;

    single_write(LSM303AGR_ACC_CTRL_REG1, 0x27);            //write single byte on register

    single_write(LSM303AGR_ACC_CTRL_REG2, 0x00);

    single_write(LSM303AGR_ACC_CTRL_REG3, 0x00);

    single_write(LSM303AGR_ACC_CTRL_REG4, 0x80);

  

    wait(1);

    

    while(1){

        b = single_read(LSM303AGR_ACC_STATUS_REG2);

        if(b&0x01) {

            lx = single_read(LSM303AGR_ACC_OUT_X_L);

            hx = single_read(LSM303AGR_ACC_OUT_X_H);

            dx = (int16_t)((uint16_t)(((uint16_t)hx)<<8+((uint16_t)lx)));

            fx = (double)(2. / 32768.) * (double)dx;

            pc.printf('\tX READY: x=%d\t\t\tfx=%lf\r\n', dx, fx);

        }

        if(b&0x02) {

            ly = single_read(LSM303AGR_ACC_OUT_Y_L);

            hy = single_read(LSM303AGR_ACC_OUT_Y_H);

            dy = (int16_t)((uint16_t)(((uint16_t)hy)<<8+((uint16_t)ly)));

            fy = (double)(2. / 32768.) * (double)dy;

            pc.printf('\tY READY: y=%d\t\t\tfy=%lf\r\n', dy, fy);

        }

        if(b&0x04) {

            lz = single_read(LSM303AGR_ACC_OUT_Z_L);

            hz = single_read(LSM303AGR_ACC_OUT_Z_H);

            dz = (int16_t)((uint16_t)(((uint16_t)hz)<<8+((uint16_t)lz)));

            fz = (double)(2. / 32768.) * (double)dz;

            pc.printf('\tZ READY: z=%d\t\t\tfz=%lf\r\n', dz, fz);

        }

        wait(0.01);

        i++;

    }

}
ST Employee
June 1, 2017
Posted on June 01, 2017 at 10:11

The problem is in the following line 

dx = (int16_t)((uint16_t)(((uint16_t)hx)<<8+((uint16_t)lx))); brackets are missing around the shift. So if the lx, ly, lz is not zero, which is the case of 'normal mode' you shift the value out of the int16 range.

Use following code

   dx = (int16_t)((uint16_t)((((uint16_t)hx)<<8)+((uint16_t)lx)));

or much simpler

   dx = ((int16_t)hx<<8)+(uint16_t)lx;