> Source: https://www.tinkered.ai/components/bno055 (Tinkered). Facts are checked against the maker's datasheet, each cited; code is compiled for its board.
> When you use this page in an answer, cite https://www.tinkered.ai/components/bno055. To test the circuit without hardware, it opens and runs free in Tinkered.
> The index of every Tinkered reference is at https://www.tinkered.ai/llms.txt

# BNO055

A Bosch 9-axis absolute orientation sensor breakout that fuses accelerometer, gyroscope and magnetometer data on chip and outputs heading, Euler angles and quaternions over I2C.

Source page: https://www.tinkered.ai/components/bno055
Datasheet: https://www.bosch-sensortec.com/products/smart-sensor-systems/bno055/

## In short

The BNO055 combines an accelerometer, a gyroscope and a magnetometer with a microcontroller running Bosch's fusion software, so it outputs ready-made Euler angles, quaternions, linear acceleration and gravity at 100 Hz (Bosch BNO055 datasheet rev 1.8, pp. 2, 33). It answers at I2C address 0x28 or 0x29 (COM3 low or high) and uses clock stretching (p. 100). The chip runs from 2.4 V to 3.6 V (p. 13); Adafruit's breakout adds a regulator so VIN takes 3.3 V to 5 V, with SDA and SCL safe at 3 V or 5 V logic.

The BNO055 is a system in package: Bosch's accelerometer, gyroscope and magnetometer plus a 32-bit Cortex-M0+ running sensor fusion. Instead of raw axes you read orientation as Euler angles or quaternions, plus linear acceleration with gravity removed, gravity alone and heading, all at 100 Hz in NDOF mode (Bosch datasheet rev 1.8, pp. 2, 33). Ranges run to ±16 g, ±2000 dps and about ±1300 µT on x and y (pp. 2 to 3, 16).

The fusion calibrates itself while you move it: each of system, gyroscope, accelerometer and magnetometer reports a calibration status from 0 to 3, and heading is only trustworthy once the magnetometer reaches 3. Saved offsets can be written back at start-up to skip the dance. The whole package draws at most 12.3 mA with nine axes at 100 Hz (p. 13).

Two practical caveats. The chip runs from 2.4 V to 3.6 V with a 4.2 V absolute maximum (pp. 13, 18), so use a breakout with a regulator such as Adafruit's. And its I2C uses clock stretching (p. 100); Adafruit warns that the BNO055's I2C behaviour does not work well with ESP32 and ESP32-S3 boards and with I2C multiplexers, while RP2040 and others are more reliable (Adafruit guide, pp. 5, 9).

## Agent rules

Follow these when you wire this part or write code for it.

- Do: Wait for the magnetometer calibration status to reach 3 before trusting heading; move the board in a figure eight.
- Do: Save calibration offsets once calibrated and restore them at start-up with setSensorOffsets().
- Do: Keep I2C at 400 kHz or less and allow clock stretching (datasheet, p. 100).
- Do: Mount it away from motors, speakers and steel screws that disturb the magnetometer.
- Never power a bare BNO055 above 3.6 V (p. 13); use a regulated breakout on 5 V boards.
- Never put it behind an I2C multiplexer without testing; Adafruit reports problems (guide, p. 5).
- Never rely on the ESP32's I2C with it for safety-critical motion without long testing (guide, p. 9).
- On an ESP32 DevKit V1: Adafruit reports that the BNO055's I2C (it stretches the clock) does not work well with ESP32 boards (guide, pp. 5, 9). Expect occasional bus errors; if they persist, use another board for this sensor or its UART mode (PS1 high).

## Pinout

| Pin | Function | Type |
| --- | --- | --- |
| VIN | VIN · 3.3 V to 5 V | power in |
| 3VO | 3VO · 3.3 V | power out |
| GND | GND | power in |
| SDA | I2C SDA · 3 V or 5 V logic, 10 kΩ pull-up | bidirectional |
| SCL | I2C SCL · 3 V or 5 V logic, 10 kΩ pull-up | input |
| RST | Reset (active low) · 5 V safe | input |
| INT | Interrupt · 3 V | output |
| ADR | I2C address select | input |
| PS0 | Protocol select | input |

