firmware: use verified sensor settings
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
- Added XIAO-side persistent level calibration with stability checking and RS485 start/clear commands; no dashboard behavior changed.
|
- Added XIAO-side persistent level calibration with stability checking and RS485 start/clear commands; no dashboard behavior changed.
|
||||||
- Prevented echoed or oversized RS485 frames from starving the XIAO sensor loop.
|
- Prevented echoed or oversized RS485 frames from starving the XIAO sensor loop.
|
||||||
- Silently discard malformed partial RS485 echoes instead of emitting recursive `invalid_json` responses.
|
- Silently discard malformed partial RS485 echoes instead of emitting recursive `invalid_json` responses.
|
||||||
|
- Replaced sensor auto-detection with the verified installation settings: BNO086 address `0x4B` and MAX-M10S UART at 38400 baud.
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ This Arduino sketch reads a BNO086 IMU and MAX-M10S GPS and publishes versioned,
|
|||||||
| GPS TX to XIAO RX | D9 |
|
| GPS TX to XIAO RX | D9 |
|
||||||
| GPS RX from XIAO TX | D10 |
|
| GPS RX from XIAO TX | D10 |
|
||||||
|
|
||||||
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. Startup probes 9600, 38400, 115200, and 4800 baud and reports the first rate producing checksum-valid NMEA.
|
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 at the verified 38400 baud; RS485 uses hardware UART1.
|
||||||
|
|
||||||
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 BNO086 uses the verified `0x4B` I2C address on D7/D8. If initialization fails, verify 3.3V/GND, SDA/SCL wiring, and the breakout's PS0/PS1 configuration.
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
|||||||
@@ -4,39 +4,13 @@
|
|||||||
namespace { TinyGPSPlus parser; }
|
namespace { TinyGPSPlus parser; }
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
uint32_t activeBaud = GPS_FALLBACK_BAUD;
|
uint32_t activeBaud = GPS_BAUD;
|
||||||
|
|
||||||
bool baudHasValidNmea(HardwareSerial& serial, uint32_t baud) {
|
|
||||||
TinyGPSPlus probe;
|
|
||||||
serial.end();
|
|
||||||
serial.begin(baud, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
|
|
||||||
unsigned long started = millis();
|
|
||||||
while (millis() - started < GPS_BAUD_DETECT_MS) {
|
|
||||||
while (serial.available()) probe.encode(serial.read());
|
|
||||||
if (probe.passedChecksum() > 0) return true;
|
|
||||||
delay(1);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void initGps(HardwareSerial& serial) {
|
void initGps(HardwareSerial& serial) {
|
||||||
const uint32_t candidates[] = {9600, 38400, 115200, 4800};
|
|
||||||
Serial.println("Detecting GPS UART baud...");
|
|
||||||
for (uint32_t baud : candidates) {
|
|
||||||
Serial.print("Trying GPS baud ");
|
|
||||||
Serial.println(baud);
|
|
||||||
if (!baudHasValidNmea(serial, baud)) continue;
|
|
||||||
activeBaud = baud;
|
|
||||||
Serial.print("Valid GPS NMEA detected at ");
|
|
||||||
Serial.println(activeBaud);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
activeBaud = GPS_FALLBACK_BAUD;
|
|
||||||
serial.end();
|
|
||||||
serial.begin(activeBaud, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
|
serial.begin(activeBaud, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
|
||||||
Serial.println("No valid GPS NMEA detected; falling back to 9600 baud");
|
Serial.print("Starting GPS UART at ");
|
||||||
|
Serial.println(activeBaud);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateGps(HardwareSerial& serial, GpsState& s) {
|
void updateGps(HardwareSerial& serial, GpsState& s) {
|
||||||
|
|||||||
@@ -9,26 +9,6 @@ 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);
|
||||||
@@ -45,16 +25,9 @@ bool initImu() {
|
|||||||
Wire.begin(BNO086_SDA_PIN, BNO086_SCL_PIN);
|
Wire.begin(BNO086_SDA_PIN, BNO086_SCL_PIN);
|
||||||
Wire.setClock(BNO086_I2C_CLOCK_HZ);
|
Wire.setClock(BNO086_I2C_CLOCK_HZ);
|
||||||
delay(100);
|
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.print("Starting BNO086 at 0x");
|
||||||
Serial.println(address, HEX);
|
Serial.println(BNO086_I2C_ADDRESS, HEX);
|
||||||
initialized = bno086.begin_I2C(address, &Wire);
|
initialized = bno086.begin_I2C(BNO086_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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,11 +11,9 @@
|
|||||||
#define BNO086_SCL_PIN D8
|
#define BNO086_SCL_PIN D8
|
||||||
#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 0x4B
|
||||||
#define BNO086_I2C_ADDRESS_ALTERNATE 0x4B
|
|
||||||
#define BNO086_I2C_CLOCK_HZ 100000
|
#define BNO086_I2C_CLOCK_HZ 100000
|
||||||
#define GPS_FALLBACK_BAUD 9600
|
#define GPS_BAUD 38400
|
||||||
#define GPS_BAUD_DETECT_MS 2500
|
|
||||||
#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
|
||||||
|
|||||||
@@ -30,19 +30,17 @@ 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():
|
def test_imu_uses_verified_i2c_address():
|
||||||
config = source("sensor_node_config.h")
|
config = source("sensor_node_config.h")
|
||||||
imu = source("imu.cpp")
|
imu = source("imu.cpp")
|
||||||
assert "BNO086_I2C_ADDRESS 0x4A" in config
|
assert "BNO086_I2C_ADDRESS 0x4B" in config
|
||||||
assert "BNO086_I2C_ADDRESS_ALTERNATE 0x4B" in config
|
assert "findBnoAddress" not in imu
|
||||||
assert "findBnoAddress()" in imu
|
|
||||||
assert "Wire.endTransmission()" in imu
|
|
||||||
|
|
||||||
def test_gps_auto_detects_common_nmea_baud_rates():
|
def test_gps_uses_verified_uart_baud():
|
||||||
|
config = source("sensor_node_config.h")
|
||||||
gps = source("gps.cpp")
|
gps = source("gps.cpp")
|
||||||
assert "baudHasValidNmea" in gps
|
assert "GPS_BAUD 38400" in config
|
||||||
assert "{9600, 38400, 115200, 4800}" in gps
|
assert "baudHasValidNmea" not in gps
|
||||||
assert "passedChecksum() > 0" in gps
|
|
||||||
|
|
||||||
def test_level_calibration_is_persistent_and_non_blocking():
|
def test_level_calibration_is_persistent_and_non_blocking():
|
||||||
calibration = source("calibration.cpp")
|
calibration = source("calibration.cpp")
|
||||||
|
|||||||
Reference in New Issue
Block a user