cancel
Showing results for 
Search instead for 
Did you mean: 

MotionMC calibration fails (all params have default value)

kedopofe kedopofe
Associate II
Posted on May 22, 2018 at 22:59

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 algo

    timestamp++;

}

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

3 REPLIES 3
Miroslav BATEK
ST Employee
Posted on May 23, 2018 at 21:30

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.

kedopofe kedopofe
Associate II
Posted on June 10, 2018 at 14:21

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.

Pierre Castera
Associate II

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