firmware: diagnose BNO086 I2C address

This commit is contained in:
2026-07-17 01:59:02 -06:00
parent 1ada42b9fe
commit a1a2f399d1
4 changed files with 44 additions and 3 deletions
+2 -1
View File
@@ -11,5 +11,6 @@ This Arduino sketch reads a BNO086 IMU and MAX-M10S GPS and publishes versioned,
Power both sensors from 3.3V with shared ground. Required Arduino libraries are Adafruit BNO08x, TinyGPSPlus, and ArduinoJson 6.x. Enable **USB CDC On Boot** for diagnostics. GPS uses hardware UART0 and RS485 uses hardware UART1. Power both sensors from 3.3V with shared ground. Required Arduino libraries are Adafruit BNO08x, TinyGPSPlus, and ArduinoJson 6.x. Enable **USB CDC On Boot** for diagnostics. GPS uses hardware UART0 and RS485 uses hardware UART1.
The node sends `sensor_status` at 115200 baud every 200 ms. See `docs/SENSOR_NODE_PROTOCOL.md`. The initial firmware is transmit-only; add a dashboard receiver after bench-testing the node, RS485 polarity, and sensor axes. At startup the firmware scans D7/D8 and accepts either valid BNO08x address, `0x4A` or `0x4B`. If neither appears in the scan, verify 3.3V/GND, swap-check SDA and SCL, and confirm the breakout's PS0/PS1 jumpers are configured for I2C.
The node sends `sensor_status` at 115200 baud every 200 ms. See `docs/SENSOR_NODE_PROTOCOL.md`. The initial firmware is transmit-only; add a dashboard receiver after bench-testing the node, RS485 polarity, and sensor axes.
+32 -1
View File
@@ -9,6 +9,26 @@ Adafruit_BNO08x bno086(-1);
sh2_SensorValue_t value; sh2_SensorValue_t value;
bool initialized = false; bool initialized = false;
float radiansToDegrees(float r) { return r * 180.0f / PI; } float radiansToDegrees(float r) { return r * 180.0f / PI; }
bool addressResponds(uint8_t address) {
Wire.beginTransmission(address);
return Wire.endTransmission() == 0;
}
uint8_t findBnoAddress() {
Serial.println("Scanning I2C bus on D7 SDA / D8 SCL...");
uint8_t bnoAddress = 0;
for (uint8_t address = 1; address < 127; address++) {
if (!addressResponds(address)) continue;
Serial.print("I2C device found at 0x");
if (address < 0x10) Serial.print('0');
Serial.println(address, HEX);
if (address == BNO086_I2C_ADDRESS || address == BNO086_I2C_ADDRESS_ALTERNATE) {
bnoAddress = address;
}
}
return bnoAddress;
}
void updateEuler(ImuState& s) { void updateEuler(ImuState& s) {
float sinr = 2 * (s.real * s.i + s.j * s.k); float sinr = 2 * (s.real * s.i + s.j * s.k);
float cosr = 1 - 2 * (s.i * s.i + s.j * s.j); float cosr = 1 - 2 * (s.i * s.i + s.j * s.j);
@@ -23,7 +43,18 @@ void updateEuler(ImuState& s) {
bool initImu() { bool initImu() {
Wire.begin(BNO086_SDA_PIN, BNO086_SCL_PIN); Wire.begin(BNO086_SDA_PIN, BNO086_SCL_PIN);
initialized = bno086.begin_I2C(BNO086_I2C_ADDRESS, &Wire); Wire.setClock(BNO086_I2C_CLOCK_HZ);
delay(100);
uint8_t address = findBnoAddress();
if (address == 0) {
Serial.println("No BNO086 found at 0x4A or 0x4B");
return false;
}
Serial.print("Starting BNO086 at 0x");
Serial.println(address, HEX);
initialized = bno086.begin_I2C(address, &Wire);
if (initialized) initialized = bno086.enableReport(SH2_ROTATION_VECTOR, IMU_REPORT_INTERVAL_US); if (initialized) initialized = bno086.enableReport(SH2_ROTATION_VECTOR, IMU_REPORT_INTERVAL_US);
return initialized; return initialized;
} }
@@ -12,9 +12,10 @@
#define GPS_RX_PIN D9 #define GPS_RX_PIN D9
#define GPS_TX_PIN D10 #define GPS_TX_PIN D10
#define BNO086_I2C_ADDRESS 0x4A #define BNO086_I2C_ADDRESS 0x4A
#define BNO086_I2C_ADDRESS_ALTERNATE 0x4B
#define BNO086_I2C_CLOCK_HZ 100000
#define GPS_BAUD 9600 #define GPS_BAUD 9600
#define RS485_BAUD 115200 #define RS485_BAUD 115200
#define IMU_REPORT_INTERVAL_US 20000 #define IMU_REPORT_INTERVAL_US 20000
#define TELEMETRY_INTERVAL_MS 200 #define TELEMETRY_INTERVAL_MS 200
#define SENSOR_STALE_MS 2000 #define SENSOR_STALE_MS 2000
+8
View File
@@ -26,6 +26,14 @@ def test_imu_does_not_redeclare_arduino_degrees_macro():
assert "float degrees(" not in imu assert "float degrees(" not in imu
assert "radiansToDegrees" in imu assert "radiansToDegrees" in imu
def test_imu_scans_both_bno08x_i2c_addresses():
config = source("sensor_node_config.h")
imu = source("imu.cpp")
assert "BNO086_I2C_ADDRESS 0x4A" in config
assert "BNO086_I2C_ADDRESS_ALTERNATE 0x4B" in config
assert "findBnoAddress()" in imu
assert "Wire.endTransmission()" in imu
def test_node_does_not_take_cargo_or_ble_authority(): def test_node_does_not_take_cargo_or_ble_authority():
combined = "\n".join(p.read_text() for p in NODE.glob("*.*")) combined = "\n".join(p.read_text() for p in NODE.glob("*.*"))
assert "NimBLE" not in combined and "JBD" not in combined and "server.on(" not in combined assert "NimBLE" not in combined and "JBD" not in combined and "server.on(" not in combined