| name | hardware |
| description | Hardware reference — BOM, ESP32-C3 pinout, BNO085 wiring, power, enclosure, mounting. TRIGGER when the user asks about wiring, pins, which connector, what board to buy, enclosure, physical install, or "can I use pin X for Y". DO NOT trigger for calibration math (use /calibrate) or firmware build issues (use /flash). |
Hardware reference
The single source of truth for what's in the box and how it's wired.
Mirrors docs/hardware.md and docs/wiring.md; keep them in sync.
Bill of materials
| Part | Notes |
|---|
| Seeed XIAO ESP32-C3 | Tiny, USB-C, cheap, has LiPo charger. Alternative: ESP32-C3-DevKitM-1 |
| Adafruit BNO085 breakout (PID 4754) | Qwiic/STEMMA-QT + headers, 3.3 V, I²C addr 0x4A (default) or 0x4B |
| 4-wire Qwiic/STEMMA-QT cable | JST-SH, saves soldering |
| USB-C cable (short, marine-grade if routed outside) | |
| Enclosure (TBD) | IP65+, non-ferrous, no lid over the antenna |
| 3M VHB or M3 fasteners | For a rigid mount — not zip ties, not velcro |
Draft — finalize after first prototype.
ESP32-C3 pinout (XIAO variant)
| XIAO pin | GPIO | Used for | Notes |
|---|
| D4 | GPIO6 | I²C SDA | default for Arduino-ESP32 on C3-XIAO |
| D5 | GPIO7 | I²C SCL | |
| D1 | GPIO3 | BNO085 INT (optional) | data-ready interrupt, reduces I²C polling |
| D0 | GPIO2 | BNO085 RST (optional) | hard reset on wedge |
| 3V3 | — | BNO085 VIN | do not wire 5 V even if the breakout has a regulator |
| GND | — | BNO085 GND | |
On DevKitM-1 the same functions map differently — check the silkscreen.
I²C bus numbers and pins are config, not constants; lib/config/ loads them
from NVS. Don't hardcode Wire.begin(SDA, SCL) anywhere but lib/imu/.
I²C wiring
ESP32-C3 BNO085
3V3 ──────────────── VIN
GND ──────────────── GND
SDA (D4/GPIO6) ───── SDA
SCL (D5/GPIO7) ───── SCL
GPIO3 ─────────────── INT (optional, pull-up on BNO side)
GPIO2 ─────────────── RST (optional, active-low)
- I²C pull-ups: the Adafruit breakout has 10 kΩ on SDA/SCL. Do not add more
- Bus speed: 400 kHz (
Wire.setClock(400000)). The BNO085 handles 1 MHz,
but 400 kHz leaves headroom for cable length in the boat environment
- Cable length: keep I²C under 30 cm. For longer runs, put the sensor and
ESP32 in the same enclosure and run USB (data) / wifi (no data) to it
Power
- USB-C from a 5 V source (helmlog Pi USB port, a DC-DC from the boat's
12 V, or a small LiPo on the XIAO's onboard charger)
- Power draw: ~80 mA continuous at 100 Hz sampling + active wifi.
LiPo sizing if ever needed: 1000 mAh = ~12 h runtime
- Brown-out: the ESP32-C3 brown-out detector is enabled by default.
If the device resets mid-race on heavy wifi transmit, the USB source is
sagging — use a better cable / closer source, don't disable the BOD
Mounting
The sensor should be:
- Rigidly bolted to structure, as close to the boat's pitch/roll
center as practical. Near the mast step is ideal; a cabin bulkhead
is acceptable; a stanchion base is not (flex = noise)
- Not near a compass (Raymarine/B&G fluxgate) — the ESP32 wifi
radio can disturb nearby compasses. Minimum 1 m
- Not inside a Faraday cage — keep the wifi antenna end of the
XIAO exposed. No metal enclosure lid above the antenna
- Orientation is arbitrary — we handle it via
mount_quat. Mount
it however the wiring wants; just don't move it after calibrating
Test / debug harness
For bench development without the boat:
- A foam-core L-bracket that holds the device and a laser pointer
mounted in a known orientation — lets you rotate through known
angles and verify quaternion output
scripts/fake_device.py runs on Mac and posts synthetic batches
to the helmlog dev instance without any hardware, for server-side
development
scripts/replay_capture.py takes a saved LittleFS ring buffer
dump and replays it to the endpoint at real time or 10×, for
reproducing analysis bugs from known data
Known gotchas
- Two BNO085s on the same bus — avoid. The breakout can be jumpered
to 0x4B but the sh2 library is not designed for multi-instance use
- USB to a Pi can cause ground loops if the Pi and the device share
power via other paths (e.g., both grounded to the same 12 V rail).
Symptom: garbled I²C, random resets. Fix: USB isolator or powered hub
- STEMMA-QT cable polarity — Qwiic/STEMMA-QT is polarized and you can't
insert it wrong, but JST-SH to loose headers IS reversible. Check 3V3
and GND before first power-on; reversed polarity kills the BNO085
- C3 wifi and BNO085 on the same board — no known interference, but
keep the BNO085 > 2 cm from the ESP32-C3 antenna just in case