cancel
Showing results for 
Search instead for 
Did you mean: 

LIS3D :the calculation---Puzzling problem in AN3308.

dehai wo
Associate II
Posted on October 22, 2017 at 05:12

       I have found a puzzling problem while I reading the document AN3308,On page 17,table 9.In my opinion, 1g come from the formula : a = (0x4000 -> 0x400 = 1024)*2000mg/2048.So get the correct value : 1g , In the same way, 350mg should come from: a = (Ox15e0 -> 0x15e = 350)*2000mg/2048 , but the calculation is 341.8,not equal to 350.

       Another problem is that I have received 12bit data(so as: OxFFF0...) from LIS3DH while I config it working in normal mode (10 bit)

      Anyone can help me explain it ?  thanks !
14 REPLIES 14
Miroslav BATEK
ST Employee
Posted on October 23, 2017 at 10:13

The conversion is done in following way:

acceleration_mg = raw_data_LSB * sensitivity, the value read from output registers must be shifted right according to selected mode (8, 10, 12 bit)

The sensitivity for all combination of mode and full scale can be found in datasheet in table 4.

The FIFO stores 10-bit values.

Posted on October 24, 2017 at 14:07

Thank you very much!

Posted on October 25, 2017 at 10:47

When I use your arithmetic   , the acceleration values  I get are a little big than before , all values are

greater than 1000mg @ Z axis

:(the sensor is  aclinic,

motionless)

acceleration data(mg):

 X     Y      Z

-19, 28, 1018:

-19, 27, 1025:

-26, 26, 1011:

-24, 29, 1012:

-26, 32, 1012:

-30, 32, 1006:

-32, 30, 1008:

-20, 32, 1009:

-27, 31, 1030:

-30, 31, 1028:

-31, 29, 1011:

-22, 35, 1023:

-30, 30, 1018:

-27, 33, 1019:

-29, 29, 1007:

-31, 27, 1027:

-26, 30, 1025:

-34, 33, 1014:

-33, 27, 1016:

-31, 27, 1005:

-29, 32, 1018:

-18, 35, 1035:

-32, 31, 1029:

-33, 26, 1033:

-29, 22, 1028:

-33, 26, 1023:

-35, 28, 1035:

-24, 29, 1031:

-31, 30, 1027:

-32, 30, 1012:

-36, 39, 1012:

-42, 32, 1036:

average data:

-28, 29, 1020:

How to explain this phenomenon?

another problem is that the first value reading from LIS3DH is always abnormal , how to solve this problem?

Posted on October 25, 2017 at 13:59

The sensor is not perfect and is has an offset, according to the datasheet the typical offset can be from -40mg to +40mg. So your values are in line with the specification.

0690X00000608fXQAQ.png

Concerning the first invalid sample, do you respect the turn-on time? Do you wait enough time after turn-on before reading the output values?

Posted on October 26, 2017 at 01:10

How to calibrate the error  caused by the  offset? Is there some sulutions ?

Posted on October 26, 2017 at 09:41

You can calibrate the offset and gain error in your software (firmware) using 6-point calibration.

The 6-point calibration is described in design tip

http://www.st.com/content/ccc/resource/technical/document/design_tip/group0/28/fa/7d/ed/6a/41/4f/c1/DM00253745/files/DM00253745.pdf/jcr:content/translations/en.DM00253745.pdf

.

The 6-point calibration is available as a part of

http://www.st.com/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32cube-embedded-software-expansion/x-cube-mems1.html

library in X-CUBE-MEMS1 software package.
dehai wo
Associate II
Posted on November 20, 2017 at 08:38

Thank you very much!  But now I met another tough problem: when I enable X,Y,Z axis, and enable all interrupts ( X_H,X_L,Y_H,Y_L,Z_H,Z_L ) , LIS3DH can not generate interrupt completely . While if I 

only enable  one  of  the six  interrupts (such us X_H, or Z_L...) , or two or three of  of the six interrupts (such as X_H,Y_H,Z_L) ,then it work fine. How to resolve this problem? thanks .

Posted on November 20, 2017 at 10:18

If you enable X_H interrupt, the interrupt is triggered if the absolute value of acceleration in X axis will be higher then threshold.

If you enable X_L interrupt, the interrupt is triggered if the absolute value of acceleration in X axis will be lower then threshold.

