Skip to content

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)

  1. Check the BNO055 is powered (3.3 V LED on the breakout should be lit)
  2. Verify ADR pin: GND = 0x28, floating or 3.3 V = 0x29
  3. Check I²C pull-ups: 4.7 kΩ on SDA and SCL to 3.3 V
  4. Verify Qwiic cable is fully seated
  5. Try a different Qwiic port on the same bus (they're all in parallel)

Intermittent IMU reads

  1. Check pull-up resistor values — BNO055 clock stretching needs strong pull-ups
  2. Reduce I²C bus length; long Qwiic chains increase capacitance
  3. Lower I²C speed: Wire.setClock(100000) in setup (trade latency for reliability)
  4. Add a logic analyzer on SDA/SCL to check for signal integrity

UART bridge: [UART] no data

  1. Verify wiring: PC6→GP5, PC7←GP4, GND common
  2. Check KB2040 is powered and LED is on
  3. Verify KB2040 serial monitor shows I2C0 ok, I2C1 ok
  4. Check baud rate: both sides use 921600
  5. Probe with logic analyzer: GP4(TX) should show 70-byte bursts every 10 ms

USB CDC: host doesn't receive frames

  1. Is another program using the port? lsof /dev/ttyACM0
  2. Try pio device monitor to see if the STM32 is outputting
  3. Permission: sudo chmod 666 /dev/ttyACM0 or add user to dialout
  4. usb_tx_drops high → 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