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
Posted on November 23, 2017 at 09:21

Please follow the self-test procedure as described in

http://www.st.com/content/ccc/resource/technical/document/application_note/77/ed/e7/e1/28/5a/45/d6/CD00290365.pdf/files/CD00290365.pdf/jcr:content/translations/en.CD00290365.pdf

 in chapter 12.

I see following problems in your code:

- You are not discarding first samples

- It seems you are not checking data ready status, so you may read the same sample several times

- You should wait at least 90ms after enabling the self-test

Difference between self-test 0 and 1 is in sign of the change during self-test.

Posted on November 23, 2017 at 15:48

Thanks a lot ! I now met a new problem , I use high pass filter on X,Y,Z axis , but  it work well only  on X,Y axis  .It does not work  on Z axis  . The initializtion code listed below : 

status_t LIS3DH_Init_base(void)

{

//HF

LIS3DH_WriteReg(LIS3DH_CTRL_REG2, 0x08); //09

/* enable the accelerometer */

LIS3DH_SetODR(LIS3DH_ODR_100Hz); //10ms

/* set low power mode and 8 bit resolution, start the measruements */

LIS3DH_SetMode(LIS3DH_NORMAL);

/* full scale = 2g */

LIS3DH_SetFullScale(LIS3DH_FULLSCALE_2);

/* Enable block data update, so unread previous data will just be dismissed */ // !!!

/* enable all axes */

LIS3DH_SetAxis(LIS3DH_X_ENABLE | LIS3DH_Y_ENABLE | LIS3DH_Z_ENABLE);

LIS3DH_ReadReg(LIS3DH_REFERENCE_REG, &temp_data);

return MEMS_SUCCESS;

}

the data listed below:

--- without HPF:

X Y Z

-40, -28, 1080:

-32, -28, 1044:

-40, -24, 1076:

-36, -16, 1004:

-32, -28, 1040:

-36, -28, 1068:

-28, -32, 1052:

-40, -28, 1028:

-48, -24, 988:

-36, -32, 1056:

--- HPF :nomal HPCF[2:1]=00

X Y Z

-4, -4, 1064:

-8, 4, 1068:

4, 4, 1116:

-16, -4, 1056:

4, -4, 1032:

-4, -12, 1088:

12, 8, 1088:

16, 4, 1064:

4, -4, 1116:

-4, 4, 1108:
Posted on November 23, 2017 at 17:18

Maybe you are resetting the high pass filter to quickly after enabling the X, Y, Z axis. I would try to add some delay between these two functions.

Another solution could be to use HPM[1:0] = 10.

Posted on November 24, 2017 at 03:48

according to the self test procedure in AN3308,  the difference between  OUT_NOST and  OUT_ST is very big . It can't pass self test  even 1 time while testing 10 times.

code and the testing value  listed below :

uint8_t ACC_selftest(void)

{

uint8_t i,acc_status;

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;

Delay(0x4000); //100ms

i =0;

do {

LIS3DH_GetStatusReg(&acc_status);

}while (!(acc_status & 0x08 ));

LIS3DH_GetAccAxesRaw(&acc_data[i]);

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

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

{

do {

LIS3DH_GetStatusReg(&acc_status);

}while (!(acc_status & 0x08 ));

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;

LIS3DH_WriteReg(LIS3DH_CTRL_REG4, 0x82);

Delay(0x8000); //100ms

i =0;

do {

LIS3DH_GetStatusReg(&acc_status);

}while (!(acc_status & 0x08 ));

LIS3DH_GetAccAxesRaw(&acc_data[i]);

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

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

{

do {

LIS3DH_GetStatusReg(&acc_status);

}while(!(acc_status & 0x08 ));

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;

}

}0690X00000608wbQAA.png
Posted on December 21, 2017 at 14:02

Dear sir, now I want achieve tilt remedy function. I did as the following:

1,tilt the sensor with a constant angle.

2, In initialization function:

set ODR,set mode nomal ,set full scale(+/-2g),enable x,y,z axis,

set LIS3DH_CTRL_REG2=0x48 ( HPM[1:0]=[01],Reference signal for filtering),set REFERENCE =0;

set THR = 2。enable X and Y interrupt . enable IA1 to INT1 .

3, In tilt remedy function:

check IA interrupt flag;

if IA interrupt occured , set THR with THR+1.

loop up line until interrupt not occured.

set the REFERENCE regesiter with the value of current THR ,

resume the THR register with value 2.

by now , IA interrupt should not occured. because the the difference between the input acceleration and the content of

REFERENCE is 0. but actually the IA interrupt always occured. How to resolve it?

Thanks!