Fix pan axis drift: soft-iron bug + gyro calibration improvements#244
Open
sorcerdu wants to merge 2 commits into
Open
Fix pan axis drift: soft-iron bug + gyro calibration improvements#244sorcerdu wants to merge 2 commits into
sorcerdu wants to merge 2 commits into
Conversation
The soft-iron compensation computed the 3x3 matrix-vector product in-place: each row overwrote magx/magy/magz before subsequent rows could read the original values. This introduced a heading-dependent bias that contributed to pan axis drift. Fix: use temporary variables for the full multiplication before writing back.
The original EMA-based bias estimator (alpha=0.05) effectively only averaged the last ~20 samples, leaving significant noise in the bias estimate. Combined with the soft-iron bug, this caused ~0.1°/s cumulative drift on the pan axis during normal use. Changes: - Replace EMA with arithmetic mean over 1000 samples (~6.7s at 150Hz), reducing bias noise by ~31x - Add automatic re-calibration: when the device is stationary for >5s, silently re-estimate gyro bias (at most once per 60s) to compensate for thermal drift - Add manual re-calibration on center-reset button press - Clamp Madgwick filter delta-t to prevent integration overshoot from thread scheduling delays Tested on Seeed XIAO BLE Sense: pan drift reduced from ~0.1°/s to <1° over one hour of stationary operation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On Seeed XIAO BLE Sense, the pan (yaw) axis exhibits ~0.1°/s cumulative drift even when the device is completely stationary. While the center-reset button can temporarily correct it, the continuous drift significantly degrades the user experience during extended sessions.
Root Cause Analysis
Two independent sources of drift were identified. Controlled testing on Seeed XIAO BLE Sense (stationary, bench-mounted):
Bug 1: Soft-iron matrix in-place overwrite
The 3×3 soft-iron compensation matrix was applied in-place:
Each row used already-overwritten values from previous rows. Even at rest, magnetometer noise combined with this wrong transform produced a fluctuating heading reference that the Madgwick filter integrated into slow yaw drift.
Bug 2: Noisy gyro bias estimate
The EMA-based bias estimator (
alpha=0.05) effectively only averaged the last ~20 samples, leaving significant noise in the zero-bias estimate. Any residual error in the bias integrates directly into yaw over time.Changes
delta-tto handle thread scheduling delays and 32-bit timer wraparoundTesting Scope
Verified on Seeed XIAO BLE Sense only. The changes are board-agnostic (no platform-specific code modified). Testing on other supported boards (Arduino Nano 33 BLE, ESP32-C3 DevkitM, M5StickC Plus, RPi Pico W, DTQSys HT, Licardo HT) is welcomed from the community.
Notes
GYRO_STABLE_SAMPLESincreased from 400 to 1000, adding ~4s to boot calibration time (now ~6.7s @ 150Hz)gyroCalibrate()using board-specificGYRO_STABLE_DIFF