2017-10-21 8:12 PM
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 !2017-11-23 1:21 AM
Please follow the self-test procedure as described in
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.
2017-11-23 7:48 AM
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]=00X 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:2017-11-23 9:18 AM
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.
2017-11-23 7:48 PM
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; }}2017-12-21 6:02 AM
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!
We’re moving the ST Community to a new platform to give you a better and more reliable community experience.