06-08-2022 01:25 PM
BNO055 unreliable calibration & heading readings
I'm having difficulty with reliable heading in DNOF mode. I find it can drifts as much as +/- 20 degrees.
There are many questions I have regarding this. But, as they are all related, I will put them all here in a number list:
1. Power cycling calibration status
I find power cycling effects the accuracy / reliability of the calibration status.
2. Power cycling heading reading
I find power cycling effects the accuracy / reliability of the heading reading.
Always powered-up
I have changed my design to try the compass always powered-up while the battery is connected. This makes an improvement in both cases above, but this is not how I want the design.
I even put the compass into suspend mode on power-down & then back into normal mode at power-up.
3. When / how often should the calibration data to read / restored?
If I have to adopt the always powered-up approach, then the compass will be powered for long periods of time. How often should I read the OFFSET & RADIUS registers into NV storage?
4. Heading drift
I find that the heading drifts. IF I orient the compass in one direction, not change any compass settings, but just turn thru 360 degrees, or move the compass in some random way, the heading can be up to 30 degrees wrong.
5. Absolute heading
I find that the compass does not point north to match my magnetic compass, of my iPhone compass. (NB my magnetic compass & iPhone compass match each other photos attached)
This is was a fully calibrated BNO055 with all 4 CALIB STAT read 3’s
Solved! Go to Solution.
06-09-2022 08:12 AM
Hi Digisolve,
If current sensor status is suspend mode or power-down, and you want to reuse the sensor, it is recommended that you do soft reset for sensor and wait for tens of milliseconds before configuring the sensor.
Test it and see if it has improvement.
06-09-2022 10:46 AM - edited 06-09-2022 11:06 AM
Please can you be more specific as I find if I reset & configure the device from power moved, restore the cal data (OFFSET & RADIUS regs) then the CAL STATUS usually starts back at 0x00 & the heading readings are completely wrong showing 0 degrees regardness of the direction it's pointing
If I run my BNO055_sleep(TRUE) instead of removing power from the BNO055 & then run BNO055_sleep(FALSE) I get much better results. However, Ideally I want to remove the power completely when not in use to maximise the battery life.
When the battery is insterted I run BNO055_init() & BNO055_sleep(TRUE). This puts the unit in an off state, but still with the BNO055 powered-up
When the user turns the unit on I run BNO055_sleep(FALSE) & start to use the unit.
However, I find from a battery instartion, I need to always calibrate as the CAL STATUS is usually 0x00 (then soon changes to 0x30 as the GYRO cals quite quickly) but never 0xFF
Once calibrated I can place in suspend power mode then back to normal power mode & the cal status & heading readings restore too.
This is a very slow process for tech support, so a comprehensive responce would be greatly appreciated
Here is my code (sorry but pasting it in lost the tabulation):
void bno055_init(void)
{
Delay(TICK_100MS);
COMPASS_RESET = 0;
Delay(TICK_10MS);
COMPASS_RESET = 1;
Delay(7*TICK_100MS); // wait compass POR
/* switch back to page 0 */
BNO055_I2C_Write(BNO055_PAGE_ID_ADDR, PAGE0);
// Delay(TICK_10MS);
/* read chip IDs (for debug only)*/
BNO055_I2C_Read(BNO055_CHIP_ID_ADDR);
BNO055_I2C_Read(BNO055_ACCEL_REV_ID_ADDR);
BNO055_I2C_Read(BNO055_MAG_REV_ID_ADDR);
BNO055_I2C_Read(BNO055_GYRO_REV_ID_ADDR);
BNO055_I2C_Read(BNO055_SW_REV_ID_LSB_ADDR);
BNO055_I2C_Read(BNO055_SW_REV_ID_MSB_ADDR);
BNO055_I2C_Read(BNO055_BL_REV_ID_ADDR);
/* Wait till restart */
while(BNO055_I2C_Read(BNO055_SELFTEST_RESULT_ADDR) != 0x0F )
{
Delay(TICK_10MS);
}
/* Set to config mode */
BNO055_I2C_Write(BNO055_OPR_MODE_ADDR, BNO055_OPERATION_MODE_CONFIG);
/* Set to normal power mode */
BNO055_I2C_Write(BNO055_PWR_MODE_ADDR, BNO055_POWER_MODE_NORMAL);
/* Set the output units */
BNO055_I2C_Write(BNO055_UNIT_SEL_ADDR, 0x00);
// use external clock //
BNO055_I2C_Write(BNO055_SYS_TRIGGER_ADDR, 0x80);
Delay(TICK_10MS);
while(BNO055_I2C_Read(BNO055_SYS_CLK_STAT_ADDR) & 1)
{
Delay(TICK_10MS);
}
if((BNO055_I2C_Read(BNO055_SYS_TRIGGER_ADDR) & 0x80) == 0)
while(1); // !!! EXTERNAL CLOCK SELECTION FAILED
/* Set the axis map */
BNO055_I2C_Write(BNO055_AXIS_MAP_CONFIG_ADDR, xyz_table[XYZ_MODE].map);
BNO055_I2C_Write(BNO055_AXIS_MAP_SIGN_ADDR, xyz_table[XYZ_MODE].sign);
// Load calibration Profile //
if(inhibit_profile == TRUE)
{
inhibit_profile = FALSE;
}
else
{
BNO055_Load_Calibration_Profile();
}
/* Set the requested operating mode (see section 3.3) */
BNO055_I2C_Write(BNO055_OPR_MODE_ADDR, OPERATION_MODE);
Delay(TICK_10MS);
}
void BNO055_sleep(BOOL sleep_flg)
{
if(sleep_flg)
{
BNO055_I2C_Write(BNO055_OPR_MODE_ADDR, BNO055_OPERATION_MODE_CONFIG);
Delay(3*TICK_10MS);
BNO055_I2C_Write(BNO055_PWR_MODE_ADDR, BNO055_POWER_MODE_SUSPEND);
}
else
{
BNO055_I2C_Write(BNO055_PWR_MODE_ADDR, BNO055_POWER_MODE_NORMAL);
BNO055_I2C_Write(BNO055_OPR_MODE_ADDR, OPERATION_MODE);
Delay(TICK_10MS);
}
Delay(TICK_10MS);
}
void BNO055_Load_Calibration_Profile(void)
{
S16 profile_data[sizeof(NvBuff.CompassProfile)/sizeof(NvBuff.CompassProfile[0])];
U8 flash_loop ;
for(flash_loop = 0; flash_loop < sizeof(profile_data)/sizeof(profile_data[0]); flash_loop++)
{
profile_data[flash_loop] = NvBuff.CompassProfile[flash_loop];
}
BNO055_I2C_Write(BNO055_OPR_MODE_ADDR, BNO055_OPERATION_MODE_CONFIG);
Delay(3*TICK_10MS);
BNO055_I2C_WriteArray(BNO055_CAL_DATA_START, (U8*)profile_data, sizeof(profile_data));
BNO055_I2C_Write(BNO055_OPR_MODE_ADDR, OPERATION_MODE);
Delay(TICK_10MS);
}
06-14-2022 03:13 PM
Please can I get some feedback. My client is chasing me daily. Thank you
06-28-2022 11:23 AM
Hi Digisolve,
For your question 1 & 2: you cann't power off the mag when you use the NDOF mode. If you do that, the algorithm output should be wrong.
For your question 3: the mag calibration is always on, and it is keeping calibrating, and the value keep changes. So there is no fixed period for mag offset and radius update.
For your question 4 & 5: recommend you to do SIC first and then check the heading value.