mirror of
https://github.com/ALLFATHER-BV/wadamesh.git
synced 2026-09-26 20:18:04 +00:00
Two answers to "does the compass app matter for battery life", both yes-ish and both now fixed. The driver put the QMC6309 into normal mode at boot and left it there, so it converted continuously from power-on whether or not anything read it: ~1 mA at 100 Hz / OSR 8, forever, on a 2300 mAh battery. It is now parked in suspend after configuration and woken on demand, with m9CompassIdleTick() (called from the M9's existing per-loop branch) suspending it again two seconds after the last read. Waking is a single register write since suspend preserves the configuration; the waking call reports "nothing fresh" and the caller's next poll gets data, which callers already handle because the chip may be absent. Separately, lv_timer_handler() runs unconditionally, so a Lua app's timer kept firing while the display slept -- GPS Compass polled the magnetometer at 10 Hz into a dark screen, which would have held the sensor awake even after the fix above. The host now skips the tick while the screen is off and resumes on wake; dt comes from millis(), so an app sees one long frame rather than a broken clock. Documented on the SDK page. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
53 lines
2.7 KiB
C++
53 lines
2.7 KiB
C++
#pragma once
|
|
|
|
// ThinkNode M9 magnetometer — QST QMC6309 on the peripheral I2C bus (Wire,
|
|
// SDA=7 / SCL=6) at 7-bit address 0x7C. The chip sits on the GPIO18 peripheral
|
|
// rail with the LCD/GPS, which ThinkNodeM9Board::begin() claims for the whole
|
|
// runtime, so it is powered whenever the firmware runs.
|
|
//
|
|
// This is deliberately a dumb sensor reader: it hands out the raw field vector
|
|
// in Gauss, sensor frame, uncalibrated. Hard-iron calibration, the sensor-to-
|
|
// screen axis mapping (not documented anywhere — Meshtastic's own M9 driver
|
|
// marks its heading offset "must be verified on real hardware" and never uses
|
|
// it) and the heading maths live in the consumer (the GPS Compass Lua app),
|
|
// where they can be adjusted and persisted per user without a firmware cut.
|
|
//
|
|
// Register map (QMC6309 datasheet Rev A, cross-checked against SlimeVR,
|
|
// madflight and the emfcamp Tildagon drivers — NOT against SensorLib, whose
|
|
// setOutputDataRate() writes the ODR into the wrong register):
|
|
// 0x00 chip id (0x90) 0x01..0x06 X/Y/Z int16 little-endian
|
|
// 0x09 status: bit0 DRDY (cleared by reading 0x09), bit1 OVFL
|
|
// 0x0A CTRL1: OSR2[7:5] OSR1[4:3] MODE[1:0] (00 suspend, 01 normal, 11 cont.)
|
|
// 0x0B CTRL2: SOFT_RST[7] ODR[6:4] RNG[3:2] SET/RESET[1:0]
|
|
// Sensitivity at the ±32 G range used here: 1000 LSB/G (1 mG per count).
|
|
#if defined(HAS_M9_COMPASS) && defined(ESP32)
|
|
|
|
#include <stdint.h>
|
|
|
|
class TwoWire;
|
|
|
|
/** Probe + configure the chip on `w`. Safe to call when the chip is absent or
|
|
* not yet out of power-on reset: the read path re-probes on its own. Logs one
|
|
* line to Serial either way (matches the keyboard bring-up style). */
|
|
void m9CompassBegin(TwoWire& w);
|
|
|
|
/** True once the chip has answered with its id and taken the configuration. */
|
|
bool m9CompassPresent();
|
|
|
|
/** Latest field vector in Gauss, sensor frame, uncalibrated. Reads the chip
|
|
* synchronously when a new sample is ready (three short I2C transactions,
|
|
* well under 1 ms at 100 kHz on a healthy bus), otherwise returns the cached
|
|
* sample while it is younger than a second. False = no chip, bus error, or
|
|
* nothing fresh. `overflow` (optional) is set when the chip flagged the
|
|
* sample as saturated (an axis beyond ±32000 counts): the values are still
|
|
* returned so a consumer can show "away from magnets" rather than "no
|
|
* compass", but they are not a usable heading. */
|
|
bool m9CompassRead(float* x_gauss, float* y_gauss, float* z_gauss, bool* overflow = nullptr);
|
|
|
|
/** Call periodically (cheap: one comparison until it acts). Suspends the chip
|
|
* a couple of seconds after the last read, so it only draws its ~1 mA while
|
|
* something is actually using the compass. The next read wakes it. */
|
|
void m9CompassIdleTick();
|
|
|
|
#endif
|