First Data Stream¶
After flashing both MCUs and connecting the UART bridge, verify the full pipeline: sensors → MCU → packet → PC.
1. Hardware checklist¶
- [ ] STM32F405 flashed and USB-C connected to PC
- [ ] KB2040 flashed and powered (USB-C or via STM32 3.3 V)
- [ ] UART bridge wired: PC6 → GP5, PC7 ← GP4, GND common
- [ ] At least one BNO055 connected to each bus pair (optional — zero works, but data is zeros)
- [ ] LED_BUILTIN on on both boards (indicates
setup()completed)
2. Serial monitor check¶
Open a terminal on the STM32 serial port:
cd firmware/stm32f405
pio device monitor -b 115200
Expected output when KB2040 is connected and all sensors present:
STM32F405: init
[IMU] 0:ok 1:ok 2:ok 3:ok
[ADC] EMG 2ch, FSR 4ch
[UART] KB2040 data
seq=0 seq=1 seq=2 ...
[IMU] N:fail→ that BNO055 is not detected. Check I2C wiring on the corresponding bus (see Wiring).[UART] no data→ KB2040 not transmitting. Check UART wiring, KB2040 power, KB2040 LED → bothI2C0 ok, I2C1 ok.seq=Nincrements by 1 each line → main loop running at ~100 Hz.
3. Host data stream¶
Stop the PlatformIO monitor (Ctrl+C) so the serial port is free, then:
cd wearable_har_v2
.venv/bin/python -m host.serial_reader
This opens /dev/ttyACM0 (adjust with --port if needed), syncs on the 0xAA 0x55
magic bytes, validates CRC32, and prints one line per frame:
seq=0 ts=12345 imus=6 emg=2 fsr=4 crc=ok
seq=1 ts=22346 imus=6 emg=2 fsr=4 crc=ok
seq=2 ts=32347 imus=6 emg=2 fsr=4 crc=ok
crc=ok means the CRC32 checksum matched. If you see crc=FAIL, the UART
bridge has bit errors — check wiring and reduce cable length.
4. Dump raw frames¶
For debugging, use the --hex flag to dump the raw packet bytes:
.venv/bin/python -m host.serial_reader --hex
Output:
AA 55 00 00 00 00 39 30 00 00 ...
Compare against the binary protocol reference.
5. Verify with feature extraction¶
from host.serial_reader import SerialReader
from host.feature_extraction import FeatureExtractor
extractor = FeatureExtractor()
with SerialReader("/dev/ttyACM0") as reader:
for frame in reader:
feats = extractor.add_frame(frame)
if feats is not None:
print(f"window: {feats.shape[0]} dims, nonzero={(feats != 0).sum()}")
break
Expected: window: 328 dims, nonzero=... (nonzero count depends on how many
sensors are connected — all zeros means no sensors are producing data).
Troubleshooting¶
| Symptom | Check |
|---|---|
No /dev/ttyACM0 |
STM32 USB-C is charge-only cable? Try another cable |
| Permission denied | sudo chmod 666 /dev/ttyACM0 or add user to dialout group |
| No frames (just hangs) | Magic sync not found — is the STM32 actually streaming? Check monitor |
| Frames but all zeros | IMUs may be disconnected/failed; check [IMU] N:fail on monitor |
crc=FAIL on most frames |
UART bridge noise — check GND connection, shorten wires |