2018-05-22 01:59 PM
Hi,
I'm currently trying to use the MotionEC library for an E-Compass application, and to calibrate the Magnetometer with the MotionMC library. I'm using an STM32L1-DISCO with an LSM303AGR. My general idea is to run the calibration algorithm for x seconds, then get the calibration parameters, and apply them to the e-compass calculation.
The MotionEC library works perfectly fine but I ran into troubles with the MotionMC library.
At first, I'm running the MotionMC_Update function with the parameters I'm reading from the Magnetometer. After that, I'm calling MotionMC_GetCalParams to get the calibration parameters. But the library is always returning the following default values:
HI_Bias = {0, 0, 0},
SF_Matrix = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}},
CalQuality = MMC_CALQSTATUSUNKNOWN
Here is my code (based on the ST examples).
// COMPASS_REPORT_INTERVAL = 20
// gets called every 20ms
void doCalibrationStep()
{ SensorAxes_t mag_data_uncompensated; getMagneto(&mag_data_uncompensated);MMC_Input_t data_in;
data_in.Mag[0] = (float) mag_data_uncompensated.AXIS_X / 10.0f; data_in.Mag[1] = (float) mag_data_uncompensated.AXIS_Y / 10.0f; data_in.Mag[2] = (float) mag_data_uncompensated.AXIS_Z / 10.0f;data_in.TimeStamp = timestamp * COMPASS_REPORT_INTERVAL;
// example data_in: Mag = {-64, 5.5, 17.1000004}, TimeStamp = 0
MotionMC_Update(&data_in);MMC_Output_t data_out;
MotionMC_GetCalParams(&data_out);dbg('CalParams X: %f, Y: %f, Z: %f, Quality: %d\r\n', data_out.HI_Bias[0], data_out.HI_Bias[1],
data_out.HI_Bias[2], data_out.CalQuality); // everything has default values, no matter how often I run the algotimestamp++;
}
void doCalibration()
{ MotionMC_Initialize(COMPASS_REPORT_INTERVAL, 1); char lib_version[200];MotionMC_GetLibVersion(lib_version);
dbg(lib_version); // here the correct version is printed<doCalibrationStep() is called repeatedly in 20ms intervals until x seconds elapsed>
MotionMC_GetCalParams(&cal_params); // all parameters are zero
}
I have absolutely no clue what's wrong. Do I miss something?
Thanks
2018-05-23 12:30 PM
Did you rotate the sensor slowly in a figure eight pattern through 3D space?
Or you can rotate it along each axis.
After this movement you should get the calibration value.
2018-06-10 05:21 AM
I did not have time in the last few weeks to look at this issue, but found time today to investigate further.
For users that might encounter this problem:
The problem, was/is that the calibration algorithm has to run quite often before one can read calibration values. Depending on the interval, this takes some time, in my case >10 seconds. I ran the calibration algorithm for a few seconds only and, thus, did not get results.
2024-03-19 07:58 AM
Hi,
I'm facing the same issue. Does anyone resolve this ?
I'm using a Nucleo F401RE board and a STEVAL -MKI172V1 board ( dev board for the LSM303AGR sensor).
My hardware is good (I can acces the lsm303agr register)
I init the MotionMc fucntion with a 200ms sample time. I set up a timer for over count every 200ms.I can read the firmware version of the lib
debug_init(&huart2);
lsm303agr_init(&lsm303agr,&hi2c1);
lsm303agr_setup_magnetometer(&lsm303agr);
lsm303agr_setup_accelerometer(&lsm303agr);
MotionMC_Initialize(LSM303AGR_MAGNETOMETER_CALIBRATION_SAMPLE_TIME, 1);
char motion_mc_version[35] = {0};
MotionMC_GetLibVersion(motion_mc_version);
printf("motion mc version : %s \n",motion_mc_version);
HAL_TIM_Base_Start_IT(&htim10);
I set up the lsm303agr magnetometer as follow
//0b100001100 = 0x8C
//COMP_TEMP_EN = 1 -> mag temp compensation enabled
//REBOOT = 0 -> reboot memory content disabled
//SOFT_RST = 0 -> soft reset disabled
//LP = 0 -> low power mode disabled
//ODR[1:0] = 0x11 -> 100Hz
//MD[1:0] = 0x00 -> continous mode
lsm303agr_write_register(lsm303agr,LSM303AGR_CFG_REG_A_M,0x8C);
//0b00000010 = 0x02
//OFF_CAN_ONE_SHOT = 0 -> offset cancelation in single mode disabled
//INT_on_Data_OFF = 0 -> interutp block recognition do not checks data after HI correction to discover the interupt
//set_FREQ = 0 -> frequency of the pulse is set to every 63 ODR
//OFF_CANC = 1 -> offset cancelation enabled
//LPF = 0 -> low pass filter disabled
lsm303agr_write_register(lsm303agr,LSM303AGR_CFG_REG_B_M,0x02);
//0b00010000 = 0x10
//INT_MAG_PIN = 0 -> interupt signal is not driven on INT_MAG_PIN
//I2C_DIS = 0 -> I2C is enabled
//BDU = 1 -> protection over wrong data enabled
//BLE = 0 -> LSB and MSB not inverted
//SELF_TEST = 0 -> self test disabled
//INT_MAG = 0 -> DRDY pin is not configure as GPIO Output
lsm303agr_write_register(lsm303agr,LSM303AGR_CFG_REG_C_M,0x10);
//set delay to let time to power up
HAL_Delay(LSM303AGR_DELAY_MAGNETOMETER_POWER_UP);
Then I call the following function every 200ms
if (token_200ms){
HAL_GPIO_WritePin(TEST_PIN_GPIO_Port, TEST_PIN_Pin,GPIO_PIN_SET);
lsm303agr_magnetometer_run_calib(&lsm303agr);
HAL_GPIO_WritePin(TEST_PIN_GPIO_Port, TEST_PIN_Pin,GPIO_PIN_RESET);
token_200ms = 0;
}
lsm303agr_status_t lsm303agr_magnetometer_run_calib(lsm303agr_t *lsm303agr)
{
//increment time count
lsm303agr->calib_time_count++;
MMC_Input_t data_in;
MMC_Output_t data_out;
// Get magnetic field X/Y/Z
lsm303agr_read_mag_output_register(lsm303agr);
data_in.Mag[0] = lsm303agr_mag_val_to_uT(lsm303agr->mag.x);
data_in.Mag[1] = lsm303agr_mag_val_to_uT(lsm303agr->mag.y);
data_in.Mag[2] = lsm303agr_mag_val_to_uT(lsm303agr->mag.z);
// Get current sample time in [ms]
data_in.TimeStamp = lsm303agr->calib_time_count * LSM303AGR_MAGNETOMETER_CALIBRATION_SAMPLE_TIME;
// Magnetometer calibration algorithm update
MotionMC_Update(&data_in);
// Get the magnetometer calibration coefficients
MotionMC_GetCalParams(&data_out);
}
// @brief TIM callback
// @PAram TIM which trig the callback
// @return None
//---------------------------------------------------------------------------------------------------------------------
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
if (htim->Instance == TIM10) { //200ms
token_200ms = 1;
}
}
I tried to run the algo more than 1min rotating the sensor slowly but nothing happened I always got 0 for the bias and an Identity matrice for the SF
thanks