How Do You Interface and Calibrate a BNO055 Absolute Orientation Sensor?
Last updated 20 July 2026 · 7 min read
Direct Answer
The Bosch BNO055 is a system-in-package combining a 3-axis accelerometer, gyroscope, and magnetometer with an onboard ARM Cortex-M0 running Bosch's own sensor-fusion firmware, so it outputs ready-to-use orientation data over I2C or UART instead of raw axes a host MCU has to fuse itself. Set the operation mode register to a fusion mode (NDOF for full 9-axis absolute orientation, or IMU mode for 6-axis relative orientation when no reliable magnetic reference is available), then read either the Euler angle registers or the quaternion registers depending on whether gimbal-lock-free representation matters for your application. Calibration status is exposed per-subsystem (system, gyroscope, accelerometer, magnetometer) in a single status register, and once fully calibrated the internal offsets can be read out and rewritten on every future boot so the sensor doesn't need to be recalibrated from scratch each time.
Detailed Explanation
The Bosch BNO055 is a system-in-package IMU: a 3-axis accelerometer, a 3-axis gyroscope, and a 3-axis magnetometer sit alongside a dedicated ARM Cortex-M0 microcontroller running Bosch's own sensor-fusion firmware, all inside one package. This changes the integration problem compared with a raw IMU like the MPU-6050 or LSM6DSO (see accelerometer and IMU basics). With a raw IMU, the host MCU reads unfused axis data and runs its own fusion algorithm (a complementary filter or a Madgwick filter) to turn that into a usable orientation estimate. With the BNO055, the fusion already happened onboard before the host MCU ever reads a register: the device exposes finished orientation data directly, at the cost of that fusion algorithm being closed-source and not something the host firmware can inspect or retune.
That trade-off, faster integration against the loss of internal visibility into the fusion algorithm, is the central design decision when choosing between the two approaches. It's the same trade-off the MPU-6050's onboard DMP offers on a smaller scale, but the BNO055 goes further: it adds a magnetometer to the fusion input and outputs both quaternion and Euler-angle orientation directly, not just raw motion events.
Fusion Modes and the Operation Mode Register
The BNO055's OPR_MODE register selects one of several operating modes, split into two families. Non-fusion modes (ACCONLY, MAGONLY, GYROONLY, and combinations like ACCGYRO) simply expose one or more raw sensor outputs without running the onboard fusion algorithm, which is useful for bring-up and self-test but doesn't provide orientation data. Fusion modes run the onboard Cortex-M0's sensor-fusion firmware and output computed orientation:
- IMU mode fuses only the accelerometer and gyroscope, providing relative orientation (roll and pitch, with yaw drifting unbounded since there's no magnetic reference). Use this when the installation environment has unreliable or heavily disturbed magnetic fields, for example close to motors, speakers, or large ferrous structures, where trusting the magnetometer would introduce more error than it corrects.
- NDOF mode fuses all three sensors for full 9-axis absolute orientation, including a bounded, magnetically referenced heading. This is the mode most designs default to once the installation environment allows a usable magnetic reference.
- COMPASS and M4G modes serve narrower use cases (COMPASS mode outputs static, non-fused heading; M4G uses magnetometer data to aid orientation without a gyroscope input) and are less commonly used than IMU or NDOF for general orientation tracking.
Before writing to most configuration registers, including the offset registers described below, the device must be switched into CONFIG mode (OPR_MODE = 0x00). Writes to some registers are silently ignored outside CONFIG mode, which is a common source of confusing "my calibration write didn't stick" bugs.
Quaternion vs Euler Angle Output
The BNO055 exposes both representations simultaneously in fusion modes, and the choice between them depends on what the receiving code needs to do with the data:
- Euler angles (heading, roll, pitch) are immediately human-readable and simple to display or log directly, but they suffer from gimbal lock: as pitch approaches ±90°, roll and heading become numerically ill-defined, which shows up as sudden jumps or instability in the reported values even though the physical orientation is changing smoothly.
- Quaternions (a four-component W/X/Y/Z representation) have no gimbal lock singularity and are the correct representation for any downstream math that composes rotations, such as feeding orientation into a 3D rendering pipeline or a further fusion stage. The cost is that quaternions aren't directly human-readable and need conversion to Euler angles or a rotation matrix for display purposes.
For a product that only needs to display or threshold a roll/pitch/heading value and never operates near vertical pitch, Euler output is simpler to work with. For anything that composes orientation with other transforms, or that needs to operate reliably through the full orientation range including near-vertical pitch, read the quaternion registers instead and convert only where a human-readable value is actually needed.
Calibration Status and Offset Save and Restore
The CALIB_STAT register reports calibration state as four independent 2-bit fields, one each for the overall system, the gyroscope, the accelerometer, and the magnetometer, with a value of 3 meaning fully calibrated and lower values meaning partially or not calibrated. A design reading fusion output should check this register, not just assume the sensor is ready once it starts responding to reads: a BNO055 that has only just powered on will report plausible-looking but inaccurate orientation data before the magnetometer in particular reaches full calibration.
Once all four fields reach full calibration, the device's internal offset values (per-axis accelerometer offset, per-axis magnetometer offset, per-axis gyroscope offset, plus an accelerometer and magnetometer radius value) can be read out over the same register interface and stored in the host MCU's own non-volatile memory (see embedded flash storage for common approaches to storing small calibration blobs). On a subsequent boot, writing those saved offsets back into the device while it's in CONFIG mode, then switching to the desired fusion mode, restores most of the calibration state without repeating the physical motion needed to build it from scratch. This is standard practice for any product where asking the end user to wave the device through a figure-8 pattern on every power-up isn't acceptable.
I2C and UART Interfacing
The BNO055 supports two host interfaces, selectable in hardware:
- I2C, at a default slave address of 0x28 or an alternate address of 0x29 selected by the COM3 pin (often labelled ADR on breakout boards), which matters when more than one BNO055 shares a bus.
- UART, using a fixed packet-based protocol with a start byte rather than plain serial text, useful when I2C bus contention or cable length makes the I2C interface impractical.
Most designs use I2C, since it shares the bus infrastructure already present for other sensors and doesn't need dedicated UART pins on the host MCU. See what is I2C? for the underlying bus protocol.
Design Considerations
- Keep the magnetometer away from sources of magnetic interference. Motors, speakers, relays, and traces carrying significant switching current all distort the local magnetic field the magnetometer relies on for heading. Where the module can't be physically relocated away from a known interference source, IMU mode (accelerometer and gyroscope only, no magnetometer) avoids the problem entirely at the cost of unbounded yaw drift.
- Give the device time and motion to calibrate before trusting its output. A freshly powered BNO055 has not yet built a magnetometer calibration model; NDOF mode output during that window can look plausible while still being inaccurate. Check CALIB_STAT before acting on orientation data in any application where an uncalibrated reading would cause a real problem.
- Save and restore calibration offsets for any product where re-running a figure-8 calibration on every boot is impractical. Read the offset registers once CALIB_STAT reports full calibration, store them in host flash, and rewrite them (in CONFIG mode) on subsequent boots.
- Choose NDOF or IMU mode deliberately, not by default. NDOF gives a bounded absolute heading but depends on a usable magnetic environment; IMU mode is immune to magnetic interference but its heading drifts without bound over time. The right choice depends on whether the product's installation environment can reliably support magnetometer calibration.
- Sensor and firmware integration for motion-sensing products: choosing between onboard-fusion and raw-IMU-plus-custom-filter approaches, and validating calibration behaviour across real installation environments, is exactly the kind of integration work Zeus Design's engineering team handles as part of full product development.
Common Mistakes
- Writing to configuration or offset registers while the device is still in a fusion operating mode instead of switching to CONFIG mode first, resulting in writes that appear to succeed but have no effect.
- Trusting NDOF heading output immediately after power-up without checking CALIB_STAT, especially in products that also power-cycle frequently in normal use.
- Mounting the module directly next to a motor, speaker, or high-current switching trace and then treating the resulting heading drift as a sensor defect rather than a magnetic interference problem.
- Defaulting to NDOF mode in an environment where a reliable magnetic reference isn't actually available, when IMU mode would give more consistent (if unbounded-drift) behaviour for that specific installation.
Frequently Asked Questions
- Should I use the BNO055 or a raw IMU like the MPU-6050 or LSM6DSO?
- It depends on where you want the fusion computation to happen. A raw IMU (see accelerometer and IMU basics) hands the host MCU unfused accelerometer and gyroscope data, and you run your own complementary or Madgwick filter, which gives full visibility and tuning control but costs MCU cycles and development time. The BNO055 runs Bosch's fusion algorithm internally on its own Cortex-M0 and hands back finished orientation data, which is faster to integrate and offloads the host MCU entirely, at the cost of the fusion algorithm being a closed-source black box you can't tune or debug internally. For a quick, reliable orientation output with minimal firmware effort, the BNO055's onboard fusion is usually the better fit; for a highly constrained MCU budget or a need to fully control and tune the fusion behaviour, a raw IMU with your own filter is the better fit.
- Why does the BNO055 report a wrong or drifting heading until I move it in a figure-8 pattern?
- The magnetometer subsystem needs motion through a range of orientations to characterise its own hard-iron and soft-iron offset errors, and it cannot do this while sitting still. Bosch's application guidance for the BNO055 recommends moving the sensor through a figure-8 pattern in the air until the magnetometer calibration field in CALIB_STAT reaches its maximum value. Until that happens, the heading component of NDOF mode's output is unreliable even though roll and pitch (which only depend on the accelerometer and gyroscope) may already be accurate.
- Is the BNO055 still a reasonable choice for a new design?
- It remains a common choice because of its mature driver ecosystem, wide breakout-board availability, and a well-documented register interface that many existing firmware libraries already support. Bosch and other vendors also offer newer fusion-IMU parts with additional features such as higher-rate output or built-in step counters; whether one of those is a better fit depends on the specific product requirement, so it's worth checking current part availability and feature sets against your design's needs rather than defaulting to either the newest or the most familiar part.
References
Related Questions
What Is an Accelerometer and IMU?
Covers IMU and accelerometer basics: MEMS principles, MPU-6050 and LSM6DSO interfacing, gyroscope drift, and complementary filter sensor fusion.
What Is I2C (Inter-Integrated Circuit)?
I2C is a two-wire serial bus for addressing multiple peripherals over shared SDA/SCL lines. Learn how addressing, speed grades, and pull-up resistors work.
What Is a Microcontroller (MCU)?
A microcontroller (MCU) combines a CPU, flash, RAM, and peripherals on one chip. Learn how MCUs work and how they differ from microprocessors and FPGAs.
How Do You Integrate a GNSS (GPS) Module into an Embedded Design?
Integrate a GNSS (GPS) module into an embedded design — module and antenna selection, NMEA vs binary protocols, backup power for fast TTFF, and RF layout.
Sensor Signal Conditioning Basics
Covers signal conditioning for sensors: op-amp gain, offset, 4-20mA interface, anti-aliasing filter design, ADC input protection, and two-point calibration.
How Do You Store Data in Embedded Flash Memory?
Store settings and logs in embedded flash — erase-before-write rules, endurance and wear levelling, littlefs vs FatFs, and power-fail-safe writes.
Related Forum Discussions
ICM-42688-P INT1 never fires after FIFO setup — FIFO count stuck at 0x0000 but WHO_AM_I reads back correctly
Working on a motion data logger: ICM-42688-P on an STM32F4 via SPI4 at 4 MHz. SPI seems fine: WHO_AM_I at register 0x75 reliably returns 0x4
STM32 GPIO interrupt configured but ISR never fires — what am I missing?
Trying to use a button on PA0 to trigger an interrupt on an STM32F411 Nucleo board. Using HAL, generated the init code with CubeMX. The GPIO
Can't decide between FreeRTOS and bare-metal for a simple sensor node — what's the tipping point?
Working on a temperature and humidity monitoring node: STM32F103 target, BME280 over I2C, reports data every 60 seconds over UART to a Raspb