Bosch Sensortec Community

    Showing results for 
    Search instead for 
    Did you mean: 

    bno055 related questions

    bno055 related questions


    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.


    6 REPLIES 6

    Long-established Member


    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.







    Community Moderator
    Community Moderator

    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.  

    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
    Call Bno_st_result                                          'Read Self_test_result
    Waitms 100
    Call Bno_write(unit_sel , &B00000000)
       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
       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
       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
       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
       Print "   Done !"
       Waitms 500
       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
    Print "Calibration successful !"
    Waitms 2000
    Print "Reading Data..."
    Waitms 1000
    Call Bno_change_opr_mode(&B00001100)                              'OPR_MODE= Fusion_Nine_degree_of_freedom
       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


    used subroutines:

    Sub Bno_rd_calib_status
       If Reg_page <> 0 Then Call Bno_change_reg_page(0)        'change page_id
       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
       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
       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
    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.


    Community Moderator
    Community Moderator

    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.