GPS PowerSaving
This commit is contained in:
1 parent
552599fb34
commit
4d9e15d467
4 files changed
+167
-33
No files matched your search
@@ -165,7 +165,11 @@ static RAK12035_SoilMoisture RAK12035;
|
||||
#endif
|
||||
|
||||
#ifdef RAK_WISBLOCK_GPS
|
||||
static uint32_t gpsResetPin = 0;
|
||||
// PowerSaving variant
|
||||
// -1 = no enable pin; out-of-range values are no-ops in pinMode/digitalWrite,
|
||||
// while 0 would be a real GPIO (P0.00 = LFXO crystal on nRF52)
|
||||
static uint32_t gpsResetPin = -1;
|
||||
|
||||
static bool i2cGPSFlag = false;
|
||||
static bool serialGPSFlag = false;
|
||||
#ifndef TELEM_RAK12500_ADDRESS
|
||||
@@ -181,6 +185,9 @@ class RAK12500LocationProvider : public LocationProvider {
|
||||
int _sats = 0;
|
||||
long _epoch = 0;
|
||||
bool _fix = false;
|
||||
|
||||
// PowerSaving variant
|
||||
int _pin_en = -1;
|
||||
public:
|
||||
long getLatitude() override { return _lat; }
|
||||
long getLongitude() override { return _lng; }
|
||||
@@ -193,18 +200,28 @@ public:
|
||||
void begin() override { }
|
||||
void stop() override { }
|
||||
void loop() override {
|
||||
if (ublox_GNSS.getGnssFixOk(8)) {
|
||||
_fix = true;
|
||||
_lat = ublox_GNSS.getLatitude(2) / 10;
|
||||
_lng = ublox_GNSS.getLongitude(2) / 10;
|
||||
_alt = ublox_GNSS.getAltitude(2);
|
||||
_sats = ublox_GNSS.getSIV(2);
|
||||
} else {
|
||||
_fix = false;
|
||||
// PowerSaving variant
|
||||
static long next_gps_update = 0;
|
||||
if ((int32_t)(millis() - next_gps_update) >= 0) {
|
||||
if (ublox_GNSS.getGnssFixOk(8)) {
|
||||
_fix = true;
|
||||
_lat = ublox_GNSS.getLatitude(2) / 10;
|
||||
_lng = ublox_GNSS.getLongitude(2) / 10;
|
||||
_alt = ublox_GNSS.getAltitude(2);
|
||||
_sats = ublox_GNSS.getSIV(2);
|
||||
} else {
|
||||
_fix = false;
|
||||
}
|
||||
_epoch = ublox_GNSS.getUnixEpoch(2);
|
||||
|
||||
next_gps_update = millis() + 1000;
|
||||
}
|
||||
_epoch = ublox_GNSS.getUnixEpoch(2);
|
||||
}
|
||||
bool isEnabled() override { return true; }
|
||||
|
||||
// PowerSaving variant
|
||||
void setPinEn(int pin_en) override { _pin_en = pin_en; }
|
||||
int getPinEn() override { return _pin_en; }
|
||||
};
|
||||
|
||||
static RAK12500LocationProvider RAK12500_provider;
|
||||
@@ -731,8 +748,12 @@ bool EnvironmentSensorManager::setSettingValue(const char* name, const char* val
|
||||
#if ENV_INCLUDE_GPS
|
||||
if (gps_detected && strcmp(name, "gps") == 0) {
|
||||
if (strcmp(value, "0") == 0) {
|
||||
// PowerSaving variant
|
||||
gps_active = false; // Disabled by CLI or App
|
||||
stop_gps();
|
||||
} else {
|
||||
// PowerSaving variant
|
||||
gps_active = true; // Enabled by CLI or App
|
||||
start_gps();
|
||||
}
|
||||
return true;
|
||||
@@ -805,14 +826,10 @@ void EnvironmentSensorManager::rakGPSInit(){
|
||||
Serial1.begin(9600);
|
||||
#endif
|
||||
|
||||
//search for the correct IO standby pin depending on socket used
|
||||
if(gpsIsAwake(WB_IO2)){
|
||||
}
|
||||
else if(gpsIsAwake(WB_IO4)){
|
||||
}
|
||||
else if(gpsIsAwake(WB_IO5)){
|
||||
}
|
||||
else{
|
||||
// search for the correct IO standby pin depending on socket used
|
||||
if (gpsIsAwake(WB_IO2)) {
|
||||
_location->setPinEn(WB_IO2); // WB_IO2 is the power switch for all sensor and IO slots
|
||||
} else {
|
||||
MESH_DEBUG_PRINTLN("No GPS found");
|
||||
gps_active = false;
|
||||
gps_detected = false;
|
||||
@@ -866,13 +883,9 @@ bool EnvironmentSensorManager::gpsIsAwake(uint8_t ioPin){
|
||||
|
||||
_location = &RAK12500_provider;
|
||||
return true;
|
||||
} else if (Serial1.available()) {
|
||||
} else if (Serial1.available()) { // RAK12501 (L76K) on UART
|
||||
MESH_DEBUG_PRINTLN("Serial GPS init correctly and is turned on");
|
||||
#ifdef PIN_GPS_EN
|
||||
if(PIN_GPS_EN){
|
||||
gpsResetPin = PIN_GPS_EN;
|
||||
}
|
||||
#endif
|
||||
gpsResetPin = ioPin; // WB_IO2
|
||||
serialGPSFlag = true;
|
||||
gps_active = true;
|
||||
gps_detected = true;
|
||||
@@ -888,7 +901,16 @@ bool EnvironmentSensorManager::gpsIsAwake(uint8_t ioPin){
|
||||
#endif
|
||||
|
||||
void EnvironmentSensorManager::start_gps() {
|
||||
gps_active = true;
|
||||
// PowerSaving variant
|
||||
if (_location->isPowerSavingEnabled()) {
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef RAK_WISBLOCK_GPS
|
||||
#ifndef RAK_3401
|
||||
pinMode(gpsResetPin, OUTPUT);
|
||||
@@ -906,7 +928,16 @@ void EnvironmentSensorManager::start_gps() {
|
||||
}
|
||||
|
||||
void EnvironmentSensorManager::stop_gps() {
|
||||
gps_active = false;
|
||||
// PowerSaving variant
|
||||
if (_location->isPowerSavingEnabled()) {
|
||||
gps_wake = false; // gps_active is unchanged (true for GPS sleep, false for GPS off)
|
||||
_location->stopTimeSync(); // Stop time sync
|
||||
_location->setNextWake(); // Next time to on
|
||||
} else {
|
||||
gps_active = false;
|
||||
gps_wake = false;
|
||||
}
|
||||
|
||||
#ifdef RAK_WISBLOCK_GPS
|
||||
#ifndef RAK_3401 // rak3401 shouldn't turn off WB_IO2 as it powers the PA
|
||||
pinMode(gpsResetPin, OUTPUT);
|
||||
@@ -927,13 +958,41 @@ void EnvironmentSensorManager::stop_gps() {
|
||||
void EnvironmentSensorManager::loop() {
|
||||
|
||||
#if ENV_INCLUDE_GPS
|
||||
static unsigned long next_gps_update = 0;
|
||||
if (gps_active) {
|
||||
static long next_gps_update = 0;
|
||||
|
||||
// PowerSaving variant
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((!_location->isPowerSavingEnabled() && gps_active) || (_location->isPowerSavingEnabled() && gps_wake)) {
|
||||
_location->loop();
|
||||
}
|
||||
if ((long)(millis() - next_gps_update) > 0) {
|
||||
|
||||
if(gps_active){
|
||||
// PowerSaving variant
|
||||
if ((int32_t)(millis() - next_gps_update) >= 0) {
|
||||
if((!_location->isPowerSavingEnabled() && gps_active) || (_location->isPowerSavingEnabled() && gps_wake)){
|
||||
#ifdef RAK_WISBLOCK_GPS
|
||||
if ((i2cGPSFlag || serialGPSFlag) && _location->isValid()) {
|
||||
node_lat = ((double)_location->getLatitude())/1000000.;
|
||||
@@ -951,8 +1010,12 @@ void EnvironmentSensorManager::loop() {
|
||||
MESH_DEBUG_PRINTLN("lat %f lon %f alt %f", node_lat, node_lon, node_altitude);
|
||||
}
|
||||
#endif
|
||||
|
||||
// In powersaving mode, GPS is on and off. Only update data when GPS is on
|
||||
if(_location->isPowerSavingEnabled()) next_gps_update = millis() + (gps_update_interval_sec * 1000);
|
||||
}
|
||||
next_gps_update = millis() + (gps_update_interval_sec * 1000);
|
||||
|
||||
if(!_location->isPowerSavingEnabled()) next_gps_update = millis() + (gps_update_interval_sec * 1000);
|
||||
}
|
||||
#endif
|
||||
#if ENV_INCLUDE_BME680_BSEC
|
||||
|
||||
@@ -21,6 +21,10 @@ protected:
|
||||
|
||||
bool gps_detected = false;
|
||||
bool gps_active = false;
|
||||
|
||||
// PowerSaving variant
|
||||
bool gps_wake = false; // In PowerSaving, gps_active can have gps_wake true or false
|
||||
|
||||
uint32_t gps_update_interval_sec = 1;
|
||||
|
||||
#if ENV_INCLUDE_GPS
|
||||
|
||||
@@ -9,9 +9,55 @@ class LocationProvider {
|
||||
protected:
|
||||
bool _time_sync_needed = true;
|
||||
|
||||
// PowerSaving variant
|
||||
uint8_t* powersaving_enabled = nullptr;
|
||||
bool _powersaving_enabled_prev = false; // Track previous PowerSaving state
|
||||
unsigned long _wake_duration_secs = 86400; // Full day
|
||||
unsigned long _sleep_duration_secs = 0; // No off
|
||||
unsigned long _next_wake = 0;
|
||||
unsigned long _next_sleep = 0;
|
||||
unsigned long _last_valid_time_sync = 0;
|
||||
|
||||
public:
|
||||
virtual void syncTime() { _time_sync_needed = true; }
|
||||
virtual bool waitingTimeSync() { return _time_sync_needed; }
|
||||
|
||||
// PowerSaving variant
|
||||
virtual void stopTimeSync() { _time_sync_needed = false; }
|
||||
|
||||
virtual void setPowerSavingProfile(uint8_t &enabled, unsigned long wake_duration_secs,
|
||||
unsigned long sleep_duration_secs) {
|
||||
powersaving_enabled = &enabled;
|
||||
_wake_duration_secs = wake_duration_secs;
|
||||
_sleep_duration_secs = sleep_duration_secs;
|
||||
}
|
||||
|
||||
virtual bool isPowerSavingEnabled() const {
|
||||
return powersaving_enabled != nullptr && *powersaving_enabled != 0;
|
||||
}
|
||||
|
||||
virtual void updatePowerSavingSettings(bool gps_wake) {
|
||||
bool powersaving_enabled = isPowerSavingEnabled();
|
||||
|
||||
// PowerSaving changed from OFF to ON
|
||||
if (!_powersaving_enabled_prev && powersaving_enabled) {
|
||||
if (gps_wake) {
|
||||
syncTime(); // Wake when powersaving on
|
||||
setNextSleep(); // On, set next sleep
|
||||
} else {
|
||||
setNextWake(); // Off, set next wake
|
||||
}
|
||||
}
|
||||
|
||||
_powersaving_enabled_prev = powersaving_enabled;
|
||||
}
|
||||
|
||||
virtual void setNextWake() { _next_wake = millis() + _sleep_duration_secs * 1000UL; }
|
||||
virtual unsigned long getNextWake() { return _next_wake; }
|
||||
virtual void setNextSleep() { _next_sleep = millis() + _wake_duration_secs * 1000UL; }
|
||||
virtual unsigned long getNextSleep() { return _next_sleep; }
|
||||
virtual unsigned long getLastValidTimeSync() { return _last_valid_time_sync; }
|
||||
|
||||
virtual long getLatitude() = 0;
|
||||
virtual long getLongitude() = 0;
|
||||
virtual long getAltitude() = 0;
|
||||
@@ -27,6 +73,11 @@ public:
|
||||
virtual void loop() = 0;
|
||||
virtual bool isEnabled() = 0;
|
||||
|
||||
// PowerSaving variant
|
||||
virtual void setPinEn(int pin_en) = 0;
|
||||
virtual int getPinEn() = 0;
|
||||
|
||||
|
||||
// Format compact diagnostics in the caller-provided buffer. Providers that
|
||||
// have more information (for example UART counters) can override this.
|
||||
virtual void formatDiagnostics(char* out, size_t out_size) {
|
||||
|
||||
@@ -157,6 +157,15 @@ public :
|
||||
}
|
||||
}
|
||||
|
||||
// PowerSaving variant
|
||||
void setPinEn(int pin_en) override {
|
||||
_pin_en = pin_en;
|
||||
}
|
||||
|
||||
int getPinEn() override {
|
||||
return _pin_en;
|
||||
}
|
||||
|
||||
void syncTime() override { nmea.clear(); LocationProvider::syncTime(); }
|
||||
long getLatitude() override { return nmea.getLatitude(); }
|
||||
long getLongitude() override { return nmea.getLongitude(); }
|
||||
@@ -166,7 +175,9 @@ public :
|
||||
return alt;
|
||||
}
|
||||
long satellitesCount() override { return nmea.getNumSatellites(); }
|
||||
bool isValid() override { return nmea.isValid(); }
|
||||
|
||||
// PowerSaving variant
|
||||
bool isValid() override { return nmea.isValid() && nmea.getYear() < 2030; } // TODO: Pending better validation
|
||||
|
||||
long getTimestamp() override {
|
||||
DateTime dt(nmea.getYear(), nmea.getMonth(),nmea.getDay(),nmea.getHour(),nmea.getMinute(),nmea.getSecond());
|
||||
@@ -247,9 +258,14 @@ public :
|
||||
_clock->setCurrentTime(getTimestamp());
|
||||
_time_sync_needed = false;
|
||||
_last_time_sync = millis();
|
||||
|
||||
// PowerSaving variant
|
||||
_last_valid_time_sync = _clock->getCurrentTime();
|
||||
}
|
||||
}
|
||||
if (isValid()) {
|
||||
|
||||
// PowerSaving variant
|
||||
if (isValid() && satellitesCount() >= 5) {
|
||||
time_valid ++;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user