09-25-2020 03:08 PM
I understand that the bno-055's internal autocalibration which runs in background cannot be switched off. I get massive heading drifting and after reading everything I could find about this I implemented my own routine to minimize this. I use the following steps in my algorithm:
1. Bno055 initialization
2. Calibration (in NDOF mode)
3. Write the calibration values (ACC, Gyro, Mag Offsets and Acc and Mag Radius bytes) in the microcontroller's (AVR) EEPROM for later use
4. find a stable position close to roll=0, pitch=0, yaw=0 on my table and log the readings
5. enter a loop where:
5.1. read the CALIB_STAT register and see if it is 0xFF (if not goto 5.1.1)
5.1.1. read EEPROM values of offsets and radii. Enter Bno055's ConfigMode. Write these saved calibration values. Reenter NDOF Mode. Blink a LED to indicate that the calib. values were reloaded.
5.2. read euler angles or raw data from sensors or whatever
I've noticed that whenever I write the offset and radius registers the CALIB_STAT register will show 0x00111111. This tells me according to the datasheet section 4.3.54 that the status of the Gyro, Acc and Mag is "calibrated" but the system's calibration status (bits 7:6) remains 0x00 "NOT CALIBRATED" . Why is that ?
What triggers the system's calibration ? According to the datasheet (same section) the status of the system calibration deppends on status of all other sensors. So why do I get 0x00111111 ? I used the value stored in this register as a trigger for reloading the initial calibration values. Eventually I made my condition: " is the current value <= Hex 3F ?" which ignores the bit 7 and 6. It works until now. But I still wanna know the reason for the described problem.
Also, would there be another method to detect when the offset and radius are getting messed up, instead of using the CALIB_Stat register ? I thought about reading only the MAG Offset and Radius cause obviously these are the most succeptible ones to distortions. This would mean only 8 read/compare/write operations instead of 22.
Another question: when going through the initial calibration process (NDOF Mode) I calibrate gyro first then the acc and the mag at the end of the routine. I'm using the calibration steps from the datasheet (and the youtoube video). After calibrating the gyro and the acc, the mag is almost always calibrated without having to do anymore movements (figure 8 or else).
If I wanna re-calibrate just one sensor, for instance the magnetometer, would this be possible ? Pause the data output, recalibrate, save the new offset/radius, resume data output.
09-25-2020 09:16 PM
Hello
Based on my experience of using BNO055, below are some comments.
Regarding the point of heading error and drift, there are a lot of factors which could contribute to this, due to the simple fact that the magnetic field is superposition of the earth magnetic field and many other sources of disturbances which are both unpredicatible and inconsistent in space and time. The fusion algorithm is continuously monitoring discrepancies caused by the volatile disturbances and when any such situation is detected, the calibration status is downgraded to indicate a need for calibration which is typically done through the well-known butterfly or figure-8 motions. Luckily, the algoirthm on BNO055 has a so-called FMC (Fast Mag Calibration) feature which makes this calibration much easier by elimiating the need for full figure 8 motions which might be challenging to do in certain cases. And hopefully this clarifies why there is not an option to turn off the "background calibration".
In the 9DoF sensor fusion, to reach optimal accuracy of the heading, each sensor need to be calibrated properly, and you are right that the system calibration depends on the calibration status of each sensor before it becomes HIGH status too, but even if the status of all the 3 sensors isHIGH it's not enough to establish a HIGH for the system calibration automatically, and I think it's because what the system calibration means is it's trying to fuse all sensors to work in concert and figure out any discrepancies before it's confident to say everything is working fine. For example, you might have reached a perfect calibration status at one location outdoors where the disturbances are minimal, and the calibration profiles are saved to the NVM, and when you move indoors, the superposed magnetic environment has changed dramatically, when you load the old (stale) magnetic calibration profile which has a status of HIGH, the fusion module cann't trust that right away, instead it fuses sensor data from 3 sensors together to see if all sensors can now work in concert and agreement with each other before the system calibration status could be set to HIGH. To reach a HIGH status of the system calibration, my expereince was that one simply needs to do some more mild movements of the board and in most cases, the HIGH status should be coming pretty quickly.
10-26-2020 11:19 PM
System calibration is running all the time in fusion lib as background routine.
When you switching to any working mode, the system calibration module starts to work and check the individual physical sensor calibration status then update its own status. If you just write all calibration parameters, not switching to any working mode, you can get system calibration level as 0.
You don't need to pause the data streaming. the calibration parameters can be read out even in any working mode.
So you can keep checking the calibration status of system calibration level and magnetic calibration level. When you found one of them drop from 3 then calibrated and back to 3 again, you can try to store all the calibration parameters for feature usage.
10-27-2020 08:41 AM
Thank you for your answers.
My system based on a bno055 still doesn't work as it should be. Here's a listing of my algorithm and the behaviour of the bno055 sensor.
'--------------------------------------------------------------------------------------
Call Bno_change_opr_mode(&B00000000) 'OPR_MODE= Config_mode
Call Bno_change_pwr_mode(&B00000000) 'PWR Mode= Normal
Waitms 200
'Select Use Ext.OSC / Perform Self Test
Call Bno_write(sys_trigger , &B10000001)
Waitms 1000
'======================================================================================
Call Bno_rd_unique_id
Waitms 100
'--------------------------------------------------------------------------------------
'Verify if the BNO-055 chip is present by reading Chip_id, Acc_id, Gyr_id and Mag_id
'and comparing them with the default values
'don't get out of the next loop until BNO-055 is detected
While Chip_ok <> 1
Call Bno_check_chip
Wend
Call Bno_st_result 'Read Self_test_result
Waitms 100
Call Bno_write(unit_sel , &B00000000)
'Calibration
Print "starting calibration sequence.."
Call Bno_change_opr_mode(&B00001100) 'OPR_MODE= Fusion_Nine_degree_of_freedom
Call Bno_rd_calib_status
Print "Calibrating Gyroscope "
Waitms 500
While Gyr_calib_status <> 3
Call Bno_rd_calib_status
Print " calib status: " ; Gyr_calib_status
Waitms 250
Wend
Print " Done !"
Waitms 500
Print "Calibrating Accelerometer "
Waitms 500
While Acc_calib_status <> 3
Call Bno_rd_calib_status
Print " calib status: " ; Acc_calib_status
Waitms 250
Wend
Print " Done !"
Waitms 500
Print "Calibrating Magnetometer "
Waitms 500
While Mag_calib_status <> 3
Call Bno_rd_calib_status
Print " calib status: " ; Mag_calib_status
Waitms 250
Wend
Print " Done !"
Waitms 500
Print "Calibrating System "
Waitms 500
While Sys_calib_status <> 3
Call Bno_rd_calib_status
Print " calib status: " ; Sys_calib_status
Waitms 250
Wend
Print " Done !"
Waitms 500
Print
Print
Call Bno_change_opr_mode(&B00000000) 'OPR_MODE= Config_mode
Print "press Key2 to overwrite calibration values in EEPROM"
While I <= 5
If Key2 = 0 Then
Call Bno_rd_calib_profile
Call Wr_eeprom_calib_profile
I = 5
End If
Waitms 500
Incr I
Wend
Print "Calibration successful !"
Waitms 2000
Print "Reading Data..."
Waitms 1000
Call Bno_change_opr_mode(&B00001100) 'OPR_MODE= Fusion_Nine_degree_of_freedom
do
Call Bno_recheck_calibration 'check Calibration to avoid drift in Acc/ Gyro/ Mag
Call Bno_quat_2_roll_pitch_yaw 'Read & Convert Quaternions to Roll, Pitch, Yaw angles [dps]
Waitms 20
loop
end
used subroutines:
Sub Bno_rd_calib_status
If Reg_page <> 0 Then Call Bno_change_reg_page(0) 'change page_id
I2cstart
I2cwbyte Bno_wr_addr 'BNO-055 I2C WRITE address
I2cwbyte Calib_stat 'Start from CALIB_STAT Register
I2crepstart 'Repeat Start Condition
I2cwbyte Bno_rd_addr 'BNO-055 I2C READ address
I2crbyte Read_byte , Nack 'read EUL_Heading_MSB
Calibration_status = Read_byte
I2cstop
Mag_calib_status.0 = Calibration_status.0
Mag_calib_status.1 = Calibration_status.1
Acc_calib_status.0 = Calibration_status.2
Acc_calib_status.1 = Calibration_status.3
Gyr_calib_status.0 = Calibration_status.4
Gyr_calib_status.1 = Calibration_status.5
Sys_calib_status.0 = Calibration_status.6
Sys_calib_status.1 = Calibration_status.7
End Sub
Sub Bno_rd_calib_profile
If Reg_page <> 0 Then Call Bno_change_reg_page(0) 'change page_id
I2cstart
I2cwbyte Bno_wr_addr 'BNO-055 I2C WRITE address
I2cwbyte Acc_offset_x_lsb 'Start from ACC_OFFSET_X_LSB Register
I2crepstart 'Repeat Start Condition
I2cwbyte Bno_rd_addr 'BNO-055 I2C READ address
'Multiple Read: Reg &H55 to &H6A
I2crbyte Read_byte , Ack 'read ACC_OFFSET_X_LSB
Aox_l = Read_byte
I2crbyte Read_byte , Ack 'read ACC_OFFSET_X_MSB
Aox_m = Read_byte
I2crbyte Read_byte , Ack 'read ACC_OFFSET_Y_LSB
Aoy_l = Read_byte
I2crbyte Read_byte , Ack 'read ACC_OFFSET_Y_MSB
Aoy_m = Read_byte
I2crbyte Read_byte , Ack 'read ACC_OFFSET_Z_LSB
Aoz_l = Read_byte
I2crbyte Read_byte , Ack 'read ACC_OFFSET_Z_MSB
Aoz_m = Read_byte
I2crbyte Read_byte , Ack 'read MAG_OFFSET_X_LSB
Mox_l = Read_byte
I2crbyte Read_byte , Ack 'read MAG_OFFSET_X_MSB
Mox_m = Read_byte
I2crbyte Read_byte , Ack 'read MAG_OFFSET_Y_LSB
Moy_l = Read_byte
I2crbyte Read_byte , Ack 'read MAG_OFFSET_Y_MSB
Moy_m = Read_byte
I2crbyte Read_byte , Ack 'read MAG_OFFSET_Z_LSB
Moz_l = Read_byte
I2crbyte Read_byte , Ack 'read MAG_OFFSET_Z_MSB
Moz_m = Read_byte
I2crbyte Read_byte , Ack 'read GYR_OFFSET_X_LSB
Gox_l = Read_byte
I2crbyte Read_byte , Ack 'read GYR_OFFSET_X_MSB
Gox_m = Read_byte
I2crbyte Read_byte , Ack 'read GYR_OFFSET_Y_LSB
Goy_l = Read_byte
I2crbyte Read_byte , Ack 'read GYR_OFFSET_Y_MSB
Goy_m = Read_byte
I2crbyte Read_byte , Ack 'read GYR_OFFSET_Z_LSB
Goz_l = Read_byte
I2crbyte Read_byte , Ack 'read GYR_OFFSET_Z_MSB
Goz_m = Read_byte
I2crbyte Read_byte , Ack 'read ACC_RADIUS_LSB
Ar_l = Read_byte
I2crbyte Read_byte , Ack 'read ACC_RADIUS_MSB
Ar_m = Read_byte
I2crbyte Read_byte , Ack 'read MAG_RADIUS_LSB
Mr_l = Read_byte
I2crbyte Read_byte , Nack 'read MAG_RADIUS_MSB. Last multiple Read operation send NACK
Mr_m = Read_byte
I2cstop
End Sub
Sub Bno_recheck_calibration
' Make sure the CALIB_STAT Register is ok
' if not reload the calibration values to avoid Acc/Gyro/Mag drift
Call Bno_rd_calib_status
If Calibration_status <= 62 Then
'calibration status is smaller than 0x00111111
'bit 7:6 (system calibration) are ignored here.
Set Wled
Call Rd_eeprom_calib_profile 'load calibration values from uC's EEPROM
Call Bno_wr_calib_profile 're-write BNO-055 calibration values
Call Bno_write(opr_mode , Ndof) 're-enter NDOF Fusion Mode
Waitms 100
Reset Wled
End If
End Sub
Here's a short description of the BNO-055's behaviour:
After the initial calibration, I get correct values for the Roll, Pitch, Yaw angles (based on the quaternions). When the de-calibration occurs (usually Mag Offset and Radius) the microcontroller detects this and reloads all the calibration values (acc offset x,y,z / gyro offset x,y,z / mag offset x,y,z / acc radius x,y,z / mag radius x,y,z) from it's eeprom and writes them to the BNO's registers. I do change the operation mode to config before doing this. After reloading I change the operation mode back to NDOF Fusion, and from now on the problem begins.
I have a white LED which I use to indicate that the calibration values have been reloaded by shortly blinking once. It blinks more than 20 times then remains off for a few seconds, and then starts to blink again.
So the BNO gets his initial calibration values back but for some reason, the calibration status remains smaller than 00111111. You notice I ignore bits 6 and 7 (system calibration). It's like it won't accept the values.
I do my testing without moving the sensor too much. Sometimes it stays in the same position for a long time, nothing else is moving on the table or around it (no mag fields or other interferences) and it still becomes drifty ...
The worse part is that, the roll pitch yaw angles are false after reloading the calibration values. Not always but most of the time. Only a complete system reset would help.
So I keep the BNO board on the table, Yaw shows 150 degrees, 40 seconds later it decalibrates, I reload the calibration values several times .. because for some reason the calib_status won't get back to "11" from the first reload, and the yaw shows 24 degrees now and jumps all over the place.
Again this happens completely random.
Please help me solve this.
10-28-2020 05:56 AM
I tried at my side with following steps:
1. power on BNO055, after reset, power mode is normal by default.
2. switch to 9DoF mode
3. do the calibration movements and read the calibration status until it goes to 3
4. check the Euler sensor output which already have the heading, pitch, roll value as direct output
5. read out the calibration parameters (0x55 - 0x6A on page 0)
6. power reset the BNO055
7. switch to 9DoF mode, then try to read the calibration status, only gryo can goes to 3 if board is no moving.
8. switch back to configure mode, write back all the calibration parameters
9. switch back to 9DoF mode, then the calibration status are all 3
10. Read again the Euler sensor output, the output is correct (without drift and jumping)
So, from my test setup, everything looks fine. I can't reproduce your issue.
You can also compare your procedure in your code with my steps to see if you missed any step.
I found when you recheck the calibration status, you didn't make sure the sensor is in configure mode before you write back the calibration parameters.
Also, if your board is not moving, the calibration status should not drop. only reason the system calibration droped is a big distortion of magnetic field are detected and algorithm can't compensate it when board is not moving. Thus, the magnetic data will float and euler output will also become drift or jumping.