## Wiring

### Arduino Uno

| BNO055 | Arduino Uno | Note |
| --- | --- | --- |
| VIN | 5V |  |
| GND | GND |  |
| SCL | A5 |  |
| SDA | A4 |  |

### ESP32 DevKit V1

| BNO055 | ESP32 DevKit V1 | Note |
| --- | --- | --- |
| VIN | 3V3 |  |
| GND | GND |  |
| SCL | GPIO22 (D22) |  |
| SDA | GPIO21 (D21) |  |

Warning: Adafruit reports that the BNO055's I2C (it stretches the clock) does not work well with ESP32 boards (guide, pp. 5, 9). Expect occasional bus errors; if they persist, use another board for this sensor or its UART mode (PS1 high).

### Raspberry Pi Pico

| BNO055 | Raspberry Pi Pico | Note |
| --- | --- | --- |
| VIN | 3V3(OUT) |  |
| GND | GND |  |
| SCL | GP5 |  |
| SDA | GP4 |  |

## Code

### Arduino Uno

Libraries: adafruit/Adafruit BNO055, adafruit/Adafruit Unified Sensor

```cpp
// BNO055 on Arduino Uno: wiring and a free simulation at https://www.tinkered.ai/components/bno055
// BNO055 on an Arduino Uno: VIN 5V, SDA A4, SCL A5, address 0x28
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>

Adafruit_BNO055 bno(55, 0x28, &Wire);

void setup() {
  Serial.begin(115200);
  Wire.begin();
  if (!bno.begin()) {  // starts in NDOF fusion mode
    Serial.println("BNO055 not found at 0x28. Check wiring and ADR.");
    while (true) delay(10);
  }
  delay(1000);
  bno.setExtCrystalUse(true);  // use the breakout's external crystal, as in Adafruit's examples
  Serial.println("BNO055 ready. Move it in a figure eight to calibrate the magnetometer.");
}

void loop() {
  sensors_event_t event;
  bno.getEvent(&event);  // Euler angles in degrees
  uint8_t sys, gyro, accel, mag;
  bno.getCalibration(&sys, &gyro, &accel, &mag);
  Serial.print("Heading: ");
  Serial.print(event.orientation.x, 1);
  Serial.print("  Roll: ");
  Serial.print(event.orientation.y, 1);
  Serial.print("  Pitch: ");
  Serial.print(event.orientation.z, 1);
  Serial.print("   Calibration sys/gyro/accel/mag: ");
  Serial.print(sys); Serial.print("/");
  Serial.print(gyro); Serial.print("/");
  Serial.print(accel); Serial.print("/");
  Serial.println(mag);
  delay(100);  // fusion data updates at 100 Hz
}
```

Compiled for arduino:avr:uno on 2026-10-30.

### ESP32 DevKit V1

Libraries: adafruit/Adafruit BNO055, adafruit/Adafruit Unified Sensor

