Skip to content

Allow setting RTC clock backwards and fix elapsed-time underflow#1349

Open
weebl2000 wants to merge 1 commit intomeshcore-dev:devfrom
weebl2000:allow-older-time
Open

Allow setting RTC clock backwards and fix elapsed-time underflow#1349
weebl2000 wants to merge 1 commit intomeshcore-dev:devfrom
weebl2000:allow-older-time

Conversation

@weebl2000
Copy link
Contributor

@weebl2000 weebl2000 commented Jan 9, 2026

Build firmware: Build from this branch

Problem

The ESP32-S3 RTC drifts 5-10% during deep sleep. After a few days with powersaving ON, the clock can run hours ahead. Previously it was impossible to correct this — all set-time paths rejected timestamps older than the current time with "clock cannot go backwards".

Additionally, when the clock is corrected backwards (e.g. via GPS sync), stored timestamps appear to be in the future, causing unsigned subtraction underflow (wrapping to ~4 billion seconds / 136 years).

Changes

1. Remove forward-only clock restriction

All set-time paths now accept any timestamp:

  • CLI time <epoch> and clock sync commands (CommonCLI.cpp)
  • Companion radio CMD_SET_DEVICE_TIME (companion_radio/MyMesh.cpp)
  • simple_secure_chat setClock()

Only admins/owners can set the time, so replay risk is minimal.

2. Add safeElapsedSecs() helper

New inline function in ArduinoHelpers.h that clamps elapsed time to 0 when a stored timestamp is in the future (i.e. clock was corrected backwards). Applied to:

  • Neighbor "heard X ago" display in simple_repeater
  • UI "received X ago" display in companion_radio
  • TimeSeriesData age calculations in simple_sensor

3. Switch connection expiry to monotonic time

BaseChatMesh connection expiry now uses millis() instead of RTC timestamps, making it immune to clock adjustments from GPS, NTP, or manual sync. Field renamed from last_activity to last_activity_ms to reflect the semantic change.

This assumes light sleep mode where millis() continues to increment (deep sleep resets it, but BaseChatMesh is only used by companion_radio which uses light sleep).

Trade-offs

  • Removing the forward-only guard means a client with a wildly wrong clock could set the node's time to nonsense via clock sync. However, only authenticated admins/owners can issue these commands.
  • safeElapsedSecs() clamps to 0 ("just now") rather than preserving relative ordering — acceptable for display purposes.

@AI7NC
Copy link

AI7NC commented Mar 1, 2026

@weebl2000 does this resolve the year 1970 issue on the v4 or is that a separate issue?

@weebl2000
Copy link
Contributor Author

@weebl2000 does this resolve the year 1970 issue on the v4 or is that a separate issue?

Not sure what issue that is. Can you link me to more info?

@AI7NC
Copy link

AI7NC commented Mar 2, 2026

We seem to see random reboots where the uptime is << than the last time we forced a reboot. Battery life is fine so it's not power related.

Here's two examples showing the really old date. I think bear is running 1.13 with PS hotfix and Deathball is running 1.12 with the PS hotfix. Both are Heltec V4s.

signal-2026-03-01-235815_002 signal-2026-03-01-235706_002

@weebl2000
Copy link
Contributor Author

weebl2000 commented Mar 2, 2026

@AI7NC I think it's unrelated.

https://github.com/meshcore-dev/MeshCore/blob/main/src/helpers/ESP32Board.h#L136

This resets clock to 2024 for clean power on. If the board resets for any other reason than the regular power on path, the clock isn't set so it can go to 0.

To troubleshoot further would be good to have some serial logging.

@AI7NC
Copy link

AI7NC commented Mar 2, 2026

https://github.com/meshcore-dev/MeshCore/blob/main/src/helpers/ESP32Board.h#L136

this should return it to 2024 not 1969/1970 no?

image

@weebl2000
Copy link
Contributor Author

https://github.com/meshcore-dev/MeshCore/blob/main/src/helpers/ESP32Board.h#L136

this should return it to 2024 not 1969/1970 no?

It only resets to 2024 on a clean power on, not if the power on was caused by something else.

@AI7NC
Copy link

AI7NC commented Mar 2, 2026

So unix timecode starts in 1970 (1969 in my time zone). What could be causing these devices to reset the unix time code to zero?

image

@weebl2000
Copy link
Contributor Author

So unix timecode starts in 1970 (1969 in my time zone). What could be causing these devices to reset the unix time code to zero?

Brownout / watchdog timer resets. Is it battery powered, what is tx power set to?

@AI7NC
Copy link

AI7NC commented Mar 2, 2026

Brownout I think is unlikely as we're using >3ah battery packs and have good state of charge and reported voltages on these nodes. Deathball is using an 11v pack stepped down to USB-C 5v/3A with a converter.

Bear is using at least a 5ah battery and is showing a charged battery.

@towerviewcams any ideas?

Edit: We're using software 22dBm TX which is 28dBm on the V4. On power supplies we show this pulling <1A at 4v.

@towerviewcams
Copy link

Brownout I think is unlikely as we're using >3ah battery packs and have good state of charge and reported voltages on these nodes. Deathball is using an 11v pack stepped down to USB-C 5v/3A with a converter.

Bear is using at least a 5ah battery and is showing a charged battery.

@towerviewcams any ideas?

Edit: We're using software 22dBm TX which is 28dBm on the V4. On power supplies we show this pulling <1A at 4v.

All my nodes are 8000mah batts and kick but. I've been testing voltage drop (brown out) and i can take my V4 down to 3.1 and it works fine in my lab. watching it on 3 different batteries and all ok. not even 0.15 change at most. pretty solid.

I truly do think we have something where we have reboots or the clock just dies and its always 31 December 1969....This has showed up in 1.13.......I've also been testing setting changes and also change to very low TX power setting and still does it.

@weebl2000
Copy link
Contributor Author

Edit: We're using software 22dBm TX which is 28dBm on the V4. On power supplies we show this pulling <1A at 4v.

I think this is the culprit. Try setting TX to 17 dBm. If your antenna has a higher SWR too much power simply comes back at the board and it can cause resets. I've seen this happening with bad antennas and high tx power.

Remove the "clock cannot go backwards" restriction from all set-time
paths (CLI `time`, `clock sync`, companion radio CMD_SET_DEVICE_TIME,
and simple_secure_chat). The ESP32-S3 RTC drifts 5-10% during deep
sleep, making backwards correction necessary after even a few days.

Add safeElapsedSecs() helper in ArduinoHelpers.h that clamps elapsed
time to 0 when a stored timestamp appears to be in the future after a
clock correction. Applied to:
- Neighbor "heard X ago" displays in simple_repeater
- UI time displays in companion_radio
- TimeSeriesData calculations in simple_sensor

Switch BaseChatMesh connection expiry from RTC timestamps to monotonic
millis(), making it immune to RTC adjustments from GPS, NTP, or manual
sync. Rename last_activity to last_activity_ms to reflect the change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants