A real-time clock (RTC) is a computer clock to keep time and is one of the more popular microcontroller features. Microcontrollers without a built-in RTC require an external RTC chip for keeping time. Typically, mid-segment to high-end microcontrollers have a built-in RTC because time-keeping is necessary for several embedded applications.
RTCs count seconds, minutes, hours, days, months, and years. These can also be used for the current date and to measure time intervals.
MicroPython’s machine module provides an RTC class that configures and uses a built-in RTC-supported port. MicroPython also provides a module “ntptime” that synchronizes time with the help of a clock source or server.
In this article, we’ll explore MicroPython’s RTC module and learn how to set and get the time in ESP8266 and ESP32.
MicroPython consists of several hardware-specific modules. The machine module is the most important one because it manages the basic hardware functionalities and built-in hardware peripherals of the supported ports.
The module has several classes for controlling the digital input/output, output signals from external devices, pulse width modulation, analog to digital conversion, ADC peripherals, UART, SPI, I2C, I2S, Timer, RTC, watchdog timer, and the SD card.
MicroPython’s machine module for the RTC class is used to configure and manage the real-time clock of the supported ports. It’s imported in a MicroPython script by using this statement:
from machine import rtc
Alternatively, the RTC class is automatically imported when the machine module is imported as follows:
After the module is imported, you must instantiate an object of the RTC class with the help of the constructor method. The constructor method of RTC class has this prototype:
class machine.RTC(id=0, …)
The constructor takes the “id” parameter, which identifies the built-in RTC (in case there are multiple RTCs in the supported port). If there’s only one, it’s not necessary to pass the id as an argument. The other parameters in the constructor method used to set time in the RTC are optional.
This is a valid example of instantiating an RTC object:
rtc = machine.RTC()
The RTC class provides these methods to maintain the date-time settings…
RTC.init(datetime): used to initialize the RTC object. It takes the current date-time as the argument. The data-time is passed as a 8-tuple with this format: (year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]]). The tuple must have the year, month, and day elements. The others are optional and may or may not be passed depending on the application.
RTC.datetime([datetimetuple]): used to get or set the date and time of the RTC.
- If called without arguments, this method returns the current date-time maintained by RTC in the form of an 8-tuple.
- If used to set the date-time, the method takes an 8-tuple as the argument.
The tuple must follow this format: (year, month, day, weekday, hours, minutes, seconds, subseconds). Depending on the port, the subseconds in the tuple can be milliseconds or microseconds.
RTC.deinit(): resets the RTC time to January 1, 2015, and restarts the RTC.
RTC.now(): gets the current date-time from the RTC, which is returned as an 8-tuple.
The RTC class provides these methods to configure the alarm settings…
RTC.alarm(id, time, *, repeat=False): used to set the alarm in the RTC. The id must be passed as an argument if there are multiple built-in RTCs in a port; otherwise, there’s no need. The time can be passed as the milliseconds value or as the date-time tuple. If the time is passed in milliseconds, the alarm can be repeated by setting the keyword argument repeat to True. The milliseconds are counted from the current date-time of the RTC.
RTC.alarm_left(alarm_id=0): returns the number of milliseconds to the alarm.
RTC.cancel(alarm_id=0): used to cancel a running alarm.
The RTC class provides these methods to configure an interrupt…
RTC.irq(*, trigger, handler=None, wake=machine.IDLE): creates an interrupt object that’s triggered by the RTC alarm. It takes three parameters: trigger, handler, and wake. The trigger is always set to RTC.ALARM0. The handler is a callback function that runs as an interrupt service routine. The wake specifies the sleep mode from which the RTC interrupt can wake up the port.
Time synchronization using ntptime
The time in the RTC does not always have to be set manually. MicroPython provides the ntptime module, which is useful for synchronizing time, maintaining the UTC standard, and providing an accurate time. The module is based on the Network Time Protocol (NTP).
The NTP protocol synchronizes the RTC time of a computer/controller to a server or remote clock source. The module facilitates a precise calibration of the RTC time. However, the board must be connected to the internet via Ethernet or WiFi to join with the NTP server.
The module is imported in a MicroPython script using this statement:
The module provides these methods…
ntptime.settime(): used to synchronize the local time maintained by the RTC or an internal clock source to the UTC standard time. Some port-specific MicroPython ntptime modules let the settime() method take two arguments, timezone and server. The ntptime module of the official MicroPython firmware does not accept any arguments. The epoch time for the UTC standard is January 1, 1970 00:00:00. The host server used by the MicroPython ntptime module is “pool.ntp.org”
ntptime.time(): returns the number of seconds elapsed since the UTC epoch. The returned value is an integer.
Again, be sure the board is connected to the internet via Ethernet or WiFi to access the NTP server.
RTC in ESP8266 and ESP32
ESP8266 and ESP32 have single built-in RTCs. Below is a valid example of instantiating an RTC object, setting the time, and retrieving the current date-time in ESP8266 and ESP32.
RTC in ESP8266 and ESP32
ESP8266 and ESP32 both have single built-in RTCs. Below is a valid example of instantiating an RTC object, setting the time, and retrieving the current date-time in ESP8266 and ESP32.
from machine import RTC
rtc = RTC()
rtc.datetime((2022, 7, 25, 1, 1, 30, 42, 0)) # set date and time
print(rtc.datetime()) # get date and time
Here’s a valid example of setting the RTC time using the NTP server in ESP8266 and ESP32:
from machine import RTC
station = network.WLAN(network.STA_IF)
station.connect(ssid, password) #replace with your WiFi ssid and password
rtc = RTC()
Displaying the local time using the ESP8266 module
The time returned by the NTP server is UTC time. To change the time, convert the UTC timestamp to the local timestamp. As MicroPython is a subset of Python, it does not have a direct function or method to convert the UTC time to another time zone. So, it’s necessary to use MicroPython firmware’s time module.
For this project, we’ll display the UTC and local time with the help of MicroPython and ESP8266.
1. ESP8266/ESP32 x1
2. Computer/laptop x1
3. USB cable (to connect the ESP board to a computer) x1
There are no circuit connections for this project. Simply connect the ESP8266/ESP32 to your computer using the USB cable. Also, make sure uPyCraft IDE or Thonny IDE is installed on your computer and upload MicroPython firmware to the ESP8266/ESP32 (learn how here).
Next, launch uPyCraft IDE. Select the serial communication port by navigating Tools->Serial and select the board by navigating Tools-> board. After uploading MicroPython firmware, you should have boot.py under the device tab.
Create a new file by navigating File->New and save the file as main.py. Copy the below script to main.py. Click the ‘Download-and-Run’ button to execute script.
How the project works
ESP8266 connects with the NTP server and gets the UTC time, which is used to set the RTC date-time. The UTC time is then converted to the local time (IST in this case) using functions from the time module. The local time is printed by the console. Finally, the RTC is updated with the local time.
The MicroPython script imports the RTC class from the machine, network, ntptime, and time modules. Next, an object of the network module’s WLAN class is instantiated.
The user-defined function, connect(), is defined to connect with the WiFi. The function disconnect() is defined to disconnect the ESP8266/ESP32 with the WiFi. To understand these functions, check out How to connect ESP8266 and ESP32 with WiFi.
The ESP8266/ESP32 connects with WiFi by calling the connect() function. You must pass the SSID and network key/password of your personal WiFi as arguments.
An object of the RTC class is instantiated using the machine.RTC() method. The current UTC time is set to the ESP8266/ESP32 RTC by calling the ntptime.settime(). The UTC time set in the ESP8266/ESP32 RTC is retrieved in a tuple and displayed on the console.
To convert UTC to the local time, use MicroPython’s time module (learn more here). MicroPython is a subset of the standard Python’s time module and contains a few functions applicable to embedded applications.
The UTC time is obtained in seconds from the UTC epoch by calling the ntptime.time() method. The current UTC time is stored in a variable sec. The time zone time difference is stored in the variable timezone_hour. You can change the value of the time zone time difference in hours, according to your own country or time zone.
- The time zone difference is converted to a value in seconds and stored in the variable timezone_sec.
- The local time in seconds is obtained by adding the time zone time difference in seconds to the UTC time obtained from the RTC.
- The local date-time is then obtained by passing the updated seconds as an argument to the time.localtime() method.
- The time returned by the time.localtime() is stored in a tuple.
- The tuple is used to display the local time on the console. The tuple is then reformatted and used to update the RTC date-time to local time.
- Lastly, disconnect ESP8266/ESP32 from WiFi by calling the disconnect() function.
You may also like:
Filed Under: Python, Tutorials
Questions related to this article?
👉Ask and discuss on Electro-Tech-Online.com and EDAboard.com forums.
Tell Us What You Think!!
You must be logged in to post a comment.