RTC: add notion of 'quality' for different time sources

Allow use of mesh based time until a GPS time arrives
1.2-legacy
Kevin Hester 2020-10-08 07:46:20 +08:00
rodzic f00d07baa3
commit 023f1c24fb
7 zmienionych plików z 40 dodań i 31 usunięć

Wyświetl plik

@ -6,8 +6,6 @@ bin/run.sh --set region 8
time only mode time only mode
./bin/run.sh --set gps_operation 3 ./bin/run.sh --set gps_operation 3
set time provisionally from net even if we have gps
ublox parsing failure ublox parsing failure
record power measurements and update spreadsheet record power measurements and update spreadsheet

Wyświetl plik

@ -1,10 +1,10 @@
#include "GPS.h" #include "GPS.h"
#include "NodeDB.h" #include "NodeDB.h"
#include "RTC.h"
#include "configuration.h" #include "configuration.h"
#include "sleep.h" #include "sleep.h"
#include <assert.h> #include <assert.h>
#include "RTC.h"
// If we have a serial GPS port it will not be null // If we have a serial GPS port it will not be null
#ifdef GPS_RX_PIN #ifdef GPS_RX_PIN
@ -23,10 +23,8 @@ uint8_t GPS::i2cAddress = GPS_I2C_ADDRESS;
uint8_t GPS::i2cAddress = 0; uint8_t GPS::i2cAddress = 0;
#endif #endif
GPS *gps; GPS *gps;
bool GPS::setup() bool GPS::setup()
{ {
setAwake(true); // Wake GPS power before doing any init setAwake(true); // Wake GPS power before doing any init
@ -99,7 +97,8 @@ uint32_t GPS::getSleepTime() const
uint32_t t = radioConfig.preferences.gps_update_interval; uint32_t t = radioConfig.preferences.gps_update_interval;
auto op = getGpsOp(); auto op = getGpsOp();
if ((timeSetFromGPS && op == GpsOperation_GpsOpTimeOnly) || (op == GpsOperation_GpsOpDisabled)) bool gotTime = (getRTCQuality() >= RTCQualityGPS);
if ((gotTime && op == GpsOperation_GpsOpTimeOnly) || (op == GpsOperation_GpsOpDisabled))
t = UINT32_MAX; // Sleep forever now t = UINT32_MAX; // Sleep forever now
if (t == UINT32_MAX) if (t == UINT32_MAX)
@ -148,7 +147,7 @@ void GPS::loop()
} }
// If we've already set time from the GPS, no need to ask the GPS // If we've already set time from the GPS, no need to ask the GPS
bool gotTime = timeSetFromGPS || lookForTime(); bool gotTime = (getRTCQuality() >= RTCQualityGPS) || lookForTime();
bool gotLoc = lookForLocation(); bool gotLoc = lookForLocation();
// We've been awake too long - force sleep // We've been awake too long - force sleep
@ -158,7 +157,7 @@ void GPS::loop()
// Once we get a location we no longer desperately want an update // Once we get a location we no longer desperately want an update
// or if we got a time and we are in GpsOpTimeOnly mode // or if we got a time and we are in GpsOpTimeOnly mode
// DEBUG_MSG("gotLoc %d, tooLong %d, gotTime %d\n", gotLoc, tooLong, gotTime); // DEBUG_MSG("gotLoc %d, tooLong %d, gotTime %d\n", gotLoc, tooLong, gotTime);
if ((gotLoc && timeSetFromGPS) || tooLong || (gotTime && getGpsOp() == GpsOperation_GpsOpTimeOnly)) { if ((gotLoc && gotTime) || tooLong || (gotTime && getGpsOp() == GpsOperation_GpsOpTimeOnly)) {
if (gotLoc) if (gotLoc)
hasValidLocation = true; hasValidLocation = true;

Wyświetl plik

@ -45,7 +45,7 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s
t.tm_mon = d.month() - 1; t.tm_mon = d.month() - 1;
t.tm_year = d.year() - 1900; t.tm_year = d.year() - 1900;
t.tm_isdst = false; t.tm_isdst = false;
perhapsSetRTC(t); perhapsSetRTC(RTCQualityGPS, t);
return true; return true;
} else } else

Wyświetl plik

