This example describes how to use the
datetime
and
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.
SDL
and SDA
I2C 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.GND
and 5V
pins from the Arduino board to the corresponding
rails on the breadboard.SDA
and SDL
with the I2C bus on the
breadboard. Wire its GND
and Vo
pins with the GND
line on the
breadboard. Wire Vcc
pin with the 5V
line on the breadboard.SDA
and SDL
with the I2C bus on
the breadboard. Wire its V
and GND
pins 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-device
node
from the xod-dev/ds-rtc
library 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 ADDR
pin is 68h
which is correct for the most DS1307
modules. The DEV
pin of the node outputs the rtc-device
value which
contains everything to operate the device.write
node from the
xod-dev/ds-rtc
library onto the patch. This node’s function is to write time
and date to the permanent memory of the RTC board. The DT
pin inputs a
datetime
type value to be written. The UPD
pin triggers a new write. The
DONE
and ERR
output pins notify about the state of writing.DEV
pin of the write
node with the DEV
pin of the rtc-device
node.On boot
value at the UPD
pin means that we write the datetime
once
after the boot of the device.The 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.
datetime
node onto the
patch.datetime
node with the DT
pin of the write
node.YEAR
, MON
, DAY
, HOUR
, MIN
, and SEC
pins 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.
2018
year value to the YEAR
pin.9
number of the September month to the MON
pin.17
number of the day of the month to the DAY
pin.14
number of the hours to the HOUR
pin.44
number of the minutes to the MIN
pin.31
number of the seconds to the SEC
pin.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.
rtc
node onto the patch.
This node represents an RTC clock. A pulse at the UPD
pin triggers a new
reading of a datetime
type value. The DONE
and ERR
output pins notify
about was the read successful or not. By default, the I2C device address at
the ADDR
pin is 68h
.UPD
pin value to
Continuous
.unpack-datetime
node onto the patch and link it with the rtc
node. The unpack-datetime
node destructs the datetime
type value and outputs Number
values 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.
2018
number value at the YEAR
pin.9
number value at the MON
pin.17
number value at the DAY
pin.14
number value at the HOUR
pin.44
number value at the MIN
pin31
number value at the SEC
pin.Besides, the unpack-datetime
node calculates the weekday and outputs it
through the WD
pin in the range from 1
to 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 /
character.
input-number
nodes onto the patch and name them YEAR
, MON
, and
DAY
.output-string
node onto the patch and name it DATE
.format-number
node
and link it with the YEAR
node. The year values that comes to the YEAR
pin
are of Number type. The Number type values are floating point, and the incoming
year value looks like 2018.00
. We use the format-number
node to get rid of
those zeroes. If you put the 0
value to the DIG
pin string value of the
year becomes 2018
.pad-with-zeroes
nodes from the xod/core
onto the patch. Link their input pins with MON
and
DAY
. The pad-with-zeroes
node 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 W
input 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/2018
date 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-zeroes
solves this problem. We put the 2
width value
to the W
pin 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.join
node onto the patch. With
the join
we 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 D
delimiter pin. With join
we can also set the order of the year,
month, and day representation. As we want the MON
value to be first, DAY
to be second, and YEAR
to be third, we make proper links between join
input pins and other nodes. After this link the join
output to the DATE
output-string node.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 format-weekday
.
input-number
node for the input weekday number onto the patch. Name
it IN
.output-string
node for the string name of the weekday onto the patch
and name it OUT
.Mon
, Tue
,
Wed
, Thu
, Fri
, Sat
, Sun
and create constant nodes for them.nth-input
node onto the
patch. The format-weekday
node outputs the number of weekdays in the range
from 1
to 7
. So, the Monday number is 1
, and the Sunday number is 7
.
The nth-input
node is great for this example, it outputs the selected value
from X
pins based on the IDX
index value. Let the input node IN
be the
index.IN
input-node to the IDX
pin.X
pins of the nth-input
node.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-number
node for the time and name them HOUR
, MIN
, and
SEC
.output-string
node for the formatted time in a string form.pad-with-zeroes
nodes onto the patch and link them with HOUR
,
MIN
, and SEC
nodes. To display hours, minutes, and seconds in a two-digit
format, put the2
value to theW
pins as we do it in theformat-date
node.join
node. Put the :
delimiter into the D
pin of the join
node. Also, you can use the join
to
set the order in which the time is displayed. Make proper links between the
pad-with-zeroes
outputs and the join
inputs.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 AM
and PM
words on the display
screen.
am-pm
node between the
HOUR
input node and the pad-with-zeroes
node. The am-pm
changes the hour
format from 24 to 12. The AM
pin is true
if it is “before midday” or
false
if it is not.if-else
node onto the patch and set the AM
string value for T
,
and PM
string value for F
. Link the COND
pin with the AM
output of the
am-pm
node.PM
and AM
labels with a single space. For this,
put another join
node onto the patch. Put the spacer character to its
delimiter D
pin.join
with the nodes above and the output node TIME
to finish
the format-time
patch.Format nodes are ready, so let’s put them onto the rtc-example-read
patch.
format-date
, format-weekday
, and format-time
nodes, that you’ve
just created. Link their inputs to the unpack-datetime
outputs.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-16x2-i2c
node onto the patch.concat
nodes 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.concat
node of the date and time with the L1
pin of the
text-lcd-16x2-i2c
node. The second concat
node with the L2
pin.Upload 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/datetime
and 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.