sl-controls created pull request seb/saltylab-firmware#25

sl-controls
Sat, 28 Feb 2026 17:42:56 -0500

25#feat: Boot gyro calibration — eliminates yaw drift (#21, #23)#

Summary

Issue #21: Yaw drifts ~3.5°/s CCW when stationary — caused by gyro Z-axis bias

Issue #23: No gyro bias calibration on boot — bias varies with temperature so must be measured fresh

On every boot, before the main loop enters, mpu6000_calibrate() samples 1000 gyro readings over ~1s with the board held still, computes the per-axis mean offset in sensor-frame raw LSBs, and stores it. All subsequent mpu6000_read() calls subtract the bias before the CW270 axis transform and scale — so all three axes (pitch rate, roll rate, yaw rate) are corrected.

Changes

src/mpu6000.c: mpu6000_calibrate() — LED1+LED2 solid ON during 1s window, int32 accumulation (avoids float error), resets filter state to zero after; mpu6000_is_calibrated() gate; bias subtraction before axis transform

include/mpu6000.h: declares the two new functions with doc comments

src/main.c: calls mpu6000_calibrate() immediately after mpu6000_init() (before safety_init() so IWDG is not yet running); gates arming and USB streaming on mpu6000_is_calibrated()

include/config.h: GYRO_CAL_SAMPLES=1000

No flash storage — bias recalibrated fresh each boot (temperature-dependent).

Test plan

Build passes

On power-on: LED1+LED2 solid for ~1s, then return to normal blink pattern

Arm command ignored during calibration window

USB stream does not start until calibration complete

Stationary yaw rate ≈ 0 (vs ~3.5°/s before)

Pitch/roll stable at 0° when level and still

Reboot with board tilted: calibration still completes (bias is gyro offset, not accel)

Closes #21, #23.

🤖 Generated with Claude Code