Skip to main content
Visitor II
May 22, 2018
Question

MotionMC calibration fails (all params have default value)

  • May 22, 2018
  • 3 replies
  • 2480 views
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

    This topic has been closed for replies.

    3 replies

    ST Employee
    May 23, 2018
    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.

    Visitor II
    June 10, 2018
    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.

    Visitor II
    March 19, 2024

    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