2017-10-21 08: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 01: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 07: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 09: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 07: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 06: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!