So enabling both X_H and X_L conditions doesn't make sense because the interrupt will be triggered all the time.

Posted on November 23, 2017 at 04:12

Now I see.

About self test , I  have tested my  sensor , 10 times self testing , only 2~3 times successful, my self test code listed below , is there some thing wrong in the code?

 Self-test0 �?self-test 1  is be mentioned on  page 37 of the datasheet , what is the difference of 

self-test0  and self-test 1 ? thanks�?

uint8_t ACC_selftest(void)

{

uint8_t i;

int16_t Gx_no_st,Gy_no_st,Gz_no_st,Gx_st,Gy_st,Gz_st,ST_x,ST_y,ST_z;

AxesRaw_t acc_data[32];

//---InitializeSensor,turn on sensor,enableX/Y/Zaxes.?SetBDU=1,FS=2G, NormalMode,ODR=50Hz

if (!(LIS3DH_WriteReg(0x21, 0x00)))

return MEMS_ERROR;

if (!(LIS3DH_WriteReg(0x22, 0x00)))

return MEMS_ERROR;

if (!(LIS3DH_WriteReg(0x23, 0x80))) //A0

return MEMS_ERROR;

if (!(LIS3DH_WriteReg(0x20, 0x47))) //6F

return MEMS_ERROR;

// GYRO is in power down mode after power up

//set the control register (24h) to Cut-Off Frequency = 50Hz

// Write(0x24, 0x02);

// set the control register (23h) to ±2000dps FS, self-test0 mode with BDU bit enabled

//Write(0x23, 0xA0);

// set the control register (20h) to 200Hz ODR with X/Y/Z axis enabled.

//Write(0x20, 0x6F);

//Wait for 800mS for the gyroscope to be stabilized [2]

Delay(0x2000);

// read the gyroscope data 5 times in self-test0 mode

for (i = 0; i < 5; i++)

{

LIS3DH_GetAccAxesRaw(&acc_data[i]);

}

// average the raw data

Gx_no_st = (acc_data[0].AXIS_X + acc_data[1].AXIS_X + acc_data[2].AXIS_X + acc_data[3].AXIS_X + acc_data[4].AXIS_X) / 5;

Gy_no_st = (acc_data[0].AXIS_Y + acc_data[1].AXIS_Y + acc_data[2].AXIS_Y + acc_data[3].AXIS_Y + acc_data[4].AXIS_Y) / 5;

Gz_no_st = (acc_data[0].AXIS_Z + acc_data[1].AXIS_Z + acc_data[2].AXIS_Z + acc_data[3].AXIS_Z + acc_data[4].AXIS_Z) / 5;

// enable self-test 0 at +/-2000dps FS with BDU enabled, Wait for 60mS for the gyroscope to be stabilized

//Write(0x23, 0xA2);

//REG4:---selftest'

LIS3DH_SetSelfTest(LIS3DH_SELF_TEST_0);

// read the gyroscope data 5 times in self-test0 mode

for (i = 0; i < 5; i++)

{

LIS3DH_GetAccAxesRaw(&acc_data[i]);

}

// average the raw data

Gx_st = (acc_data[0].AXIS_X + acc_data[1].AXIS_X + acc_data[2].AXIS_X + acc_data[3].AXIS_X + acc_data[4].AXIS_X) / 5;

Gy_st = (acc_data[0].AXIS_Y + acc_data[1].AXIS_Y + acc_data[2].AXIS_Y + acc_data[3].AXIS_Y + acc_data[4].AXIS_Y) / 5;

Gz_st = (acc_data[0].AXIS_Z + acc_data[1].AXIS_Z + acc_data[2].AXIS_Z + acc_data[3].AXIS_Z + acc_data[4].AXIS_Z) / 5;

// calculate the absolute self-test values of with self-test minus without self-test

ST_x = abs(Gx_st - Gx_no_st);

ST_y = abs(Gy_st - Gy_no_st);

ST_z = abs(Gz_st - Gz_no_st);

//

if ((ST_x <= 360) && (ST_y <= 360) && (ST_z <= 360) && (ST_x >= 17) && (ST_y >= 17) && (ST_z >= 17)){ // 60mg,17,360 need be chaeck !!!!!

//The gyroscope passes;

return MEMS_SUCCESS;

}

else{

//The gyroscope fails;

return MEMS_ERROR;

}

}