feat: Auto-detect magnetometer + barometer (#24) #27

Merged
seb merged 1 commits from sl-firmware/mag-baro-detect into main 2026-02-28 18:45:26 -05:00
Collaborator

Summary

Auto-detects external I2C sensors at boot and adds telemetry fields when present. Skips gracefully if hardware not connected.

Shared I2C1 bus (i2c1.c/h)

i2c1_init() initializes PB8=SCL / PB9=SDA at 100 kHz. hi2c1 is a global handle used by both sensor drivers. Called once in main() before probing.

Barometer (bmp280.c/h)

  • Probes 0x76 then 0x77 (both SDO pin options)
  • Chip IDs: 0x58=BMP280, 0x60=BME280
  • Added bmp280_pressure_to_alt_cm() — ISA barometric formula
  • Added bmp280.h (was missing from the repo)

Magnetometer (mag.c/h)

Auto-detects in order:

Sensor I2C ID
QMC5883L 0x0D reg 0x0D = 0xFF
HMC5883L 0x1E regs 0x0A-0x0C = H,4,3
IST8310 0x0E reg 0x00 = 0x10

mag_read_heading() returns heading in degrees×10 (0–3599), -1 if not ready.

Telemetry JSON

Base fields unchanged. Optional fields appended when sensor present:

  • "hd":<n> — compass heading, degrees×10 (mag detected)
  • "alt":<n> — altitude in cm above sea level (baro detected)

No extra bytes in packet when sensors absent.

UI

HEADING and ALT stat rows are hidden until first packet containing that field. Heading shown in degrees, altitude in metres.

Test plan

  • No I2C sensors: boot normal, no hd/alt in JSON, no hang
  • BMP280 at 0x76: alt appears in JSON, ALT row visible in UI
  • BMP280 at 0x77: same as above
  • QMC5883L: hd appears, HEADING row visible, rotates with compass
  • HMC5883L: same
  • Mag + baro both: both fields in JSON

Closes #24.

## Summary Auto-detects external I2C sensors at boot and adds telemetry fields when present. Skips gracefully if hardware not connected. ## Shared I2C1 bus (`i2c1.c/h`) `i2c1_init()` initializes PB8=SCL / PB9=SDA at 100 kHz. `hi2c1` is a global handle used by both sensor drivers. Called once in `main()` before probing. ## Barometer (`bmp280.c/h`) - Probes 0x76 then 0x77 (both SDO pin options) - Chip IDs: 0x58=BMP280, 0x60=BME280 - Added `bmp280_pressure_to_alt_cm()` — ISA barometric formula - Added `bmp280.h` (was missing from the repo) ## Magnetometer (`mag.c/h`) Auto-detects in order: | Sensor | I2C | ID | |---|---|---| | QMC5883L | 0x0D | reg 0x0D = 0xFF | | HMC5883L | 0x1E | regs 0x0A-0x0C = H,4,3 | | IST8310 | 0x0E | reg 0x00 = 0x10 | `mag_read_heading()` returns heading in degrees×10 (0–3599), -1 if not ready. ## Telemetry JSON Base fields unchanged. Optional fields appended when sensor present: - `"hd":<n>` — compass heading, degrees×10 (mag detected) - `"alt":<n>` — altitude in cm above sea level (baro detected) No extra bytes in packet when sensors absent. ## UI HEADING and ALT stat rows are hidden until first packet containing that field. Heading shown in degrees, altitude in metres. ## Test plan - [ ] No I2C sensors: boot normal, no hd/alt in JSON, no hang - [ ] BMP280 at 0x76: `alt` appears in JSON, ALT row visible in UI - [ ] BMP280 at 0x77: same as above - [ ] QMC5883L: `hd` appears, HEADING row visible, rotates with compass - [ ] HMC5883L: same - [ ] Mag + baro both: both fields in JSON Closes #24.
sl-firmware added 1 commit 2026-02-28 17:49:20 -05:00
Shared I2C1 bus (i2c1.c/h, PB8=SCL PB9=SDA 100kHz):
- i2c1_init() called once in main() before sensor probes.
- hi2c1 exported globally; baro and mag drivers use it directly.

Barometer (bmp280.c):
- Probes I2C1 at 0x76 then 0x77 (covers both SDO options).
- bmp280_init() returns chip_id (0x58/0x60) on success, neg if absent.
- Added bmp280_pressure_to_alt_cm() — ISA barometric formula.
- Added bmp280.h (was missing).

Magnetometer (mag.c / mag.h):
- Auto-detects QMC5883L (0x0D, id=0xFF), HMC5883L (0x1E, id='H43'),
  IST8310 (0x0E, id=0x10) in that order.
- mag_read_heading() returns degrees×10 (0–3599) or -1 if not ready.
- HMC5883L: correct XZY byte order applied.
- IST8310: single-measurement trigger mode.

main.c:
- i2c1_init() + bmp280_init() + mag_init() after all other inits.
- Both skip gracefully (baro_ok=0, mag_type=MAG_NONE) if not present.
- Telemetry JSON: incremental builder appends ",\"hd\":<n>" when mag
  found and ",\"alt\":<n>" when baro found. No extra bytes when absent.

UI (index.html):
- HEADING and ALT rows hidden until first packet with that field.
- Heading shown in degrees, alt in metres (firmware sends cm).

Closes #24.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
seb approved these changes 2026-02-28 18:45:19 -05:00
seb left a comment
Owner

Flash-tested all 3 together. Gyro cal eliminates yaw drift, LEDs solid, I2C probe clean.

Flash-tested all 3 together. Gyro cal eliminates yaw drift, LEDs solid, I2C probe clean.
seb merged commit d37e9ab276 into main 2026-02-28 18:45:26 -05:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: seb/saltylab-firmware#27
No description provided.