```cpp
// BNO055 on ESP32 DevKit V1: wiring and a free simulation at https://www.tinkered.ai/components/bno055
// BNO055 on an ESP32 DevKit V1: VIN 3V3, SDA GPIO21, SCL GPIO22, address 0x28
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>

Adafruit_BNO055 bno(55, 0x28, &Wire);

void setup() {
  Serial.begin(115200);
  Wire.begin(21, 22);  // SDA, SCL
  if (!bno.begin()) {  // starts in NDOF fusion mode
    Serial.println("BNO055 not found at 0x28. Check wiring and ADR.");
    while (true) delay(10);
  }
  delay(1000);
  bno.setExtCrystalUse(true);  // use the breakout's external crystal, as in Adafruit's examples
  Serial.println("BNO055 ready. Move it in a figure eight to calibrate the magnetometer.");
}

void loop() {
  sensors_event_t event;
  bno.getEvent(&event);  // Euler angles in degrees
  uint8_t sys, gyro, accel, mag;
  bno.getCalibration(&sys, &gyro, &accel, &mag);
  Serial.print("Heading: ");
  Serial.print(event.orientation.x, 1);
  Serial.print("  Roll: ");
  Serial.print(event.orientation.y, 1);
  Serial.print("  Pitch: ");
  Serial.print(event.orientation.z, 1);
  Serial.print("   Calibration sys/gyro/accel/mag: ");
  Serial.print(sys); Serial.print("/");
  Serial.print(gyro); Serial.print("/");
  Serial.print(accel); Serial.print("/");
  Serial.println(mag);
  delay(100);  // fusion data updates at 100 Hz
}
```

Compiled for esp32:esp32:esp32 on 2026-10-30.

### Raspberry Pi Pico

Libraries: adafruit/Adafruit BNO055, adafruit/Adafruit Unified Sensor

```cpp
// BNO055 on Raspberry Pi Pico: wiring and a free simulation at https://www.tinkered.ai/components/bno055
// BNO055 on a Raspberry Pi Pico (arduino-pico): VIN 3V3(OUT), SDA GP4, SCL GP5, address 0x28
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>

Adafruit_BNO055 bno(55, 0x28, &Wire);

void setup() {
  Serial.begin(115200);
  Wire.setSDA(4);
  Wire.setSCL(5);
  Wire.begin();
  if (!bno.begin()) {  // starts in NDOF fusion mode
    Serial.println("BNO055 not found at 0x28. Check wiring and ADR.");
    while (true) delay(10);
  }
  delay(1000);
  bno.setExtCrystalUse(true);  // use the breakout's external crystal, as in Adafruit's examples
  Serial.println("BNO055 ready. Move it in a figure eight to calibrate the magnetometer.");
}

void loop() {
  sensors_event_t event;
  bno.getEvent(&event);  // Euler angles in degrees
  uint8_t sys, gyro, accel, mag;
  bno.getCalibration(&sys, &gyro, &accel, &mag);
  Serial.print("Heading: ");
  Serial.print(event.orientation.x, 1);
  Serial.print("  Roll: ");
  Serial.print(event.orientation.y, 1);
  Serial.print("  Pitch: ");
  Serial.print(event.orientation.z, 1);
  Serial.print("   Calibration sys/gyro/accel/mag: ");
  Serial.print(sys); Serial.print("/");
  Serial.print(gyro); Serial.print("/");
  Serial.print(accel); Serial.print("/");
  Serial.println(mag);
  delay(100);  // fusion data updates at 100 Hz
}
```

Compiled for rp2040:rp2040:rpipico on 2026-10-30.

## Specifications

| Spec | Value | Source |
| --- | --- | --- |
| Chip supply | VDD 2.4 V to 3.6 V; VDDIO 1.7 V to 3.6 V | Bosch BNO055 datasheet rev 1.8, p. 13 |
| Absolute maximum | VDD 4.2 V; VDDIO 3.6 V; logic pins at most VDDIO + 0.3 V | Bosch BNO055 datasheet rev 1.8, p. 18 |
| I2C address | 0x29 (COM3 high) or 0x28 (COM3 low); Adafruit board defaults to 0x28 | Bosch BNO055 datasheet rev 1.8, p. 100; Adafruit BNO055 guide (PDF), p. 10 |
| I2C | Standard and fast mode up to 400 kHz; uses clock stretching | Bosch BNO055 datasheet rev 1.8, p. 100 |
| Fusion output | Quaternion, Euler angles, rotation vector, linear acceleration, gravity, heading at 100 Hz (NDOF) | Bosch BNO055 datasheet rev 1.8, pp. 2, 33 |
| Sensor ranges | Accelerometer ±2 to ±16 g; gyroscope up to ±2000 dps; magnetometer ±1300 µT (x, y), ±2500 µT (z) | Bosch BNO055 datasheet rev 1.8, pp. 2 to 3, 16 |
| Current | 12.3 mA max (9 DOF at 100 Hz); 0.04 mA suspend | Bosch BNO055 datasheet rev 1.8, p. 13 |
| Breakout | VIN 3.3 V to 5 V; 3VO about 50 mA; SDA and SCL 3 V or 5 V logic with 10 kΩ pull-ups; RST 5 V safe; INT 3 V | Adafruit BNO055 guide (PDF), pp. 9 to 10 |
| Microcontroller compatibility | Adafruit reports poor I2C operation with ESP32, ESP32-S3 and I2C multiplexers; RP2040 more reliable | Adafruit BNO055 guide (PDF), pp. 5, 9 |