@ -1,9 +1,14 @@
#include "configuration.h"
#include "RTC.h" #include "RTC.h"
#include "configuration.h"
#include <sys/time.h> #include <sys/time.h>
#include <time.h> #include <time.h>
bool timeSetFromGPS; // We try to set our time from GPS each time we wake from sleep static RTCQuality currentQuality = RTCQualityNone;
RTCQuality getRTCQuality()
{
return currentQuality;
}
// stuff that really should be in in the instance instead... // stuff that really should be in in the instance instead...
static uint32_t static uint32_t
@ -17,17 +22,17 @@ void readFromRTC()
if (!gettimeofday(&tv, NULL)) { if (!gettimeofday(&tv, NULL)) {
uint32_t now = millis(); uint32_t now = millis();
DEBUG_MSG("Read RTC time as %ld (cur millis %u) valid=%d\n", tv.tv_sec, now, timeSetFromGPS); DEBUG_MSG("Read RTC time as %ld (cur millis %u) quality=%d\n", tv.tv_sec, now, currentQuality);
timeStartMsec = now; timeStartMsec = now;
zeroOffsetSecs = tv.tv_sec; zeroOffsetSecs = tv.tv_sec;
} }
} }
/// If we haven't yet set our RTC this boot, set it from a GPS derived time /// If we haven't yet set our RTC this boot, set it from a GPS derived time
bool perhapsSetRTC(const struct timeval *tv) bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
{ {
if (!timeSetFromGPS) { if (q > currentQuality) {
timeSetFromGPS = true; currentQuality = q;
DEBUG_MSG("Setting RTC %ld secs\n", tv->tv_sec); DEBUG_MSG("Setting RTC %ld secs\n", tv->tv_sec);
#ifndef NO_ESP32 #ifndef NO_ESP32
settimeofday(tv, NULL); settimeofday(tv, NULL);
@ -41,7 +46,7 @@ bool perhapsSetRTC(const struct timeval *tv)
} }
} }
bool perhapsSetRTC(struct tm &t) bool perhapsSetRTC(RTCQuality q, struct tm &t)
{ {
/* Convert to unix time /* Convert to unix time
The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1, 1970 The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of seconds that have elapsed since January 1, 1970
@ -57,7 +62,7 @@ bool perhapsSetRTC(struct tm &t)
// DEBUG_MSG("Ignoring invalid GPS month=%d, year=%d, unixtime=%ld\n", t.tm_mon, t.tm_year, tv.tv_sec); // DEBUG_MSG("Ignoring invalid GPS month=%d, year=%d, unixtime=%ld\n", t.tm_mon, t.tm_year, tv.tv_sec);
return false; return false;
} else { } else {
return perhapsSetRTC(&tv); return perhapsSetRTC(q, &tv);
} }
} }
@ -68,5 +73,5 @@ uint32_t getTime()
uint32_t getValidTime() uint32_t getValidTime()
{ {
return timeSetFromGPS ? getTime() : 0; return (currentQuality >= RTCQualityFromNet) ? getTime() : 0;
} }

Wyświetl plik

@ -4,16 +4,27 @@
#include "sys/time.h" #include "sys/time.h"
#include <Arduino.h> #include <Arduino.h>
extern bool timeSetFromGPS; // We try to set our time from GPS each time we wake from sleep enum RTCQuality {
/// We haven't had our RTC set yet
RTCQualityNone = 0,
/// Some other node gave us a time we can use
RTCQualityFromNet = 1,
/// Our time is based on our own GPS
RTCQualityGPS = 2
};
RTCQuality getRTCQuality();
/// If we haven't yet set our RTC this boot, set it from a GPS derived time /// If we haven't yet set our RTC this boot, set it from a GPS derived time
bool perhapsSetRTC(const struct timeval *tv); bool perhapsSetRTC(RTCQuality q, const struct timeval *tv);
bool perhapsSetRTC(struct tm &t); bool perhapsSetRTC(RTCQuality q, struct tm &t);
/// Return time since 1970 in secs. Until we have a GPS lock we will be returning time based at zero /// Return time since 1970 in secs. While quality is RTCQualityNone we will be returning time based at zero
uint32_t getTime(); uint32_t getTime();
/// Return time since 1970 in secs. If we don't have a GPS lock return zero /// Return time since 1970 in secs. If quality is RTCQualityNone return zero
uint32_t getValidTime(); uint32_t getValidTime();
void readFromRTC(); void readFromRTC();

Wyświetl plik

@ -152,7 +152,7 @@ bool UBloxGPS::lookForTime()
t.tm_mon = ublox.getMonth(0) - 1; t.tm_mon = ublox.getMonth(0) - 1;
t.tm_year = ublox.getYear(0) - 1900; t.tm_year = ublox.getYear(0) - 1900;
t.tm_isdst = false; t.tm_isdst = false;
perhapsSetRTC(t); perhapsSetRTC(RTCQualityGPS, t);
return true; return true;
} }

Wyświetl plik

@ -140,7 +140,7 @@ void MeshService::handleIncomingPosition(const MeshPacket *mp)
tv.tv_sec = secs; tv.tv_sec = secs;
tv.tv_usec = 0; tv.tv_usec = 0;
perhapsSetRTC(&tv); perhapsSetRTC(RTCQualityFromNet, &tv);
} }
} else { } else {
DEBUG_MSG("Ignoring incoming packet - not a position\n"); DEBUG_MSG("Ignoring incoming packet - not a position\n");
@ -151,12 +151,8 @@ int MeshService::handleFromRadio(const MeshPacket *mp)
{ {
powerFSM.trigger(EVENT_RECEIVED_PACKET); // Possibly keep the node from sleeping powerFSM.trigger(EVENT_RECEIVED_PACKET); // Possibly keep the node from sleeping
// If it is a position packet, perhaps set our clock (if we don't have a GPS of our own, otherwise wait for that to work) // If it is a position packet, perhaps set our clock
if (!gps->isConnected)
handleIncomingPosition(mp); handleIncomingPosition(mp);
else {
DEBUG_MSG("Ignoring incoming time, because we have a GPS\n");
}
if (mp->which_payload == MeshPacket_decoded_tag && mp->decoded.which_payload == SubPacket_user_tag) { if (mp->which_payload == MeshPacket_decoded_tag && mp->decoded.which_payload == SubPacket_user_tag) {
mp = handleFromRadioUser(mp); mp = handleFromRadioUser(mp);