Hi guys,
I’m working on a digital compass project and we decided to use LSM303D 3D accelerometer and 3D magnetometer module and the PCB design has already done by engineers which is previously working in our company.
I’m having problems understanding the readings from LSM303D. Here is my 10 readings from sensors in x-, y-, z-axis when PCB board is laying down on my desk. As you see the values are not varying to much as there is no force acting to PCB and changes in acceleration should be zero.
Ax | Ay | Az |
-------------------
65342 71 4167
65346 68 4161
65353 61 4167
65351 71 4181
65343 63 4145
65347 67 4185
65334 73 4179
65354 70 4153
65364 71 4152
65337 76 4170
First of all I was expecting to read zero acceleration in x and y direction and 1g in z direction as the placement of LSM303D in PCB layout indicates. I know these sensor readings should be scaled by a conversion factor which is associated with selected sensitivity of LSM303D accelerometer to read the sensor output in units of g.
In my case conversion factor is 0.244 mg/LSB for ±8g sensitivity as indicated in LSM303D datasheet. After scaling Ay seems very near to zero but Ax is quite away from zero.
Any suggestions, ideas will be welcomed.
Thanks in advance,
Torehan
Hello, Torehan.
I am sorry you are having problems using your LSM303D module. Are you using our LSM303D carrier? Could you tell us more about your setup? What are you using to communicate with the sensor and how are you reading the data? I suspect that you might be interpreting the readings as unsigned numbers instead of signed. Could you post pictures of your setup?
- Jeremy
Hi Jeremy,
I’m not using your Pololu LSM303D carrier. Actually whole PCB (see attachment) was designed by one of out engineers in our company who quit a couple of months ago.
I use I2C protocol to communicate with the sensor and reading data procedure is implemented as indicated in datasheet. I have my own I2C protocol libraries to read/write data from any kind of sensor or device. The source code of read subroutine is given below.
struct SensorRawData {
uint8_t x_lo;
uint8_t x_hi;
uint8_t y_lo;
uint8_t y_hi;
uint8_t z_lo;
uint8_t z_hi;
};
struct Vector3 {
uint16_t x;
uint16_t y;
uint16_t z;
};
typedef struct Vector3 AccVec ;
AccVec LSM303D_RReadAcc(){
struct SensorRawData AccRawData;
AccVec AccRawVec;
AccRawData.x_lo = PALS_I2C_Read(I2C1,LSM303D_READ_ADDR,LSM303D_OUT_X_L_A);
AccRawData.x_hi = PALS_I2C_Read(I2C1,LSM303D_READ_ADDR,LSM303D_OUT_X_H_A);
AccRawData.y_lo = PALS_I2C_Read(I2C1,LSM303D_READ_ADDR,LSM303D_OUT_Y_L_A);
AccRawData.y_hi = PALS_I2C_Read(I2C1,LSM303D_READ_ADDR,LSM303D_OUT_Y_H_A);
AccRawData.z_lo = PALS_I2C_Read(I2C1,LSM303D_READ_ADDR,LSM303D_OUT_Z_L_A);
AccRawData.z_hi = PALS_I2C_Read(I2C1,LSM303D_READ_ADDR,LSM303D_OUT_Z_H_A);
AccRawVec.x = (AccRawData.x_hi << 8) | AccRawData.x_lo;
AccRawVec.y = (AccRawData.y_hi << 8) | AccRawData.y_lo;
AccRawVec.z = (AccRawData.z_hi << 8) | AccRawData.z_lo;
return AccRawVec;
};
//I2C reading subroutines
uint8_t PALS_I2C_Read(I2C_TypeDef* I2Cx, uint8_t address, uint8_t reg) {
uint8_t received_data;
PALS_I2C_Start(I2Cx, address, I2C_Direction_Transmitter, 0);
PALS_I2C_WriteData(I2Cx, reg);
PALS_I2C_Stop(I2Cx);
PALS_I2C_Start(I2Cx, address, I2C_Direction_Receiver, 0);
received_data = PALS_I2C_ReadNoAck(I2Cx);
return received_data;
}
uint8_t PALS_I2C_ReadNoAck(I2C_TypeDef* I2Cx) {
uint8_t data;
I2C_AcknowledgeConfig(I2Cx, DISABLE);
I2C_GenerateSTOP(I2Cx, ENABLE);
PALS_I2C_Timeout = PALS_I2C_TIMEOUT;
while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED) && PALS_I2C_Timeout) {
PALS_I2C_Timeout--;
}
data = I2C_ReceiveData(I2Cx);
return data;
}
Actually your are right about your suspicion. I’m reading the data to a unsigned integer variables.
Should I read the registers as signed integers variables? By the way should I have to calibrate the accelerometer to read the correct values?
Torehan
You should interpret the readings as signed numbers. In general, you should not need to calibrate the accelerometer to get good results but calibrating might still help. You might refer to our Arduino library for the LSM303D for an example of how to read the sensor.
- Jeremy
Hi Jeremy,
Thank you very much for your help. Now I am interpereting to read sensor data in signed integer and everything seem OK.
Here is my ten successive readings from accelerometer in units of G.
Ax Ay Az
G : -0.0466 0.0137 1.0219
G : -0.0481 0.0161 1.0185
G : -0.0456 0.0137 1.0221
G : -0.0473 0.0144 1.0194
G : -0.0478 0.0166 1.0192
G : -0.0471 0.0159 1.0211
G : -0.0483 0.0176 1.0211
G : -0.0468 0.0134 1.0182
G : -0.0495 0.0137 1.018
G : -0.0478 0.0166 1.0192
By the way the sensitivity of the sensor data is quite convincing for most of the cases but in my opinion for a high precision application recalibration of accelerometer is crucial as factory calibration may be corrupted from soldering process. While soldering, applied temperature on the sensor may damage previous factory calibration.
See you next,
Torehan
Thanks for letting us know. I am glad you got it working.
- Jeremy