Don't calibrate while device is moving

This commit is contained in:
2026-03-19 20:19:26 +01:00
parent 532ba4f719
commit 5f928d7c92
+46 -7
View File
@@ -34,6 +34,17 @@ static volatile bool pendingWakeRecal = false; // set only when recal is also
// has been off long enough for thermal drift to matter (~5 minutes).
static constexpr unsigned long RECAL_AFTER_LP_MS = 5UL * 60UL * 1000UL;
// Post-wake stillness gate: don't calibrate while the device is moving.
// Each axis of the gyro must stay below RECAL_STILL_DPS for RECAL_STILL_FRAMES
// consecutive loop ticks before calibration fires. If the device keeps moving
// past RECAL_WAIT_MAX_MS, recal is skipped and the pre-sleep bias is kept.
static constexpr float RECAL_STILL_DPS = 10.0f; // deg/s per axis
static constexpr uint8_t RECAL_STILL_FRAMES = 10; // ~100 ms at 10 ms/frame
static constexpr unsigned long RECAL_WAIT_MAX_MS = 3000; // give up after 3 s
static uint8_t recalStillFrames = 0;
static unsigned long recalLastWarnMs = 0;
// I2C helpers - Wire1 at 0x6A (SA0 LOW on XIAO nRF52840 Sense)
static uint8_t lsmRead(uint8_t reg) {
Wire1.beginTransmission(LSM_ADDR);
@@ -238,15 +249,43 @@ bool sleepManagerUpdate(unsigned long nowMs, bool idle, bool bleConnected) {
}
}
// Gyro settling after wake
// Post-wake recalibration — gated on device being still
if (pendingWakeRecal) {
if (nowMs - wakeSettleMs >= 120) {
pendingWakeRecal = false;
wakeSettleMs = 0;
extern void calibrateGyroBias();
calibrateGyroBias();
Serial.println("[SLEEP] Post-wake recal done");
if (nowMs - wakeSettleMs < 120) return true; // initial hardware settle
// Sample gyro magnitude; each axis must be below threshold
float gx = fabsf(imu.readFloatGyroX());
float gy = fabsf(imu.readFloatGyroY());
float gz = fabsf(imu.readFloatGyroZ());
bool still = (gx < RECAL_STILL_DPS && gy < RECAL_STILL_DPS && gz < RECAL_STILL_DPS);
if (!still) {
recalStillFrames = 0;
// Rate-limited log so we don't flood serial while waiting
if (nowMs - recalLastWarnMs >= 500) {
recalLastWarnMs = nowMs;
Serial.print("[SLEEP] Waiting for still: gx="); Serial.print(gx, 1);
Serial.print(" gy="); Serial.print(gy, 1);
Serial.print(" gz="); Serial.println(gz, 1);
}
if (nowMs - wakeSettleMs >= RECAL_WAIT_MAX_MS) {
// Device never settled — keep pre-sleep bias rather than corrupt it
pendingWakeRecal = false;
recalStillFrames = 0;
recalLastWarnMs = 0;
Serial.println("[SLEEP] Recal skipped — device still moving after timeout");
}
return true;
}
// Device is still — accumulate consecutive still frames
if (++recalStillFrames < RECAL_STILL_FRAMES) return true;
pendingWakeRecal = false;
recalStillFrames = 0;
recalLastWarnMs = 0;
calibrateGyroBias();
Serial.println("[SLEEP] Post-wake recal done");
return true;
}