From a27e78e4da1389055b6dd16ce473112d25c8a5cd Mon Sep 17 00:00:00 2001 From: Kevin Le Date: Sun, 27 Sep 2026 23:33:01 +0700 Subject: [PATCH] Added GPS PowerSaving v2 for some boards --- variants/heltec_mesh_solar/target.cpp | 39 +++++++------ variants/heltec_tracker/target.cpp | 38 +++++++----- variants/meshtracker_x1/target.cpp | 83 +++++++++++++++++++++++---- variants/meshtracker_x1/target.h | 1 + variants/t1000-e/target.cpp | 4 +- 5 files changed, 121 insertions(+), 44 deletions(-) diff --git a/variants/heltec_mesh_solar/target.cpp b/variants/heltec_mesh_solar/target.cpp index e85a62be5..aef713f30 100644 --- a/variants/heltec_mesh_solar/target.cpp +++ b/variants/heltec_mesh_solar/target.cpp @@ -31,12 +31,13 @@ mesh::LocalIdentity radio_new_identity() { void SolarSensorManager::start_gps() { if (!gps_active) { - gps_active = true; - if (_location->isPowerSavingEnabled()) { - gps_wake = true; // gps_active is true + gps_wake = true; // gps_active is true _location->syncTime(); // Clear GPS data and force sync time _location->setNextSleep(); // Next time to off + } else { + gps_active = true; + gps_wake = true; } _location->begin(); @@ -84,24 +85,28 @@ void SolarSensorManager::loop() { static long next_gps_update = 0; // PowerSaving - if (_location->isPowerSavingEnabled() && gps_detected) { - if (gps_wake && ((int32_t)(millis() - _location->getNextSleep()) >= 0 || - !_location->waitingTimeSync())) { // Time to off or GPS set + if (_location->isPowerSavingEnabled() && gps_detected && gps_active) { + // Handle change in PowerSaving mode + _location->updatePowerSavingSettings(gps_wake); + + if (gps_wake) { + // GPS is awake: check whether it should sleep if ((int32_t)(millis() - _location->getNextSleep()) >= 0) { POWERSAVING_DEBUG_PRINTLN("GPS wake timeout. Enter sleep"); + stop_gps(); } else if (!_location->waitingTimeSync()) { POWERSAVING_DEBUG_PRINTLN("GPS set. Enter sleep early"); + stop_gps(); + } + } else { + // GPS is asleep: check whether it should wake + if ((int32_t)(millis() - _location->getNextWake()) >= 0) { + POWERSAVING_DEBUG_PRINTLN("GPS sleep timeout. Wakeup."); + start_gps(); + } else if (_location->waitingTimeSync()) { + POWERSAVING_DEBUG_PRINTLN("CLI gps sync. Wakeup"); + start_gps(); } - - stop_gps(); - } else if (!gps_wake && ((int32_t)(millis() - _location->getNextWake()) >= 0)) { // Time to on - POWERSAVING_DEBUG_PRINTLN("GPS sleep timeout. Wakeup."); - - start_gps(); - } else if (!gps_wake && _location->waitingTimeSync()) { // On for "gps sync" - POWERSAVING_DEBUG_PRINTLN("CLI gps sync. Wakeup"); - - start_gps(); } } @@ -145,8 +150,10 @@ const char* SolarSensorManager::getSettingValue(int i) const { bool SolarSensorManager::setSettingValue(const char* name, const char* value) { if (gps_detected && strcmp(name, "gps") == 0) { if (strcmp(value, "0") == 0) { + gps_active = false; // Disabled by CLI or App stop_gps(); } else { + gps_active = true; // Enabled by CLI or App start_gps(); } return true; diff --git a/variants/heltec_tracker/target.cpp b/variants/heltec_tracker/target.cpp index ab1b391ed..2ae85d6d5 100644 --- a/variants/heltec_tracker/target.cpp +++ b/variants/heltec_tracker/target.cpp @@ -45,12 +45,14 @@ mesh::LocalIdentity radio_new_identity() { void HWTSensorManager::start_gps() { if (!gps_active) { _location->begin(); // Claims periph_power via RefCountedDigitalPin - gps_active = true; if (_location->isPowerSavingEnabled()) { - gps_wake = true; // gps_active is true + gps_wake = true; // gps_active is unchanged (true for GPS sleep, false for GPS off) _location->syncTime(); // Clear GPS data and force sync time _location->setNextSleep(); // Next time to off + } else { + gps_active = true; + gps_wake = true; } Serial1.println("$CFGSYS,h35155*68"); // Configure GPS for all constellations @@ -89,24 +91,28 @@ void HWTSensorManager::loop() { static long next_gps_update = 0; // PowerSaving - if (_location->isPowerSavingEnabled()) { - if (gps_wake && ((int32_t)(millis() - _location->getNextSleep()) >= 0 || - !_location->waitingTimeSync())) { // Time to off or GPS set + if (_location->isPowerSavingEnabled() && gps_active) { + // Handle change in PowerSaving mode + _location->updatePowerSavingSettings(gps_wake); + + if (gps_wake) { + // GPS is awake: check whether it should sleep if ((int32_t)(millis() - _location->getNextSleep()) >= 0) { POWERSAVING_DEBUG_PRINTLN("GPS wake timeout. Enter sleep"); + stop_gps(); } else if (!_location->waitingTimeSync()) { POWERSAVING_DEBUG_PRINTLN("GPS set. Enter sleep early"); + stop_gps(); + } + } else { + // GPS is asleep: check whether it should wake + if ((int32_t)(millis() - _location->getNextWake()) >= 0) { + POWERSAVING_DEBUG_PRINTLN("GPS sleep timeout. Wakeup."); + start_gps(); + } else if (_location->waitingTimeSync()) { + POWERSAVING_DEBUG_PRINTLN("CLI gps sync. Wakeup"); + start_gps(); } - - stop_gps(); - } else if (!gps_wake && ((int32_t)(millis() - _location->getNextWake()) >= 0)) { // Time to on - POWERSAVING_DEBUG_PRINTLN("GPS sleep timeout. Wakeup."); - - start_gps(); - } else if (!gps_wake && _location->waitingTimeSync()) { // On for "gps sync" - POWERSAVING_DEBUG_PRINTLN("CLI gps sync. Wakeup"); - - start_gps(); } } @@ -145,8 +151,10 @@ const char* HWTSensorManager::getSettingValue(int i) const { bool HWTSensorManager::setSettingValue(const char* name, const char* value) { if (strcmp(name, "gps") == 0) { if (strcmp(value, "0") == 0) { + gps_active = false; // Disabled by CLI or App stop_gps(); } else { + gps_active = true; // Enabled by CLI or App start_gps(); } return true; diff --git a/variants/meshtracker_x1/target.cpp b/variants/meshtracker_x1/target.cpp index d6d548b51..95007fa33 100644 --- a/variants/meshtracker_x1/target.cpp +++ b/variants/meshtracker_x1/target.cpp @@ -26,7 +26,15 @@ mesh::LocalIdentity radio_new_identity() { } void MeshTrackerX1SensorManager::start_gps() { - gps_active = true; + if (_nmea->isPowerSavingEnabled()) { + gps_wake = true; // gps_active is unchanged (true for GPS sleep, false for GPS off) + _nmea->syncTime(); // Clear GPS data and force sync time + _nmea->setNextSleep(); // Next time to off + } else { + gps_active = true; + gps_wake = true; + } + // this init sequence comes from seeed examples and deals with all gps pins pinMode(GPS_EN, OUTPUT); digitalWrite(GPS_EN, HIGH); @@ -47,7 +55,15 @@ void MeshTrackerX1SensorManager::start_gps() { } void MeshTrackerX1SensorManager::sleep_gps() { - gps_active = false; + if (_nmea->isPowerSavingEnabled()) { + gps_wake = false; // gps_active is unchanged (true) even the GPS sleep (e.g: off) + _nmea->stopTimeSync(); // Stop time sync + _nmea->setNextWake(); // Next time to on + } else { + gps_active = false; + gps_wake = false; // When GPS is off, wake is false to be sure + } + digitalWrite(GPS_VRTC_EN, HIGH); // keep RTC alive for faster fix on wake digitalWrite(GPS_EN, LOW); digitalWrite(GPS_RESET, LOW); @@ -56,7 +72,15 @@ void MeshTrackerX1SensorManager::sleep_gps() { } void MeshTrackerX1SensorManager::stop_gps() { - gps_active = false; + if (_nmea->isPowerSavingEnabled()) { + gps_wake = false; // gps_active is unchanged (true) even the GPS sleep (e.g: off) + _nmea->stopTimeSync(); // Stop time sync + _nmea->setNextWake(); // Next time to on + } else { + gps_active = false; + gps_wake = false; // When GPS is off, wake is false to be sure + } + digitalWrite(GPS_VRTC_EN, LOW); digitalWrite(GPS_EN, LOW); digitalWrite(GPS_RESET, LOW); @@ -95,16 +119,51 @@ bool MeshTrackerX1SensorManager::querySensors(uint8_t requester_permissions, Cay void MeshTrackerX1SensorManager::loop() { static long next_gps_update = 0; + // PowerSaving + if (_nmea->isPowerSavingEnabled() && gps_active) { + // Handle change in PowerSaving mode + _nmea->updatePowerSavingSettings(gps_wake); - _nmea->loop(); - - if (millis() > next_gps_update) { - if (gps_active && _nmea->isValid()) { - node_lat = ((double)_nmea->getLatitude())/1000000.; - node_lon = ((double)_nmea->getLongitude())/1000000.; - node_altitude = ((double)_nmea->getAltitude()) / 1000.0; + if (gps_wake) { + // GPS is awake: check whether it should sleep + if ((int32_t)(millis() - _nmea->getNextSleep()) >= 0) { + POWERSAVING_DEBUG_PRINTLN("GPS wake timeout. Enter sleep"); + sleep_gps(); + } else if (!_nmea->waitingTimeSync()) { + POWERSAVING_DEBUG_PRINTLN("GPS set. Enter sleep early"); + sleep_gps(); + } + } else { + // GPS is asleep: check whether it should wake + if ((int32_t)(millis() - _nmea->getNextWake()) >= 0) { + POWERSAVING_DEBUG_PRINTLN("GPS sleep timeout. Wakeup."); + start_gps(); + } else if (_nmea->waitingTimeSync()) { + POWERSAVING_DEBUG_PRINTLN("CLI gps sync. Wakeup"); + start_gps(); + } } - next_gps_update = millis() + 1000; + } + + if ((!_nmea->isPowerSavingEnabled() && gps_active) || (_nmea->isPowerSavingEnabled() && gps_wake)) { + _nmea->loop(); + } + + if ((int32_t)(millis() - next_gps_update) >= 0) { + if ((!_nmea->isPowerSavingEnabled() && gps_active) || (_nmea->isPowerSavingEnabled() && gps_wake)) { + if (_nmea->isValid()) { + node_lat = ((double)_nmea->getLatitude()) / 1000000.; + node_lon = ((double)_nmea->getLongitude()) / 1000000.; + MESH_DEBUG_PRINTLN("lat %f lon %f", node_lat, node_lon); + node_altitude = ((double)_nmea->getAltitude()) / 1000.0; + MESH_DEBUG_PRINTLN("lat %f lon %f alt %f", node_lat, node_lon, node_altitude); + } + + // In powersaving mode, GPS is on and off. Only update data when GPS is on + if (_nmea->isPowerSavingEnabled()) next_gps_update = millis() + 1000; + } + + if (!_nmea->isPowerSavingEnabled()) next_gps_update = millis() + 1000; } } @@ -122,8 +181,10 @@ const char* MeshTrackerX1SensorManager::getSettingValue(int i) const { bool MeshTrackerX1SensorManager::setSettingValue(const char* name, const char* value) { if (strcmp(name, "gps") == 0) { if (strcmp(value, "0") == 0) { + gps_active = false; // Disabled by CLI or App sleep_gps(); // sleep for faster fix ! } else { + gps_active = true; // Enabled by CLI or App start_gps(); } return true; diff --git a/variants/meshtracker_x1/target.h b/variants/meshtracker_x1/target.h index 9741efb6a..6138a7ee5 100644 --- a/variants/meshtracker_x1/target.h +++ b/variants/meshtracker_x1/target.h @@ -15,6 +15,7 @@ class MeshTrackerX1SensorManager: public SensorManager { bool gps_active = false; + bool gps_wake = false; // In PowerSaving, gps_active can have gps_wake true or false bool baro_ok = false; Adafruit_SPA06_003 spa06; LocationProvider * _nmea; diff --git a/variants/t1000-e/target.cpp b/variants/t1000-e/target.cpp index 2cfec93b7..2e3102398 100644 --- a/variants/t1000-e/target.cpp +++ b/variants/t1000-e/target.cpp @@ -85,8 +85,8 @@ void T1000SensorManager::start_gps() { _nmea->syncTime(); // Clear GPS data and force sync time _nmea->setNextSleep(); // Next time to off } else { - gps_active = true; - gps_wake = true; + gps_active = true; + gps_wake = true; } //_nmea->begin();