mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-20 17:52:35 +00:00
GPS Power State tidy-up (#4161)
* Refactor GPSPowerState enum Identifies a case where the GPS hardware is awake, but an update is not yet desired * Change terminology * Clear old lock-time prediction on triple press * Use exponential smoothing to predict lock time * Rename averageLockTime to predictedLockTime * Attempt: Send PMREQ with duration 0 on MCU deep-sleep * Attempt 2: Send PMREQ with duration 0 on MCU deep-sleep * Revert "Attempt 2: Send PMREQ with duration 0 on MCU deep-sleep" This reverts commit8b697cd2a4. * Revert "Attempt: Send PMREQ with duration 0 on MCU deep-sleep" This reverts commit9d29ec7603. * Remove unused notifyGPSSleep Observable Handled with notifyDeepSleep, and enable() / disable() * WIP: simplify GPS power management An initial attempt only. * Honor #3e9e0fd * No-op when moving between GPS_IDLE and GPS_ACTIVE * Ensure U-blox GPS is awake to receive indefinite sleep command * Longer pause when waking U-blox to send sleep command * Actually implement soft and hard sleep.. * Dynamically estimate the threshold for GPS_HARDSLEEP * Fallback to GPS_HARDSLEEP, if GPS_SOFTSLEEP unsupported * Move "excessive search time" behavior to scheduler class * Minor logging adjustments * Promote log to warning * Gratuitous buffer clearing on boot * Fix inverted standby pin logic Specifically the standby pin for L76B, L76K and clones Discovered during T-Echo testing: totally broken function, probe method failing. * Remove redundant pin init Now handled by setPowerState * Replace max() with if statements Avoid those platform specific implementations.. * Trunk formatting New round of settings.json changes keep catching me out, have to remember to re-enable my "clang-format" for windows workaround. * Remove some asserts from setPowerState Original aim was to prevent sending a 0 second PMREQ to U-blox hardware as part of a timed sleep (GPS_HARDSLEEP, GPS_SOFTSLEEP). I'm not sure this is super important, and it feels tidier to just allow the 0 second sleeptime here, rather than fudge the sleeptime further up. * Fix an error determining whether GPS_SOFTSLEEP is supported * Clarify a log entry * Set PIN_STANDBY for MCU deep-sleep Required to reach TTGO's advertised 0.25mA sleep current for T-Echo. Without this change: ~6mA.
This commit is contained in:
118
src/gps/GPSUpdateScheduling.cpp
Normal file
118
src/gps/GPSUpdateScheduling.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
#include "GPSUpdateScheduling.h"
|
||||
|
||||
#include "Default.h"
|
||||
|
||||
// Mark the time when searching for GPS position begins
|
||||
void GPSUpdateScheduling::informSearching()
|
||||
{
|
||||
searchStartedMs = millis();
|
||||
}
|
||||
|
||||
// Mark the time when searching for GPS is complete,
|
||||
// then update the predicted lock-time
|
||||
void GPSUpdateScheduling::informGotLock()
|
||||
{
|
||||
searchEndedMs = millis();
|
||||
LOG_DEBUG("Took %us to get lock\n", (searchEndedMs - searchStartedMs) / 1000);
|
||||
updateLockTimePrediction();
|
||||
}
|
||||
|
||||
// Clear old lock-time prediction data.
|
||||
// When re-enabling GPS with user button.
|
||||
void GPSUpdateScheduling::reset()
|
||||
{
|
||||
searchStartedMs = 0;
|
||||
searchEndedMs = 0;
|
||||
searchCount = 0;
|
||||
predictedMsToGetLock = 0;
|
||||
}
|
||||
|
||||
// How many milliseconds before we should next search for GPS position
|
||||
// Used by GPS hardware directly, to enter timed hardware sleep
|
||||
uint32_t GPSUpdateScheduling::msUntilNextSearch()
|
||||
{
|
||||
uint32_t now = millis();
|
||||
|
||||
// Target interval (seconds), between GPS updates
|
||||
uint32_t updateInterval = Default::getConfiguredOrDefaultMs(config.position.gps_update_interval, default_gps_update_interval);
|
||||
|
||||
// Check how long until we should start searching, to hopefully hit our target interval
|
||||
uint32_t dueAtMs = searchEndedMs + updateInterval;
|
||||
uint32_t compensatedStart = dueAtMs - predictedMsToGetLock;
|
||||
int32_t remainingMs = compensatedStart - now;
|
||||
|
||||
// If we should have already started (negative value), start ASAP
|
||||
if (remainingMs < 0)
|
||||
remainingMs = 0;
|
||||
|
||||
return (uint32_t)remainingMs;
|
||||
}
|
||||
|
||||
// How long have we already been searching?
|
||||
// Used to abort a search in progress, if it runs unnaceptably long
|
||||
uint32_t GPSUpdateScheduling::elapsedSearchMs()
|
||||
{
|
||||
// If searching
|
||||
if (searchStartedMs > searchEndedMs)
|
||||
return millis() - searchStartedMs;
|
||||
|
||||
// If not searching - 0ms. We shouldn't really consume this value
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Is it now time to begin searching for a GPS position?
|
||||
bool GPSUpdateScheduling::isUpdateDue()
|
||||
{
|
||||
return (msUntilNextSearch() == 0);
|
||||
}
|
||||
|
||||
// Have we been searching for a GPS position for too long?
|
||||
bool GPSUpdateScheduling::searchedTooLong()
|
||||
{
|
||||
uint32_t maxSearchMs =
|
||||
Default::getConfiguredOrDefaultMs(config.position.position_broadcast_secs, default_broadcast_interval_secs);
|
||||
|
||||
// If broadcast interval set to max, no such thing as "too long"
|
||||
if (maxSearchMs == UINT32_MAX)
|
||||
return false;
|
||||
|
||||
// If we've been searching longer than our position broadcast interval: that's too long
|
||||
else if (elapsedSearchMs() > maxSearchMs)
|
||||
return true;
|
||||
|
||||
// Otherwise, not too long yet!
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// Updates the predicted time-to-get-lock, by exponentially smoothing the latest observation
|
||||
void GPSUpdateScheduling::updateLockTimePrediction()
|
||||
{
|
||||
|
||||
// How long did it take to get GPS lock this time?
|
||||
// Duration between down() calls
|
||||
int32_t lockTime = searchEndedMs - searchStartedMs;
|
||||
if (lockTime < 0)
|
||||
lockTime = 0;
|
||||
|
||||
// Ignore the first lock-time: likely to be long, will skew data
|
||||
|
||||
// Second locktime: likely stable. Use to intialize the smoothing filter
|
||||
if (searchCount == 1)
|
||||
predictedMsToGetLock = lockTime;
|
||||
|
||||
// Third locktime and after: predict using exponential smoothing. Respond slowly to changes
|
||||
else if (searchCount > 1)
|
||||
predictedMsToGetLock = (lockTime * weighting) + (predictedMsToGetLock * (1 - weighting));
|
||||
|
||||
searchCount++; // Only tracked so we can diregard initial lock-times
|
||||
|
||||
LOG_DEBUG("Predicting %us to get next lock\n", predictedMsToGetLock / 1000);
|
||||
}
|
||||
|
||||
// How long do we expect to spend searching for a lock?
|
||||
uint32_t GPSUpdateScheduling::predictedSearchDurationMs()
|
||||
{
|
||||
return GPSUpdateScheduling::predictedMsToGetLock;
|
||||
}
|
||||
Reference in New Issue
Block a user