This example describes how to use the
ds-rtc libraries, format date and time values, and work with real-time clock (RTC) modules for Arduino. Upon the completion of this guide, you will learn how to create a simple digital clock based on a DS1307 I2C RTC module and I2C LCD display.
You can use a DS3231 or DS1302 breakout board instead of DS1307 because they are interchangeable.
SDAI2C pins from the Arduino board to the contact lines on the breadboard. The display and RTC have different I2C addresses, they do not interfere with each other, so you can connect them to the same I2C bus.
5Vpins from the Arduino board to the corresponding rails on the breadboard.
SDLwith the I2C bus on the breadboard. Wire its
Vopins with the
GNDline on the breadboard. Wire
Vccpin with the
5Vline on the breadboard.
SDLwith the I2C bus on the breadboard. Wire its
GNDpins with the corresponding lines on the breadboard.
If you are using another model of the I2C display or RTC module, look at their pinout and datasheet to connect them correctly.
For this example, the programming process consists of two steps:
Create a new patch
set-current-time. We’ll use it only once to write the current time to the memory of RTC module so that it has a proper base point.
rtc-devicenode from the
xod-dev/ds-rtclibrary onto the patch. This node describes an RTC breakout board which communicates via I2C. By default, the I2C device address of the RTC at the
68hwhich is correct for the most DS1307 modules. The
DEVpin of the node outputs the
rtc-devicevalue which contains everything to operate the device.
writenode from the
xod-dev/ds-rtclibrary onto the patch. This node’s function is to write time and date to the permanent memory of the RTC board. The
DTpin inputs a
datetimetype value to be written. The
UPDpin triggers a new write. The
DONEoutput pin notifies writing complete.
DEVpin of the
writenode with the
DEVpin of the
On bootvalue at the
UPDpin means that we write the
datetimeonce after the boot of the device.
write node requires the date and time values having a
datetime type. The
datetime node is used to pack year, month, day, and hours, minutes, seconds into a
datetime type value.
datetimenode onto the patch.
datetimenode with the
DTpin of the
SECpins with values. Each pin contains a description of what form this values should be.
For example, we set the current date. Now it is the 17-th of September of the 2018 year, and the time is 14 hours 44 minutes and about 31 seconds. To set this date and time values to the RTC, we fill the
datetime pins with values.
2018year value to the
9number of the September month to the
17number of the day of the month to the
14number of the hours to the
44number of the minutes to the
31number of the seconds to the
The patch to set up the real-time clock is completed. Let’s quickly load it into the Arduino board, to make the difference between the real and written time be only a few seconds.
Once the board is flashed the RTC module will get the correct current time value which automatically ticks and not get lost as long as the module is powered by either its battery or the device itself. However, note that the time gets re-written on every boot to that exact value we have set. So, if you will reset your board after an hour, it will overwrite the correct time with the now-obsolete hour-lagging value. To protect from this effect it is a good idea to remove the uploaded time setting program. Upload an empty patch right after
set-current-time to clear.
We won’t need the
set-current-time patch anymore.
Create a new patch and name it
digital-clock. This is the patch for our digital clock. Strictly speaking, we are going to create a new program. So we need to put an RTC node again. To fetch the data, a node which is named simply
rtc might be used. Then we unpack the obtained values for further work.
rtcnode onto the patch. This node represents an RTC clock. A pulse at the
UPDpin triggers a new reading of a
datetimetype value. The
DONEoutput pin fires on successful read. By default, the I2C device address at the
UPDpin value to
unpack-datetimenode onto the patch and link it with the
unpack-datetimenode destructs the
datetimetype value and outputs
Numbervalues of the date and time for subsequent processing or formatting.
Look at descriptions of output pins of the
unpack-datetime node to figure out the ranges and formats of the output values.
If the real-time clock takes a small place in your extensive project, and a controller is very loaded, the
Continuous pulses on time readings can lead to various unexpected read failures. To solve this problem limit the pulse frequency. For example, you can link the
UPD pin with the
clock node and set the
IVAL value to
1 second. By this, you adjust the real-time clock updates to 1 Hz.
Let’s put this patch aside for a while. Imagine that no time has passed since we written values to the RTC. Thus, if we look at output pins of the
unpack-datetime node, the values of date and time are the same format that we entered.
2018number value at the
9number value at the
17number value at the
14number value at the
44number value at the
31number value at the
unpack-datetime node calculates the weekday and outputs it through the
WD pin in the range from
7. Now, we need to format this numbers to a proper view and add punctuation before showing them at the display screen.
Different conventions exist all around the world for the date and time representation, both written and spoken. Differences can exist in:
Some time formats are standardized though. For example, you can read about ISO 8601 or Unix time formats. You can check out the
xod/datetime library for the
format-timestamp node. It formats datetime for use in spreadsheet computer programms. In this example, let’s format date and time as they are shown on the digital clock in the classic American style. Here is the picture of the digital clock we want to make.
Let’s create three additional patch nodes which format our date and time values.
We start the formatting process from the date. Create a patch for the first new patch node and name it
format-date. We want this node to get numbers for a year, month, and day and output them as a single string. Also, we want
format-date to separate the date values with the
input-numbernodes onto the patch and name them
output-stringnode onto the patch and name it
format-numbernode and link it with the
YEARnode. The year values that comes to the
YEARpin are of Number type. The Number type values are floating point, and the incoming year value looks like
2018.00. We use the
format-numbernode to get rid of those zeroes. If you put the
0value to the
DIGpin string value of the year becomes
pad-with-zeroesnodes from the
xod/coreonto the patch. Link their input pins with
pad-with-zeroesnode transforms a Number value into String adding zeroes before the value. The number of added zeroes depends on the width of the string. The width value is set at the
Winput pin. This node is very useful for this guide. The month and day value fields on our display have 2 digit capacity. If we show the
12/22/2018date on the screen, it is ok. However, if we show, for example the 3rd of September directly without adding zeroes below the month and day, the text on the screen looks will be
3/9/2018. Thus cuts the width of the date by two digits, and the total width of the line on the display screen. The
pad-with-zeroessolves this problem. We put the
2width value to the
Wpin on both nodes, so the 3rd of September looks like
03/09/2018. By this, the total width of the line with the date will always be static.
joinnode onto the patch. With the
joinwe can separate day, month and year by a character of our choice. As we want to separate date values with
/, we link the
/string constant with the
Ddelimiter pin. With
joinwe can also set the order of the year, month, and day representation. As we want the
MONvalue to be first,
DAYto be second, and
YEARto be third, we make proper links between
joininput pins and other nodes. After this link the
joinoutput to the
unpack-datetime node outputs the number of the weekday depending on the date. To show weekday names instead of numbers we need a node. Create a patch for this node and name it
input-numbernode for the input weekday number onto the patch. Name it
output-stringnode for the string name of the weekday onto the patch and name it
Sunand create constant nodes for them.
nth-inputnode onto the patch. The
format-weekdaynode outputs the number of weekdays in the range from
7. So, the Monday number is
1, and the Sunday number is
nth-inputnode is great for this example, it outputs the selected value from
Xpins based on the
IDXindex value. Let the input node
INbe the index.
INinput-node to the
Xpins of the
Ok, we created nodes that format date and weekday. Time is left to format. Create a patch for the new node and name it
format-time. This node will take hours, minutes and seconds from the
unpack-datetime node and format them as we desire.
input-numbernode for the time and name them
output-stringnode for the formatted time in a string form.
pad-with-zeroesnodes onto the patch and link them with
SECnodes. To display hours, minutes, and seconds in a two-digit format, put the
2value to the
Wpins as we do it in the
joinnode. Put the
:delimiter into the
Dpin of the
joinnode. Also, you can use the
jointo set the order in which the time is displayed. Make proper links between the
pad-with-zeroesoutputs and the
For the American style clock, we decide to use the 12-hour format instead of 24-hour. For the part of the day, we show the
PM words on the display screen.
am-pmnode between the
HOURinput node and the
am-pmchanges the hour format from 24 to 12. The
trueif it is “before midday” or
falseif it is not.
if-elsenode onto the patch and set the
AMstring value for
PMstring value for
F. Link the
CONDpin with the
AMoutput of the
AMlabels with a single space. For this, put another
joinnode onto the patch. Put the spacer character to its delimiter
joinwith the nodes above and the output node
TIMEto finish the
Format nodes are ready, so let’s put them onto the
format-timenodes, that you’ve just created. Link their inputs to the
When the date, time, and weekday are formatted we can show them on the I2C display screen. Let’s show the date and the weekday at the first line of the I2C display, and time at the second line.
text-lcd-i2c-16x2node onto the patch.
concatnodes for each line. There we added two spaces to indent the text from the edge of the screen and one space to separate the day of the week from the date.
concatnode of the date and time with the
L1pin of the
text-lcd-16x2-i2cnode. The second
concatnode with the
rtc-example-read patch to your Arduino board and look what the digital clock you get.
If you encounter any problems trying to repeat the guide, download the prepared project and open it in the IDE.
We created a digital clock device using
xod/ds-rtc libraries. Try to make your own clock with different styles and timestamp formats.
If you want to practice, find other usages of these libraries. For example, connect a real-time clock to an SD card, log timestamp values using the
format-timestamp node, and have a look how it is easy to process timestamps with the computer applications.