Browse Source

add hardware RTC startup sync and periodic system clock correction

AutoDiscoverRTCClock now syncs the fallback system clock from the
hardware RTC immediately after discovery in begin(), and re-syncs
every hour via tick() to correct drift. Invalid RTC readings (before
2024-01-01) are ignored to handle unpowered DS3231 gracefully.
pull/2710/head
Paweł Małecki 1 month ago
parent
commit
cc6031dba7
  1. 17
      src/helpers/AutoDiscoverRTCClock.cpp
  2. 17
      src/helpers/AutoDiscoverRTCClock.h

17
src/helpers/AutoDiscoverRTCClock.cpp

@ -26,6 +26,17 @@ bool AutoDiscoverRTCClock::i2c_probe(TwoWire& wire, uint8_t addr) {
return (error == 0);
}
void AutoDiscoverRTCClock::syncSystemClock() {
uint32_t hw_time = getCurrentTime();
if (hw_time <= 1704067200UL) return; // DS3231 not set or lost power (before 2024-01-01)
uint32_t sys_time = _fallback->getCurrentTime();
int32_t drift = (int32_t)(hw_time - sys_time);
if (drift > 2 || drift < -2) {
_fallback->setCurrentTime(hw_time);
}
}
void AutoDiscoverRTCClock::begin(TwoWire& wire) {
if (i2c_probe(wire, DS3231_ADDRESS)) {
ds3231_success = rtc_3231.begin(&wire);
@ -49,6 +60,12 @@ void AutoDiscoverRTCClock::begin(TwoWire& wire) {
rtc_8130_success = true;
MESH_DEBUG_PRINTLN("RX8130CE: Initialized");
}
_has_hw_rtc = ds3231_success || rv3028_success || rtc_8563_success || rtc_8130_success;
if (_has_hw_rtc) {
syncSystemClock();
_last_sync_ms = millis();
}
}
uint32_t AutoDiscoverRTCClock::getCurrentTime() {

17
src/helpers/AutoDiscoverRTCClock.h

@ -4,12 +4,20 @@
#include <Arduino.h>
#include <Wire.h>
#ifndef RTC_RESYNC_INTERVAL_MS
#define RTC_RESYNC_INTERVAL_MS 3600000UL // re-sync system clock from hardware RTC once per hour
#endif
class AutoDiscoverRTCClock : public mesh::RTCClock {
mesh::RTCClock* _fallback;
bool _has_hw_rtc;
unsigned long _last_sync_ms;
bool i2c_probe(TwoWire& wire, uint8_t addr);
void syncSystemClock();
public:
AutoDiscoverRTCClock(mesh::RTCClock& fallback) : _fallback(&fallback) { }
AutoDiscoverRTCClock(mesh::RTCClock& fallback)
: _fallback(&fallback), _has_hw_rtc(false), _last_sync_ms(0) { }
void begin(TwoWire& wire);
uint32_t getCurrentTime() override;
@ -17,5 +25,12 @@ public:
void tick() override {
_fallback->tick(); // is typically VolatileRTCClock, which now needs tick()
if (_has_hw_rtc) {
unsigned long now = millis();
if ((unsigned long)(now - _last_sync_ms) >= RTC_RESYNC_INTERVAL_MS) {
syncSystemClock();
_last_sync_ms = now;
}
}
}
};

Loading…
Cancel
Save