Add motion tracking and calibration features

This commit is contained in:
Nik Rozman committed 2026-10-14 09:37:41 +02:00
1 parent 4aa369ca73
commit aab61a2b7b
13 files changed
+735 -169

No files matched your search

+11 -18
View File
@@ -7,7 +7,7 @@
#define FEATURE_IMU_STREAM
// #define FEATURE_TAP_DETECTION
#define FEATURE_TEMP_COMPENSATION
#define FEATURE_AUTO_RECAL
#define FEATURE_AUTO_RECAL // continuous gyro bias tracking while at rest
#define FEATURE_BATTERY_MONITOR
#define FEATURE_BOOT_LOOP_DETECT
#define FEATURE_PHYSICAL_BUTTONS
@@ -55,7 +55,7 @@
// Persistence
#define CONFIG_FILENAME "/imu_mouse_cfg.bin"
#define CONFIG_MAGIC 0xDEAD123EUL
#define CONFIG_MAGIC 0xDEAD123FUL
// Physical button pin assignments (hardcoded - set to 0xFF to disable a button)
// Valid pin numbers: 0-10 (Arduino D0-D10 on XIAO nRF52840 Sense)
@@ -69,7 +69,7 @@
// via the web UI and persisted in flash. Bits not listed here are reserved = 0.
#define FLAG_TAP_ENABLED 0x01 // Tap detection active (requires restart)
#define FLAG_TEMP_COMP_ENABLED 0x02 // Temperature gyro-drift compensation
#define FLAG_AUTO_RECAL_ENABLED 0x04 // Auto-recalibrate after long idle
#define FLAG_AUTO_RECAL_ENABLED 0x04 // Continuously re-estimate gyro bias whenever the remote is at rest
#define FLAG_ALL_DEFAULT (FLAG_TAP_ENABLED | FLAG_TEMP_COMP_ENABLED | FLAG_AUTO_RECAL_ENABLED)
// Enums
@@ -91,12 +91,12 @@ enum TapAction : uint8_t {
struct Config {
uint32_t magic;
float sensitivity;
float deadZone;
float deadZone; // soft dead zone radius on smoothed angular speed, rad/s
float accelStrength;
CurveType curve;
uint8_t axisFlip;
ChargeMode chargeMode;
uint8_t tapThreshold; // 1–31 → REG_TAP_THS_6D bits[4:0]; 1 LSB = 62.5 mg at ±2g
uint8_t tapThreshold; // 1–31 → REG_TAP_THS_6D bits[4:0]; 1 LSB = 125 mg at ±4g
TapAction tapAction; // what a double-tap does
uint8_t tapKey; // HID keycode (used when tapAction == TAP_ACTION_KEY)
uint8_t tapMod; // HID modifier byte (used when tapAction == TAP_ACTION_KEY)
@@ -145,12 +145,12 @@ extern TelemetryPacket telem;
// ImuPacket (14 bytes)
#ifdef FEATURE_IMU_STREAM
struct __attribute__((packed)) ImuPacket {
int16_t gyroX_mDPS; // [0] pitch axis (nod up/down → cursor Y)
int16_t gyroZ_mDPS; // [2] yaw axis (pan left/right → cursor X)
int16_t gyroX_mDPS; // [0] pitch rate, roll-compensated (nod up/down → cursor Y)
int16_t gyroZ_mDPS; // [2] yaw rate, roll-compensated (pan left/right → cursor X)
int16_t accelX_mg; // [4]
int16_t accelY_mg; // [6]
int16_t accelZ_mg; // [8]
int8_t moveX; // [10]
int8_t moveX; // [10] cursor counts sent since the previous packet
int8_t moveY; // [11]
uint8_t flags; // [12] bit0=idle bit1=singleTap bit2=doubleTap
uint8_t _pad; // [13]
@@ -159,9 +159,9 @@ static_assert(sizeof(ImuPacket) == 14, "ImuPacket must be 14 bytes");
#endif
// Tuning constants
extern const int LOOP_RATE_MS;
extern const int IMU_POLL_MS;
extern const int BIAS_SAMPLES;
extern const int IDLE_FRAMES;
extern const unsigned long IDLE_MS;
extern const unsigned long BATT_REPORT_MS;
extern const unsigned long TELEMETRY_MS;
extern const unsigned long HEARTBEAT_MS;
@@ -179,13 +179,8 @@ extern const float BATT_CRITICAL;
#ifdef FEATURE_TEMP_COMPENSATION
extern const float TEMP_COMP_COEFF_DPS_C;
#endif
#ifdef FEATURE_AUTO_RECAL
extern const unsigned long AUTO_RECAL_MS;
#endif
// Global state
extern float accumX, accumY;
extern float biasGX, biasGY, biasGZ;
extern float calTempC;
extern float cachedTempC;
@@ -207,9 +202,7 @@ extern bool pendingReset;
extern bool pendingOTA;
#endif
extern ChargeStatus lastChargeStatus;
extern int idleFrames;
extern unsigned long idleStartMs;
extern unsigned long lastTime;
extern unsigned long lastMotionMs;
extern unsigned long lastBattTime;
extern unsigned long lastHeartbeat;
extern unsigned long lastTelemetry;