2018-05-22 03:59 AM
I'm trying to do a compass using an LSM303DLHC sensor embedded in STM32F3 Discovery. I have prepared such a code which provides declaration and reading data from both accelerometer and magnetometer
void LSM303DLHCAcc_Config(void)
{LSM303DLHCAcc_InitStructure.AccFull_Scale = LSM303DLHC_NORMAL_MODE;
LSM303DLHCAcc_InitStructure.AccOutput_DataRate = LSM303DLHC_ODR_200_HZ;
LSM303DLHCAcc_InitStructure.Axes_Enable = LSM303DLHC_AXES_ENABLE;
LSM303DLHCAcc_InitStructure.BlockData_Update = LSM303DLHC_BlockUpdate_Continous;
LSM303DLHCAcc_InitStructure.Endianness = LSM303DLHC_BLE_MSB;
LSM303DLHCAcc_InitStructure.High_Resolution = LSM303DLHC_HR_ENABLE;
LSM303DLHCAcc_InitStructure.Power_Mode = LSM303DLHC_BOOT_NORMALMODE;
LSM303DLHC_AccInit(&LSM303DLHCAcc_InitStructure);}
void LSM303DLHCAcc_Read(float *convertedData_Acc)
{ uint8_t i, XYZ[6] = {0};LSM303DLHC_Read(ACC_I2C_ADDRESS,LSM303DLHC_OUT_X_L_A, XYZ, 1);
LSM303DLHC_Read(ACC_I2C_ADDRESS,LSM303DLHC_OUT_X_H_A, XYZ+1, 1);
LSM303DLHC_Read(ACC_I2C_ADDRESS,LSM303DLHC_OUT_Y_L_A, XYZ+2, 1);
LSM303DLHC_Read(ACC_I2C_ADDRESS,LSM303DLHC_OUT_Y_H_A, XYZ+3, 1);
LSM303DLHC_Read(ACC_I2C_ADDRESS,LSM303DLHC_OUT_Z_L_A, XYZ+4, 1);
LSM303DLHC_Read(ACC_I2C_ADDRESS,LSM303DLHC_OUT_Z_H_A, XYZ+5, 1);
for(i=0;i<3;i++)
{
convertedData_Acc[i] = (float) ((int16_t)((uint16_t)XYZ[2*i+1] << 8) + XYZ[2*i])/16;
}
}
void LSM303DLHCMag_Config(void)
{LSM303DLHCMag_InitStructure.Temperature_Sensor = LSM303DLHC_TEMPSENSOR_DISABLE;
LSM303DLHCMag_InitStructure.MagFull_Scale = LSM303DLHC_FS_1_9_GA;
LSM303DLHCMag_InitStructure.MagOutput_DataRate = LSM303DLHC_ODR_220_HZ;
LSM303DLHCMag_InitStructure.Working_Mode = LSM303DLHC_CONTINUOS_CONVERSION;
LSM303DLHC_MagInit(&LSM303DLHCMag_InitStructure);}
void LSM303DLHCMag_Read(float *convertedData_Mag)
{uint8_t XYZ[6] = {0};
LSM303DLHC_Read(MAG_I2C_ADDRESS,LSM303DLHC_OUT_X_H_M, XYZ, 1);
LSM303DLHC_Read(MAG_I2C_ADDRESS,LSM303DLHC_OUT_X_L_M, XYZ+1, 1);
LSM303DLHC_Read(MAG_I2C_ADDRESS,LSM303DLHC_OUT_Y_H_M, XYZ+2, 1);
LSM303DLHC_Read(MAG_I2C_ADDRESS,LSM303DLHC_OUT_Y_L_M, XYZ+3, 1);
LSM303DLHC_Read(MAG_I2C_ADDRESS,LSM303DLHC_OUT_Z_H_M, XYZ+4, 1);
LSM303DLHC_Read(MAG_I2C_ADDRESS,LSM303DLHC_OUT_Z_L_M, XYZ+5, 1);
convertedData_Mag[0] = (float) ((int16_t)(((uint16_t)XYZ[0] << 8) + XYZ[1]))/16;
convertedData_Mag[1] = (float) ((int16_t)(((uint16_t)XYZ[2] << 8) + XYZ[3]))/16;
convertedData_Mag[2] = (float) ((int16_t)(((uint16_t)XYZ[4] << 8) + XYZ[5]))/16;}
I'm not sure if I did the reading function properly. I'm getting data, but I don't know how to convert it further to be able to calculate the azimuth. Should I divide them by sensitivity or what? I can't find such an information in the datasheet
#lsm303dlhc2018-05-22 11:48 AM
To convert raw data into acceleration in g and magnetic field in gauss you have use the sensitivity. defined in datasheet.
Basicaly for acceleration you multiply the raw value by sensitivity (LA_So) for magnetometer you divide the raw value (M_GN).
To calculate heading to the magnetic North you can use our
library which you can find in package.2018-05-23 06:40 AM
Thank you for your response.
I have divided the raw data from the magnetometer
convertedData_Mag[0] = (float) ((int16_t) ((XYZ[0] << 8) + XYZ[1]))/LSM303DLHC_M_SENSITIVITY_XY_1_9Ga;
convertedData_Mag[1] = (float) ((int16_t) ((XYZ[2] << 8) + XYZ[3]))/LSM303DLHC_M_SENSITIVITY_XY_1_9Ga; convertedData_Mag[2] = (float) ((int16_t) ((XYZ[4] << 8) + XYZ[5]))/LSM303DLHC_M_SENSITIVITY_Z_1_9Ga;and multiplied the raw data from accelerometer (I selected 2g sensitivity)
for(i=0;i<3;i++)
{ convertedData_Acc[i] = (float) ((int16_t) ((XYZ[2*i+1] << 8) + XYZ[2*i])) * 2.0f; }and I'm getting such results
I think there's something wrong with accelerometer. Magnetometers values seem to be good.
2018-05-23 08:42 AM
I've added another question below instead of adding it in reply to your comment
2018-05-25 02:29 AM
The accelerometer value need to be divided by 16, because it is 12-bit value left adjusted in 16-bit register.
And I see another problem in your latest code, you have case the type of XYZ to uint16_t before you do the shift (<<8) as you did it in the first version.