2018-01-24 12:54 AM
Hi,
I am working on LIS3DH accelerometer sensor, I have interfaced this sensor with STM32F103 series micro controller using SPI interface. When I read X, Y and Z acceleration values, I get some random readings and it too fluctuate lot. The sensor is placed horizontal on PCB, parallel to X , Y axis and perpendicular to Z axis. The reading for all three axes is fluctuate around 0.01 to -0.15. In initialization, all three axes has been enabled.
As I am very new to accelerometer sensor, is my understanding that in the position mentioned above should I get g value for X and Y axis around 0g and for Z axis around 1g correct?
OR it just shows fluctuations in X,Y and Z axis value when there is some movement of sensor and again it get stable value when the sensor is stationary?
2018-01-24 01:41 AM
Yes, you first assumption is correct. For the the mentioned position X and Y axis should be close to 0g and Z axis around 1g.
Can you please share your sensor configuration and the procedure how do you convert raw value to acceleration in g unit?
2018-01-24 02:00 AM
Thank you so much for your response. Please refer below details.
/* accelerometer register address define */
#define Status_Reg1 ((u8)0x07)#define Who_Am_I ((u8)0x0F)#define Ctrl_Reg1 ((u8)0x20)#define Ctrl_Reg2 ((u8)0x21)#define Ctrl_Reg3 ((u8)0x22)#define Ctrl_Reg4 ((u8)0x23)#define Ctrl_Reg5 ((u8)0x24)#define Ctrl_Reg6 ((u8)0x25)#define Status_Reg2 ((u8)0x27)#define Out_X_L ((u8)0x28)#define Out_X_H ((u8)0x29)#define Out_Y_L ((u8)0x2A)#define Out_Y_H ((u8)0x2B)#define Out_Z_L ((u8)0x2C)#define Out_Z_H ((u8)0x2D)#define INT1_CFG ((u8)0x30)#define INT1_SRC ((u8)0x31)#define INT1_THS ((u8)0x32)#define INT1_DURATION ((u8)0x33)#define CLICK_CFG ((u8)0x38)#define CLICK_SRC ((u8)0x39)#define CLICK_THS ((u8)0x3A)#define TIME_LIMIT ((u8)0x3B)#define TIME_LATENCY ((u8)0x3C)#define TIME_WINDOW ((u8)0x3D)Below is the sensor configuration at power up.
/* Ask who am I to comfirm the hardware status */
retCode =ACCELEROMETER_Read(Who_Am_I,&tmp); if((tmp == 0x33) && (retCode == 0)) { MEMS_DEVICE.HardWareSta = DEF_MEMS_NONE_ERR; retCode =0; #if(DEF_ADDINFO_OUTPUTEN > 0) printf('[ACC]:OK!\r\n'); #endif } else { MEMS_DEVICE.HardWareSta = DEF_MEMS_DEVICE_ERR; retCode =-1; #if(DEF_ADDINFO_OUTPUTEN > 0) printf('[ACC]:Error!\r\n'); #endif }if(MEMS_DEVICE.HardWareSta != DEF_MEMS_DEVICE_ERR)
{ ACCELEROMETER_Write(Ctrl_Reg1,0x57);//0101:normal/low power mode (100Hz),0:normal mode,111:XYZ enable. //ACCELEROMETER_Read(Ctrl_Reg1,&tmp); ACCELEROMETER_Write(Ctrl_Reg2,0x89);//high pass filter enable //ACCELEROMETER_Read(Ctrl_Reg2,&tmp); ACCELEROMETER_Write(Ctrl_Reg3,0x00);//disable INT //ACCELEROMETER_Read(Ctrl_Reg3,&tmp); ACCELEROMETER_Write(Ctrl_Reg4,0x08);//2: Full scale selection +/- 2G High resolution enable //ACCELEROMETER_Read(Ctrl_Reg4,&tmp); ACCELEROMETER_Write(Ctrl_Reg5,0x00);//INT1 IO not latched //ACCELEROMETER_Read(Ctrl_Reg5,&tmp); ACCELEROMETER_Write(Ctrl_Reg6,0x02);//INT1 IO active low(??) //ACCELEROMETER_Read(Ctrl_Reg6,&tmp); ACCELEROMETER_Write(INT1_DURATION,0x00);//set INT1 mode OR, high event //ACCELEROMETER_Read(INT1_DURATION,&tmp); ACCELEROMETER_Write(INT1_CFG,0x2A);//set INT1 mode OR, high and low event 0X3F //ACCELEROMETER_Read(INT1_CFG,&tmp); }Below is are INT1 threshold value as per user configuration stored in non volatile memory.
BSP_ACCELEROMETER_SetInt1Threshold(s_Cfg.accMThreshold, 2000);
BSP_ACCELEROMETER_SetInt1Duration(s_Cfg.accMDuration, 2000);
g value calculation function.
s8 BSP_ACCELEROMETER_ReadXYZ(MEMS_data_Typedef *MEMS_data,u16 timeout)
{ s8 retCode=0; u8 X_data_h=0,X_data_l=0,Y_data_h=0,Y_data_l=0,Z_data_h=0,Z_data_l=0,tmp=0; s16 tmpdata=0;double x_acc = 0, y_acc = 0,z_acc = 0;
ACCELEROMETER_Read(Out_X_L,&X_data_l); ACCELEROMETER_Read(Out_X_H,&X_data_h); // read Y data ACCELEROMETER_Read(Out_Y_L,&Y_data_l); ACCELEROMETER_Read(Out_Y_H,&Y_data_h); // read Z data ACCELEROMETER_Read(Out_Z_L,&Z_data_l); ACCELEROMETER_Read(Out_Z_H,&Z_data_h);/* calculate the data */
tmpdata = X_data_l; tmpdata |= (X_data_h << 8); MEMS_data->X_data = tmpdata;tmpdata = Y_data_l;
tmpdata |= (Y_data_h << 8); MEMS_data->Y_data = tmpdata;tmpdata = Z_data_l;
tmpdata |= (Z_data_h << 8); MEMS_data->Z_data = tmpdata;x_acc = ((double)MEMS_data->X_data)/16380;
y_acc = ((double)MEMS_data->Y_data)/16380; z_acc = ((double)MEMS_data->Z_data)/16380; printf('\r\n[ACC]:X=%lf, Y=%lf, Z=%lf', x_acc,y_acc,z_acc); return retCode;}2018-01-24 03:07 AM
OK,
you enabled the High pass filter ACCELEROMETER_Write(Ctrl_Reg2,0x89);//high pass filter enable
In this case you will see only changes in the acceleration, in other words, it will remove any DC value like 1g gravity.
2018-01-24 04:29 AM
After disabling high pass filter, I am able to get g value as expected.
Thank you so much for your solution.
2018-01-24 08:13 PM
Hi Vishal, Can you share how you convert raw data into g value? And what is the configuration of registers settings? Thanks for your time.
2018-01-24 09:10 PM
Cast the signed integer to a float and scale based on the full-scale-deflection mode selected.
Pick a range based on what you expect to be measuring so you get the finest granularity measurements.
2018-01-24 11:20 PM
Hi Clive, my controller is not having FPU(Floating point unit) so only integer support. Could you provide the equation for raw data into g value for +-2g scale? Thanks.
2018-01-25 08:44 AM
You don't need an FPU to do floating point math, and you say you want units in G, not mG
float x = (float)X * 0.001f; // in G where 12-bit signed sample, and +/-2G range
2018-01-28 10:05 PM
Thank you Clive. So, as per your response. I have to put raw value into the equation to get the data into G unit. Am I right? or If I want to use 8-bit or 10-bit output sample than according to Mechanical characteristic table value from datasheet I have to replace 0.001 value to its respective value. Am I right?