cancel
Showing results for 
Search instead for 
Did you mean: 

LSM303AGR mems reading problems.

Niccolò Ferrari
Associate II
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
4 REPLIES 4
Miroslav BATEK
ST Employee
Posted on May 30, 2017 at 13:19

Can you share your source code?

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++;

    }

}
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;

Posted on June 01, 2017 at 11:11

Thank you very much,

I was going crazy

only for two

brackets

!

Thank you, problem solved!