LSM303D accelerometer readings

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