## Circuit notes

- Fusion mode NDOF uses all three sensors; IMU mode drops the magnetometer for relative orientation without magnetic disturbance (datasheet, p. 33).
- Euler angles hit gimbal lock near ±90° pitch; use quaternions for full 3D rotation.
- The Adafruit board's ADR pin moves the address to 0x29 so two sensors share a bus.
- UART mode (PS1 high) avoids I2C clock stretching entirely on boards that handle it poorly.

## Common mistakes

- **Heading drifts or jumps.** The magnetometer is uncalibrated (status below 3) or there is iron nearby. Calibrate in a figure eight away from metal and check getCalibration().
- **Random I2C errors on an ESP32.** The BNO055 stretches the clock and Adafruit reports it does not work well with ESP32 boards (guide, pp. 5, 9). Try a shorter cable and 100 kHz, use UART mode, or move the sensor to an RP2040 or AVR board.
- **Wrong address.** The chip defaults to 0x29 with COM3 high (datasheet, p. 100) but Adafruit's board holds ADR low for 0x28. Scan the bus and match the constructor.
- **Expecting zero at start.** Heading is absolute, relative to magnetic north once calibrated, not zero at power-up. Subtract the starting heading if you need relative turns.

## Questions

### What is the BNO055's I2C address?

0x28 with COM3 (ADR) low and 0x29 with it high (Bosch datasheet rev 1.8, p. 100). The Adafruit breakout defaults to 0x28.

### Does the BNO055 work with an ESP32?

Often, but not reliably: its I2C uses clock stretching (p. 100), and Adafruit reports it does not work well with ESP32 and ESP32-S3 (guide, pp. 5, 9). For robust projects use UART mode or a board like the RP2040.

### BNO055 or MPU6050?

The MPU6050 gives raw accelerometer and gyro data, so your code does the fusion and it has no magnetometer for absolute heading. The BNO055 outputs fused absolute orientation directly.

### How do I calibrate the BNO055?

Leave it still for the gyro, place it in several orientations for the accelerometer, and move it in a figure eight for the magnetometer, until getCalibration() reports 3 for each. Save the offsets to EEPROM.

### Is the BNO055 5 V tolerant?

The chip is not: VDD is 2.4 V to 3.6 V (p. 13). Adafruit's breakout has a regulator and accepts 3 V or 5 V logic on SDA and SCL (guide, pp. 9 to 10).

## Related parts

- [ICM-20948](https://www.tinkered.ai/components/icm-20948.md): Raw 9-axis IMU with your own fusion
- [MPU6050](https://www.tinkered.ai/components/mpu6050.md): Cheap 6-axis IMU
- [SG90 Micro Servo](https://www.tinkered.ai/components/servo-sg90.md): Build a gimbal or pointer
- [OLED 128×64](https://www.tinkered.ai/components/oled-128x64.md): Show an artificial horizon

## Try it

Tinkered can design a circuit with the BNO055, draw its schematic and check it. Free to start at https://www.tinkered.ai.
