System Architecture¶
The wearable is a distributed sensor network with two MCUs and a host PC.

Data flow¶
Sensors ──▶ STM32F405 ──▶ USB CDC ──▶ PC Host
▲
│ UART 921600
│
Sensors ──▶ KB2040
-
Sensors — 6 BNO055 IMUs (quaternion + linear acceleration at 100 Hz), 2 MyoWare EMG envelopes, 4 FSR force sensors, plus Intel RealSense D435i (RGB-D, on a separate USB 3.0 bus for ground truth).
-
KB2040 (RP2040) — reads 2 IMUs (chest, thigh) over I2C0/I2C1, packs a 70-byte frame, and sends it to the STM32 over UART at 921600 baud every 10 ms (100 Hz).
-
STM32F405 — reads 4 IMUs (wrists, upper arms) over I2C1/I2C2, reads 6 ADC channels (EMG + FSR) with 4× oversampling, receives the KB2040 UART frame, assembles the 214-byte unified packet, and streams it to the PC over USB CDC.
-
PC Host — Python 3.12 pipeline:
serial_reader— magic sync, CRC validation, frame parsingFeatureExtractor— 2 s sliding window / 0.5 s stride → 328-dim feature vectorLiveClassifier— TorchScript BiLSTM-CNN with EMA smoothing → activity labeldashboard— Streamlit UI with stick figure, EMG/FSR displays, timeline
Why two MCUs¶
The STM32F405 has 2 I²C buses × 2 addresses (0x28/0x29) = 4 slots. 6 IMUs need 4 buses. The KB2040 adds 2 more I²C buses without a multiplexer.
See MCU Layout for the full bus assignment.
Timing budget¶
| Component | Duration |
|---|---|
| BNO055 read (×6 IMUs) | ~2.4 ms total |
| ADC read (×6 ch, 4× oversample) | ~0.3 ms |
| UART receive (70 bytes) | ~0.8 ms @ 921600 |
| Packet assembly + CRC32 | ~0.2 ms |
| USB CDC TX (214 bytes) | ~0.5 ms |
| Total per frame | ~4.2 ms |
| Frame interval | 10 ms (100 Hz) |
Headroom: ~5.8 ms per cycle. The USB CDC TX drops a frame and continues if the host isn't draining, preventing the 100 Hz loop from backing up.