The Serpent

// Cursing the Internet since 1998

ESP32’s and the Real-time Clock

Wondering why it's always correct? Read on
Posted March 10, 2024 Hardware

tl;dr

If your ESP32 keeps magically knowing the time, check your IDE isn't automatically syncing the RTC.

I’ve been doing a lot of amateur projects with microcontroller’s lately. It’s a fun hobby which I incorrectly assumed would be quite straightforward yet rewarding. I was half right.

It’s rewarding all right, yet the world of tiny computers is mildly frustrating at times, and I wanted to share a brief article on a topic I could find no answer to online. If you’ve arrived here in frustration as to why your ESP is always able to remember the time, read on.

The Problem

I’m using Thonny with Micropython for most of my projects, thanks to it being very quick and easy to set up. I’ working on a project where the ESP32 needs to keep accurate track of time. I know the ESP32 has a real-time clock onboard, but does it have persistent storage\battery to keep the time while switched off?

The answer is no. It does not. The real-time Clock (RTC) is present, but it has no persistent storage or other power supply to keep track of time. In fact it defaults to an arbitrary Epoch of 1st January 2000 (check with utime.gmtime(0)[0]). Ideally, you’d plug the ESP32 into an external RTC which keeps time, as explained in the Espressif manual:

ESP32 uses two hardware timers for the purpose of keeping system time. System time can be kept by using either one or both of the hardware timers depending on the application’s purpose and accuracy requirements for system time. The two hardware timers are:

RTC timer: This timer allows time keeping in various sleep modes, and can also persist time keeping across any resets (with the exception of power-on resets which reset the RTC timer). The frequency deviation depends on the RTC Timer Clock Sources and affects the accuracy only in sleep modes, in which case the time will be measured at 6.6667 μs resolution.

High-resolution timer: This timer is not available in sleep modes and will not persist over a reset, but has greater accuracy. The timer uses the APB_CLK clock source (typically 80 MHz), which has a frequency deviation of less than ±10 ppm. Time will be measured at 1 μs resolution.

I don’t need high accuracy, so the RTC timer will do nicely, but since it doesn’t persist across power offs, I’ll need to set it myself on boot. No problem, just a bit of extra code.

But when I ran my test code, shortly after boot - the ESP32 always had the correct time!

import machine
import utime

rtc = machine.RTC()
print(rtc.datetime())

now = utime.time()
print("Epoch: " + str(now))
MPY: soft reboot
(2000, 1, 1, 5, 0, 0, 0, 745174)
Epoch: 0
WARNING: Could not determine epoch year (can't import name localtime), assuming 2000

MPY: soft reboot
(2024, 3, 10, 6, 19, 0, 45, 930672)
Epoch: 763412445
>>>

WiFi\Bluetooth were disabled, and I didn’t even have any code to query NTP. So how was the ESP32 gaining correct time?

After lots of trial and error, I finally discovered that the source was the IDE itself, and the following setting was triggering it:

Thonny Settings

Disabling this setting allowed the ESP32 to work as expected, clueless of the time and needing NTP to come to the rescue. Mystery solved.

ESP32's and the Real-time Clock
Posted March 10, 2024
Written by John Payne