Timezone: Europe/London

.

AboutContactMicropythonESP32Links
Moonlight Systems

ESP32 Real Time Clock

Updated Oct 24

If your project requires a record of what time certain actions are performed, such as when data readings are taken, you are going to need a way to set and keep accurate time within your program.
Fortunately, the ESP32 has a Real Time Clock (RTC) which can be synchronised from an internet NTP server [Network Time Protocol] .

Once set, the RTC keeps time and is also maintained during deepsleep. This is a really useful feature, as you can put the ESP into power saving deepsleep mode, and when it is 'woken up', it is pretty much like a power on reset, except the time has continued to be maintained.
Even more useful, the RTC has some spare bytes available that you can use to store variables, and these will also be maintained during deepsleep.
More about that in a separate article.

There are various time related functions within the library [utime] in micropyton that enable you to work with dates and time relatively easily.
Most of the test below is copied straight from the micropython documentation. https://docs.micropython.org/en/latest/library/time.html

The Epoch:

Time functions use Epoch time, which is an integer of the number of seconds elapsed since a certain date. A calenday date can then be derived from this. The RTC uses epoch integers to set the date in the system.
Unix uses the number of seconds elapsed since 0 hrs, 0 minutes and 0 seconds, January 1st 1970, UTC
The ESP uses the number of seconds elapsed since 0 hrs, 0 minutes and 0 seconds, January 1st 2000 UTC

Functions:

Micropython contains a library called utime that has functions for working with time.
utime.gmtime(seconds) and utime.localtime(seconds) both convert the time (seconds) since the epoch into an 8-tuple which contains
(year, month, mday, hour, minute, second, weekday, yearday) expressed as integers.
gmtime() returns UTC whereas localtime() returns the tuple in local time. If the argument [seconds] is left blank, the time tuple is calculated from localtime as set in the RTC.

Therefore if you reboot an ESP and enter Import utime, then print(utime.gmtime()) the result will be similar to (2000, 1, 1, 0, 0, 3, 5, 1) utime.mktime(0) produces (2000, 1, 1, 0, 0, 0, 5, 1), The 5 and 1 at the end represent weekday and yearday. I never use these, but the docs state weekday is 0-6 for Mon-Sun, yearday is 0-366. In this case 1st Jan 2000 was a friday, and day would be the 1st of the year.

utime.mktime() is the inverse of the above. It's argument is a tuple which expresses time as per localtime and it returns an integer of the number of seconds since the epoch.

So far so good, but now it gets confusing.
To set the RTC of the ESP32, first create and RTC object, ie rtc = RTC(), then run rtc.datetime(args) where args is an 8-tuple as described above. What took me a while to figure out, as I did not study the docs close enough, is that rather than use the tuples described above, which would be convenient, the function datetime() requires something slightly different.
Where the functions above return (year, month, mday, hour, minute, second, weekday, yearday) datetime() requires (year, month, mday, weekday, hours, minutes, seconds, subseconds). Subseconds is platform specific and I presume it means milliseconds, but note the weekday argument is moved to the middle of the tuple.

To set the RTC using an NTP server on the internet, you need an inbuilt library ntptime and the settime() function.
If you run the following:

The RTC is now synchronised with the current UTC time. It doesn't take into account UK summer time / daylight saving time though.
UTC stands for Coordinated Universal time, and is the current time at longitude 0 degrees, [the Greenwich meridian], and supercedes GMT.
During British Summer Time (BST), civil time in the United Kingdom is advanced one hour forward of Greenwich Mean Time (GMT), in effect
changing the time zone from UTC±00:00 to UTC+01:00, so that mornings have one hour less daylight, and evenings one hour more. BST begins
at 01:00 GMT every year on the last Sunday of March and ends at 02:00 BST on the last Sunday of October.
If you are not too fussy about the odd week here or there, you could add the following:

Note because rtc.datetime() uses slightly different arguments, we have to move the weekday position.
Finally, to get a nicely formatted UK timestamp as a string, with leading zeros, here is an example.

Using the TSYNC library
Hopefully the above section gave you an insight into the theory behind using the datetime functions. If you want to take an easy option as opposed to coding your own functions for manipulating the RTC I have created an easy to use library that takes care of all this for you.

TSYNC.py is a library that wraps all these functions together. Called from your code, it can update the RTC from either an NTP server or a GPS module.
The library takes into account your country and whether daylight saving time is used, and your timezone.
Once updated with the current time, you can subsequently request timestamps from the library without connecting to the internet or GPS.
Timestamps are returned in the configuration of your choice. When a timestamp is requested, daylight saving time is taken into account if applicable to your location, and the RTC updated as required to reflect this.

You can view and download the library and supporting demo files from my github repository.
or view the file from this link. View raw code

How accurate is the RTC.
Unfortunately, if the time related operations within your program require a high level of accuracy then you will need to allow for any discrepencies within the RTC of your module.
My project requires several ESPs taking measurements at exactly the same time, so they can be compared accross a large area, and these units run constantly for months.

In tests, I have found the RTC gains between 10 to 25 seconds an hour. It seems to be different for each module, but it certainly is not insignificant.
In a later article I will explain a way to test your individual RTC and maintain a better level of accuracy.

Links

IDE editors for programming ESP boards.
Micropython editors

Micropython functionality and libraries.
Micropython.org

Find the uPython firmware for your board.
uPython firmware for development boards.

ESP32 uPython modules and function examples.
Quick reference for the ESP32

Finding the MAC address

Scanning and connecting to multiple SSIDs

Using an SD card reader breakout board

ESP32 Real Time Clock

The Deepsleep function

Storing variables in the RTC

RTC Tuning

OTA Updating running software without interuption

Future articles

Communication between ESPs

Using an Adafruit GPS module

Hassle free web communication with urequests.py.