Debugging¶
Serial monitor¶
Both MCUs output debug info on their native USB CDC ports at 115200 baud.
# STM32
cd firmware/stm32f405
pio device monitor -b 115200
# KB2040
cd firmware/kb2040
pio device monitor -b 115200
Only the STM32 USB CDC carries the data stream (214-byte frames). The KB2040 USB CDC only shows debug output — the IMU frames go over Serial1 (UART1) to the STM32.
LED codes¶
| State | STM32 LED_BUILTIN | KB2040 LED_BUILTIN |
|---|---|---|
Power on, before setup() |
Off (or bootloader blink) | Off |
setup() OK |
On solid | On solid |
setup() failed |
Off (crash) | Off (crash) |
Both boards light the LED at the end of setup(), so LED on = all
initialization passed. If the LED stays off, connect a serial monitor
to see the last log message before the crash.
Error counters¶
The STM32 firmware tracks these in-memory counters (accessible via serial monitor if enabled in the source):
| Counter | Meaning |
|---|---|
imu_errors[N] |
Failed BNO055 reads per IMU #0–3 |
uart_errors |
KB2040 UART CRC failures or magic-sync timeouts |
usb_tx_drops |
Frames dropped because host wasn't draining |
To enable printing, uncomment the debug blocks in main.c loop:
// Uncomment for debug
// Serial.print("ERR imu="); Serial.print(imu_errors[0]);
// Serial.print(" uart="); Serial.print(uart_errors);
// Serial.print(" tx_drop="); Serial.println(usb_tx_drops);
Warning
Printing in the 100 Hz loop adds latency. Use only for debugging; disable for normal operation.
Common issues¶
No IMU detected ([IMU] N:fail)¶
- Check the BNO055 is powered (3.3 V LED on the breakout should be lit)
- Verify ADR pin: GND = 0x28, floating or 3.3 V = 0x29
- Check I²C pull-ups: 4.7 kΩ on SDA and SCL to 3.3 V
- Verify Qwiic cable is fully seated
- Try a different Qwiic port on the same bus (they're all in parallel)
Intermittent IMU reads¶
- Check pull-up resistor values — BNO055 clock stretching needs strong pull-ups
- Reduce I²C bus length; long Qwiic chains increase capacitance
- Lower I²C speed:
Wire.setClock(100000)in setup (trade latency for reliability) - Add a logic analyzer on SDA/SCL to check for signal integrity
UART bridge: [UART] no data¶
- Verify wiring: PC6→GP5, PC7←GP4, GND common
- Check KB2040 is powered and LED is on
- Verify KB2040 serial monitor shows
I2C0 ok, I2C1 ok - Check baud rate: both sides use 921600
- Probe with logic analyzer: GP4(TX) should show 70-byte bursts every 10 ms
USB CDC: host doesn't receive frames¶
- Is another program using the port?
lsof /dev/ttyACM0 - Try
pio device monitorto see if the STM32 is outputting - Permission:
sudo chmod 666 /dev/ttyACM0or add user todialout usb_tx_dropshigh → host too slow to drain. Reduce dashboard framerate or close other serial consumers.
Frames stream but all values are zero¶
This is the firmware's safe fail behavior: when a sensor read fails,
fresh stays cleared and the packet gets zeros. This prevents stale data
from being treated as real. Check the IMU error counters on serial monitor.
Logic analyzer¶
A Saleae Logic 8 (or similar) is invaluable for debugging:
- I²C: Probe SDA/SCL on each bus. Each BNO055 read is ~400 µs.
- UART bridge: Probe GP4(TX) → PC7(RX). Look for 70-byte bursts at 921600 baud every 10 ms.
- USB CDC: Probe D+/D−. Look for 214-byte bursts at 100 Hz.
Set the analyzer to: - I²C: 400 kHz, decode BNO055 register reads (start reg 0x20 = quaternion) - UART: 921600, 8N1, LSB first