I am using two Adafruit 9-DOF Orientation IMU Fusion Breakout BNO085 boards with an Adafruit ESP32-S2 TFT Feather on a shared I2C bus. The Feather connects to the first IMU through a STEMMA QT cable, and that IMU daisy-chains to the second IMU through another STEMMA QT cable. An I2C scan reliably shows the addresses of both devices at 0x4A and 0x4B, with 0x4B set by pulling the DI pin high to VCC. The problem is that only one sensor initializes with the Adafruit_BNO08x library, while the other fails to initialize. There is intermittent behavior in which both sensors stream data after a power reset or after reconnection via USB. I would appreciate guidance on any known requirements for running two BNO085 boards on the same bus with this Feather to ensure both units start consistently. My code is attached.
/*
* Dual BNO085 IMU Reader for ESP32-S2 TFT Feather
*
* Hardware Setup:
* - ESP32-S2 TFT Feather as main controller
* - First BNO085 connected via STEMMA QT (I2C) - Address 0x4A (default)
* - Second BNO085 daisy-chained via STEMMA QT - Address 0x4B (DI pin to 3V)
*
* This code will:
* 1. Scan I2C bus to find connected devices
* 2. Initialize both IMUs
* 3. Read and print Euler angles from both IMUs every second
*/
#include <Wire.h>
#include <Adafruit_BNO08x.h>
// Define I2C addresses for the two BNO085 sensors
#define BNO08X_ADDR_A 0x4A // Default address (DI pin low or floating)
#define BNO08X_ADDR_B 0x4B // Alternative address (DI pin high to 3V)
// Define reset pins (use -1 if not connected)
#define BNO08X_RESET_A -1
#define BNO08X_RESET_B -1
#define I2C_SCL_PIN 40
#define I2C_SDA_PIN 41
// Create two BNO08x objects for each sensor
Adafruit_BNO08x bno08x_1(BNO08X_RESET_A);
Adafruit_BNO08x bno08x_2(BNO08X_RESET_B);
// Structure to hold sensor data
sh2_SensorValue_t sensorValue1;
sh2_SensorValue_t sensorValue2;
// Variables to store angles
float roll1, pitch1, yaw1;
float roll2, pitch2, yaw2;
// Timer for 1-second intervals
unsigned long previousMillis = 0;
const long interval = 1000; // 1 second
void setup() {
// Initialize Serial communication
Serial.begin(115200);
while (!Serial) {
delay(10); // Wait for serial port to open (for native USB)
}
Serial.println("\n===== Dual BNO085 IMU System Starting =====\n");
Wire.begin(I2C_SDA_PIN, I2C_SCL_PIN);
// Initialize I2C with default pins for ESP32-S2
// Try lower speed for better reliability with multiple BNO085s
Wire.setClock(100000); // 100kHz I2C clock (default is 400kHz)
// Scan I2C bus to find connected devices
Serial.println("Scanning I2C bus for devices...");
scanI2C();
Serial.println("\nInitializing IMUs...\n");
// CRITICAL: Add delay to let BNO085s fully power up after I2C scan
delay(500);
// Initialize first BNO085 (address 0x4A)
Serial.print("Initializing IMU 1 at address 0x");
Serial.print(BNO08X_ADDR_A, HEX);
Serial.println("...");
if (!bno08x_1.begin_I2C(BNO08X_ADDR_A)) {
Serial.println("Failed to find BNO08x chip 1 at 0x4A");
Serial.println("Check wiring and connections!");
while (1) { delay(10); }
}
Serial.println("IMU 1 initialized successfully!");
// CRITICAL: Add significant delay between initializations
// BNO085 needs time to complete first initialization
delay(5000);
// Initialize second BNO085 (address 0x4B)
Serial.print("Initializing IMU 2 at address 0x");
Serial.print(BNO08X_ADDR_B, HEX);
Serial.println("...");
if (!bno08x_2.begin_I2C(BNO08X_ADDR_B)) {
Serial.println("Failed to find BNO08x chip 2 at 0x4B");
Serial.println("Check wiring and connections!");
while (1) { delay(10); }
}
Serial.println("IMU 2 initialized successfully!");
// Configure sensor reports for both IMUs
setReports(&bno08x_1, "IMU 1");
setReports(&bno08x_2, "IMU 2");
Serial.println("\n===== Setup Complete! Reading angles every second =====\n");
delay(100);
}
void loop() {
}
// Function to scan I2C bus and print found devices
void scanI2C() {
byte error, address;
int nDevices = 0;
Serial.println("Scanning...");
for(address = 1; address < 127; address++) {
// The i2c_scanner uses the return value of Write.endTransmission
// to see if a device acknowledged the address
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) {
Serial.print("I2C device found at address 0x");
if (address < 16) Serial.print("0");
Serial.print(address, HEX);
// Identify known devices
if (address == BNO08X_ADDR_A) {
Serial.print(" (BNO085 - Default address)");
} else if (address == BNO08X_ADDR_B) {
Serial.print(" (BNO085 - Alternative address, DI=HIGH)");
}
Serial.println();
nDevices++;
}
else if (error == 4) {
Serial.print("Unknown error at address 0x");
if (address < 16) Serial.print("0");
Serial.println(address, HEX);
}
}
if (nDevices == 0) {
Serial.println("No I2C devices found!");
Serial.println("Please check your connections:");
Serial.println("- SDA and SCL properly connected via STEMMA QT");
Serial.println("- Power to both IMUs");
Serial.println("- DI pin of second IMU connected to 3V");
}
else {
Serial.print("Scan complete. Found ");
Serial.print(nDevices);
Serial.println(" device(s).");
}
}
// Function to configure sensor reports
void setReports(Adafruit_BNO08x* sensor, String imuName) {
Serial.println("Setting desired reports for " + imuName + "...");
// Enable rotation vector report at 50Hz
// This provides orientation as a quaternion
if (!sensor->enableReport(SH2_ROTATION_VECTOR, 20000)) { // 20ms = 50Hz
Serial.println("Could not enable rotation vector for " + imuName);
}
Here is the serial monitor reading
===== Dual BNO085 IMU System Starting =====
Scanning I2C bus for devices...
Scanning...
I2C device found at address 0x4A (BNO085 - Default address)
I2C device found at address 0x4B (BNO085 - Alternative address, DI=HIGH)
Scan complete. Found 2 device(s).
Initializing IMUs...
Initializing IMU 1 at address 0x4A...
IMU 1 initialized successfully!
Initializing IMU 2 at address 0x4B...
Failed to find BNO08x chip 2 at 0x4B
Check wiring and connections!