ComputingInternet Of Things

ESP32 Tricks and Tips

Time Keeping

The ESP32 docs say you can set the RTC to keep time in deep sleep (“RTC clock is used to maintain accurate time when chip is in deep sleep mode”). This post details how to restore normal system time from the RTC in Arduino.

Time keeping is a bit confusing in C. There is my summary:

Pasted 3
Pasted 3

Deep sleep is documented for Arduino. Wall-clock versus system-clock is explained here. Basically: use millis() for loop timing.

Our strategy, to limit WiFi/NTP use, is:

  1. On reboot, or once daily: turn on WiFi. Use NTP to get the current wall-clock time. This is used for timestamps of measurements.
  2. On reanimate (i.e. after deep sleep), set the system time by asking the RTC.
  3. Use millis() for loop timing function where possible. That is, don’t rely on gettimeofday() or time() to provide monotonic time.

Although you can use system calls with the ESP32:

settimeofday(&ntpTime,NULL); // set system time
gettimeofday(); // get system time to sec+usec
time(NULL); // get system time to sec

… I used “eztime” which is rather heavyweight but provides NTP sync and nice formatting.

The key calls are to keep system time across deep sleeps are:

// Store these in RTC memory
namespace rtc {
RTC_DATA_ATTR int bootCount = 0;
RTC_DATA_ATTR struct timeval rtcStartTime = {  .tv_sec = 0, .tv_usec = 0} ;
RTC_DATA_ATTR struct timeval lastNTPSync = {  .tv_sec = 0, .tv_usec = 0} ;

void setup() {
  // Get RTC time in USec
  rtcUSec = rtc_time_slowclk_to_us(rtc_time_get(), _rtcClkCal);
  // Get current rtc offset (s,us) from the rtc
  rtc.tv_sec = long (rtcUSec / uS_TO_S_FACTOR);
  rtc.tv_usec = rtcUSec % uS_TO_S_FACTOR;
  // Add to saved delta (can use timeradd() instead)
  newTime.tv_sec = rtc::rtcStartTime.tv_sec + rtc.tv_sec;
  newTime.tv_usec = rtc::rtcStartTime.tv_usec + rtc.tv_usec;
  // Set ez and system times
  UTC.setTime(newTime.tv_sec, newTime.tv_usec / 1000);
  settimeofday(&newTime, NULL);

This can be wrapped in a nice class, TimeKeeper, which derives from Timezone (eztime) and encapsulates the RTC_DATA save.

Leave a Reply

Your email address will not be published. Required fields are marked *