Download PDF Parts List View on YouTube Download Code

Introduction

The Arduino is an amazing device. It’s useful for prototyping and can also be used to construct a complete project. It has an analog to digital converters (ADC), digital I/O pins, it handles interrupts and it can communicate via a serial port, SPI, and I2C.

But there is one thing an Arduino cannot do – it can’t tell the time.

There are several time-related functions you can use when programming an Arduino:

  • The delay function, which can delay program execution for a specified number of milliseconds.
  • The delayMicroseconds function which is like the delay function except you specify the time in microseconds.
  • The millis function, which counts the elapsed milliseconds since the Arduino was powered up or reset.
  • The micros function, like the millis function, except it measures the time the Arduino has been running in microseconds.

You can use the above functions to insert time delays or measure elapsed time. But you can’t get the time of day or date from them.

To do that you’ll need to add an external component – a “real time clock”.

Real Time Clocks

A “real time clock” is essentially a digital clock whose output can be read by a computer or microcontroller.  It has its own oscillator that it uses to count time and it has registers that allow you to set the current time and date.

Real Time Clock with Arduino

The device you are using to read this article likely has a real time clock and if you are attached to the Internet you probably are synchronizing this to a network time server (if your device is a phone it may be time synchronized to your telephone companies carrier signal instead).

Most real time clock modules have provision for a battery backup, so that they can keep time when the rest of the system is powered down.

Unix Time

Most computers keep time in what might seem to be a strange system, they use “Unix time”.

Unix time is the number of seconds that have elapsed since midnight January 1, 1970 (which was a Thursday if you’re interested).  If you are on Linux (or at the terminal on a Mac, which uses Unix as its underlying operating system) you can type “date +%s” to get the current Unix time.

Unix time is also called “POSIX Time” or “UNIX Epoch time”.

Unix time is useful when you are writing a program that needs to calculate the time difference between two dates and times, as it involves simple addition and subtraction, without having to worry about days, months and years.

But Unix time also has a few drawbacks:

  • It does not take into account leap seconds, and there have been several of these since January 1, 1970.
  • It uses a 32-bit numbering system and will run out of digits on January 19, 2038. This is sometimes referred to as the “Year 2038 problem”.

The issue with leap seconds is generally taken care of by synchronizing your real time clock with a local or network time source, which itself will have compensated for leap seconds.

The problem with 2038 is likely to be resolved within the next 19 years, I suspect just shifting to a 64-bit standard would resolve this for several millennia!

DS1307 Real Time Clock

There are a few very popular real time clock integrated circuits that are used in real time clock modules.

One chip is the DS3231, a highly accurate real time clock that uses an I2C interface.  This chip has its own internal crystal oscillator, so no external crystal is required.

Another very popular chip is the DS1307. Like the DS3231 it also communicates using the I2C bus, however, this chip requires an external timing crystal.

The experiment I’ll be performing today use a module that has a DS1307 chip.  They can be easily modified to use the DS3231.

Tiny RTC Board

I will be using a module called the “Tiny RTC”, this is a very common and inexpensive module.

Tiny RTC Front View

The board contains the DS1307 chip and all the support electronics, including the timing crystal.  It also has a battery holder for a coin cell, this sits underneath the board.

Tiny RTC Rear View

If you order your Tiny RTC online from an overseas source it likely won’t have the battery installed, this is due to international shipping regulations regarding lithium batteries. The module uses a widely available coin cell battery.

The Tiny RTC module has the following features:

  • Counts time in hours, minutes and seconds
  • Counts date, day of week, month and year.
  • Has Leap Year compensation
  • Has a programmable square wave output.
  • Has battery backup with automatic power failure detection and switchover.
  • Consumes less than 500nA in battery backup mode.

The Tiny RTC module interfaces using the I2C bus.

Tiny RTC Pinouts

The module has two sets of connectors, the I2C connections are repeated on both of them and you can use either of them to make your connections.

The device has the following connections:

  • DS – Device Select, this allows you to enable or disable the device.
  • SCL – The I2C clock or SCL connection.
  • SDA – The I2C Serial Data or SDA connection.
  • VCC – The +5-volt power supply.
  • GND – The Ground connection.
  • SQ – The programmable Square Wave output.
  • BAT – Battery connection.

Now that you have seen the module let’s hook it up to an Arduino.

Tiny RTC Basic Arduino Hookup

As the Tiny RTC uses the I2C bus it is very easy to hook it up to an Arduino.  The I2C bus provides power, clock and data signals, so only four connections are required.

Before you hook up your real time clock module it would be a good idea to install the coin cell battery, if you haven’t already. That way you will ensure that the device will keep time even after you power down the Arduino.

Arduino Hookup

Here is the hookup diagram for the Tiny RTC module.

Tiny RTC Arduino Hookup

The two I2C connections are made to two of the Arduino analog inputs.

  • Analog pin A4 is the SDA connection.
  • Analog pin A5 is the SCL connection.

Some Arduino clones also have separate SDA and SCL pins, usually located on the same side as the digital I/O pins above the AREF pin.  You can use these connections instead of the analog pins if you wish, they are actually just duplicates.

Arduino Libraries

There are several libraries available that will work with the Tiny RTC. I’m going to use two libraries that were contributed by Paul Stoffregen, a well-known figure in the Arduino community.

  • DS1307RTC Library – This library will function with any module that uses the DS1307 RTC chip, including the Tiny RTC.
  • Time Library – This library compliments the DS1307RTC library and adds a number of time-specific functions.

The Arduino Library Manager can be also used to install two updated versions of these libraries, these were updated by Michael Margolis.  You can find them as follows:

  • Open the Arduino IDE.
  • Click on the Sketch menu item at the top of the IDE window.
  • Click on Include Library. A sub-menu will open.
  • Select Manage Libraries from the sub-menu.
  • The Arduino Library Manager will open.
  • In the search box in the Library Manager type “DS1307RTC”
  • You should get two libraries in your results, the DS1307RTC library, and the Time library.
  • Click each selection to install the libraries.
  • You can now close the Library Manager window.

Once you have the libraries installed open your Arduino IDE and select the File menu item and select Examples. A sub-menu will appear, scroll down until you get to the Examples from Custom Libraries section.

Look for DS1307RTC and highlight it. You will see a sub-menu with two sketches, SetTime and ReadTest.

We will run both of these, starting with SetTime.

SetTime Sketch

As you might have guessed from its name the SetTime sketch sets the time on the Tiny RTC module. You’ll need to run this, or something similar, before you can use the clock.

SetTime uses two functions, getTime and getDate, to retrieve the time and date respectively from your computer clock. As most Internet-connected computers synchronize to a network time protocol (NTP) server this will probably be very accurate.

One statement in the code that may be new to you is the 10th line, tmElements_t tm; .  This is a “data structure” that represents the time.

Without using a data structure the time will be reported in Unix time, which I described earlier.  The tmElements_t  data structure breaks this down into elements like seconds, minutes, hours, days, months and years.

Otherwise, the sketch is fairly straightforward. It gets the current system time from the computer running the IDE and writes it to the DS1307 chip on the Tiny RTC module. It does all of this in the Setup section so there is no code in the loop.

Load this sketch and run it to set the time in your real time clock. Then move on to the next sketch.

ReadTest Sketch

The ReadTest sketch will read the time from the Tiny RTC module or any module based upon the DS1307 real time clock chip.

This is actually a pretty simple sketch, and it does a good job of illustrating how you can use these libraries to write a sketch of your own.

We start by including the Wire library, which is the built-in library that facilitates communications using I2C.  We then include the two libraries we installed earlier.

In the Setup section we just set up the serial monitor and write a few lines to it.

The Loop starts with our data structure to derive the time values from.

Al that is left is to read those time values and print them to the serial monitor. A function called print2digits is used for the hours, minutes and seconds to format the display nicely, with leading zeros for numbers below 10.

I’ll be reusing a lot of this code later when I create a sketch of my own.

Tiny RTC Square Wave Interrupt

The two sketches we have just looked at illustrate how to set and read the time from the Tiny RTC module, and they accomplish this very well. But the module has an additional function, the ability to output a square wave.

You can use this square wave as a timing source for another circuit. It could be used to drive a stepper motor to create an analog clock. And, as I will show you here, it can be used to generate an interrupt for your Arduino.

Programming the Tiny RTC Square Wave Frequency

The DS1307 chip used in the Tiny RTC module is capable of generating square waves at the following preset frequencies:

  • 1 Hz
  • 4 KHz
  • 8 KHz
  • 32 KHz

These frequencies are selected by writing to an internal control register in the DS1307.  By default, the device is programmed at the factory for a 32 KHz frequency.

Square Wave Arduino Hookup

To use the square wave output as an interrupt for your Arduino you will need to connect the SQ output on the Tiny RTC module to one of the interrupt pins on the Arduino.

The following diagram shows the hookup using an Arduino Uno.

Arduino Real Time Clock with Square Wave Interrupt

The SQ output is connected to pin 2, which corresponds to interrupt 0 in the Arduino Uno.

An LED is also connected to the Arduino to indicate when an interrupt is being serviced. This is actually optional as it is connected to pin 13 and the Uno also has a built-in LED connected to that pin. If you wish you can leave it out and just monitor the LED on your Uno board.

Square Wave Interrupt Demo Sketch

I found a great sketch that shows how to use the square wave output, it was originally published by Robert Ulbricht on the Arduino Slovakia website. Fortunately, there is an English translation available.

The sketch only requires the Wire library, it uses this to write directly to the registers on the DS1307 chip.

The constant DS1307_CTRL_ID defines the I2C address of the real time clock chip.

The function setSQW is really where the “action” is. This function writes to the control register in the DS1307 and sets the square wave frequency to 1Hz.

The handleInt function is the interrupt handler. Every time a pulse is received on the D2 pin it will be called.  This is set up in the Setup function using the Arduino attachInterrupt function.

The result is that the LED will flash every second.  In operation, it looks a lot like the Blink sketch!

Tiny RTC Temperature and Humidity Sketch

The previous sketch illustrated how to use the SQ square wave output from the Tiny RTC module as an interrupt. And while it does a great job of displaying interrupt operation it really doesn’t have many practical uses.

After all, there are many simpler methods of blinking an LED. In fact, if you really wanted to use the Tiny RTC to blink an LED you could just attach it directly to the SQ output, eliminating the Arduino entirely (although you’d need the Arduino to set the SQ output to 1Hz first).

Let’s look at a more practical example of using interrupts from the real time clock module.

Using Interrupts to Solve a Problem

Take another look at the ReadTest sketch from the DS1307RTC examples. You’ll notice that it reads the time and then adds two delays that total exactly one second. It then does it all over again.

If you’re just building a clock this will work well, as every second you’ll read the time and it will have advanced one second.  But what if you want to do something else in the Loop after you read and display the time?

Whatever your “something else” is it probably won’t take exactly one second. And this will cause an erratic clock display.

  • If the ”something else” takes less than a second then you’ll be displaying the same time more than once. On a display like an LCD or OLED this is not such a bad thing as you might never notice it, but on the serial monitor it will stand out.
  • If the “something else” takes more than one second you’ll miss reading the clock and it wil skip one or more seconds. You can alleviate this problem somewhat by simply not displaying seconds but still, your minutes may not change at precisely the right time.

To solve this timing problem we can use interrupts.

AM2320 Temperature & Humidity Sensor

To illustrate how to take advantage of interrupts to solve the timing problem I’m going to build a temperature and humidity meter that can also tell time.  I’m going to stick to the serial monitor for my display, but you could easily modify the code to use an OLED or LCD display.

The AM2320 is an I2C temperature and humidity sensor. Physically it looks identical to a DHT11 or DHT22, the difference is that it uses the I2C bus to send data to its host.

If you wish you could modify the sketch to use the DHT22 or DHT11, I used the AM2320 because I was already using I2C for the real time clock and because I had one handy!

No matter which sensor you choose for your design you’ll encounter the same dilemma – these temperature and humidity sensors require at least two seconds between readings to stabilize.  And so if you read it in the Loop you’ll get an erratic display.

This looks like a job for an interrupt!

Temperature and Humidity Clock Hookup

Let’s begin by adding an AM2320 to our existing circuit. As you can see it’s pretty easy.

Arduino Real Time Clock and Temperature Humidity Sensor

Pay attention to the connections on the AM2320, looking at the unit with the “grid holes” facing you they are as follows, from left to right:

  • VCC – Goes to the +5 Volt output from the Arduino.
  • SDA – To Arduino pin A4 (or SDA pin if you have one)
  • GND – To Arduino Ground.
  • SCL – To Arduino pin A5 (or SCL pin if you have one)

Now that you have it hooked up let’s take a look at the sketch I came up with to make it all work.

Temperature and Humidity Clock Sketch

You’ll probably notice many elements from the previous sketches in this sketch.

You’ll need another couple of libraries to run this sketch to handle the temperature and humidity sensor. Both can be installed using the Library Manager.

  • The Adafruit AM2320 Library
  • The Adafruit Unified Sensor Library.

The latter library is not called directly in the sketch, instead, it is used by the AM2320 Library. Without it installed your sketch will fail to compile.

If you’ve used other Adafruit sensor libraries you may already have the Unified Sensor library installed.

We begin the sketch by including the libraries.  We then define the constant we used before for the Tiny RTC I2C address.

We also create an object to represent our sensor.

Next, we create a couple of variables that count “ticks”. I’m defining a “tick” as a one second period. The old_tick_value variable will be used to check if the tick value has changed since we last used it.

A couple of floats are defined to hold the temperature and humidity values.

In the Setup routine we attach the interrupt to the interrupt handler, as we did earlier. I kept the same name for the interrupt handler but have changed its function.

We also setup the square wave as 1 Hz.

Next we initialize the temperature and humidity sensor, delay for two seconds and then read the temperature and humidity values. This is so we already have a first reading before we enter the loop.

Let’s look down to some of the functions before we examine the Loop.

The printCurrentTime function prints the time, date, temperature and humidity to the serial monitor. It takes the temperature and humidity as an input and reads the real time clock, it then writes everything to the serial monitor.

The interrupt handler handleInt increments the tick count every time it is run.

You’ve seen the other two functions already, so let’s go back up to the loop.

In the Loop we first check the number of ticks by reading the tick count. If it is 10 then we read the humidity and temperature, then reset the tick counter to zero.

By doing this we only read the temperature and humidity sensor every 10 seconds, which gives it plenty of time to stabilize. You can reduce this number if you wish, but don’t go below two seconds.

We then check to see if the tick count is the same as it was before. If it is then we don’t do anything. If it isn’t then it means a second has elapsed, so we call printCurrentTime  to read the time and write everything to the serial monitor.

Load the sketch and give it a test. Note that since the temperature and humidity are only updated every 10 seconds it won’t immediately respond to a change in these values. In normal situations this shouldn’t really be an issue.

Conclusion

Adding a real time clock to an Arduino makes it possible to build devices that are aware of the current time and date. This can allow you to create fancy timers and delay circuits, or just build a really cool and unique digital clock.

Hopefully you’ll see some uses for a real time clock in your own projects. There no time like the present to get started!

 

Parts List

Here are some components that you might need to complete the experiments in this article. Please note that some of these links may be affiliate links, and the DroneBot Workshop may receive a commission on your purchases. This does not increase the cost to you and is a method of supporting this ad-free website.

COMING SOON!

 

Resources

Code In this Article – The sketches in this article in a ZIP file.

 

Using a Real Time Clock with Arduino
Summary
Using a Real Time Clock with Arduino
Article Name
Using a Real Time Clock with Arduino
Description
A Real Time Clock can be added to your Arduino project in order to tell the time. Today I will show you how to use the Tiny RTC, a real time clock based upon the popular DS1307 chip.
Author
Publisher Name
DroneBot Workshop
Publisher Logo
Tagged on:
Subscribe
Notify of

28 Comments
Oldest
Newest
Inline Feedbacks
View all comments
Pete
5 years ago

I couldn’t get the square wave blink demo to work, presumably because the registers were not set correctly on my RTC. I loaded the Square wave demo from the Adafruit lib (https://github.com/adafruit/RTClib) which worked. Once I’d done that your example also worked.

Thanks for the interesting videos!

Daniël
3 years ago
Reply to  Pete

I have tryed all the demo project and nothing was working… But when i tryed RTClib, it worked great! Thx @Pete

Mike Linney
5 years ago

^
Hi

Downloaded the two library’s required
but with set time got this –

exit status 1
‘tmElements_t’ does not name a type

and with read test got this-
exit status 1
‘tmElements_t’ was not declared in this scope

Help please

Mike

Michael Thomas
5 years ago

I also had this problem. I changed Time.h to TimeLib.h and then it compiled.

Mike Panchaud
5 years ago
Reply to  Michael Thomas

I had the same issue, had to rename Time.h to TimeLib.h. Working fine now. Having set the RTC with the SetTime sketch, I noticed when displaying the time on the serial monitor using the ReadTest sketch, there was an error of about 8 seconds between my PC clock and the RTC clock. I fudged this by changing line 55 in the SetTime sketch to tm.Second = Sec+8; . This caused the time to be set correctly or near enough. BTW I’m using the DS3231 RTC, which has much better accuracy than the DS1307 and is pin compatible, but the control… Read more »

Mike
5 years ago
Reply to  Mike Panchaud

It seems you have to called Mike to join this thread!

Mike Way
5 years ago
Reply to  Michael Thomas

Thanks Michael your idea did the trick.

Mike Way
5 years ago

Thanks Bill and Michael, will try the advise given.

Tran Rick
5 years ago
Reply to  Mike Linney

Hi there I really love your series video, I wish you can make the video about using SIMserial module with Arduino

5 years ago

Hallo,
DS is not ‘Device Select’, is DS18B20 Device, Temperatur.
And this is for LIR2032 Batterry or not CR2032! You must modified.

Bill Frenz
5 years ago

Good demo. Lots of useful content. I noticed the back up battery on the DS1307 was a CR2032. This batt is not a lithium battery and could develop problems when being used with an Arduino Uno or any other MC. When power is being applied to the Arduino in your example, a charging circuit on the RTC is active and attempts to charge the back up battery. Since the CR2032 is not rechargeable, it can over-heat and bad things can happen. There are two choices on how to deal with this problem. First, use a LIR2032. This batt is a… Read more »

5 years ago

I guess there is a Time for every purpose under heaven

thanks for the teaching video

Evile
4 years ago

Kind of tangentially related, but a lot of people are using now ESP32/ESP8266 based ‘Arduinos’, as they are much more powerful and have WiFi/Bluetooth, and are generally cheaper.
Obviously with the WiFi connection is the possibility to use NTP (network time protocol) to get the accurate time from a time server, the ESP even has functions built into it’s ROM for registering which time server you want to use, so require almost no code to set up.
Maybe this would make a good topic for one of your excellent videos Bill.

markonjak
4 years ago

What if you’re using dht11, does it also skip seconds, can i add an interrupt to rtc to not miss anything?

Andre
4 years ago

Good Day Sir,
I would like to thank you for the excellent tutorial on the Arduino real time clock application. I am a newcomer in the Arduino world. If you don’t mind I need to pose a few questions. I would like to use the application to for switching certain items on and off at designated times. What data format is used in the “tmElements_t”? Is there a posibillity that a person can extract the individual Hour and minute registers and compare a predetermined time to them?
Kind regards

Carsten Grötschel
4 years ago

Hello and good evening!
Your tutorials are super great and I am recently merging several of them to a project which shall controll a drying cabinet. Therefore I need a time signal and for the data storage a time stamp. For this I need only a very simpel sketch, without too much if/else fail-flags inside the sketch. So my question is:
What is really crucial to match the “system”-time, so that it is possible to combine the SetTime Sketch and the ReadTime Sketch Thanks for your input and regards from Germany

Likith Kumar J
4 years ago

I really appreciate and love the way you explain from scratch.

‘tmElements_t’ does not name a type; did you mean ‘timelib_month_t’? , I am getting this I tried to debug this in every possible way, 1) Included updated libraries 2)Check for syntax and semicolons too 3)Tried to change time.h to timelib.h

Could you please help me out with thus.

Thanks in advance.

Regrads
Likith

Rob Grattan
4 years ago

Hi,
Couldn’t get the Square Wave Interrupt Demo Sketch working at all!Also, where do you get TimeLib.h from?

Thanks.

Shashank
4 years ago

How can is hookup 12c 16*2 lcd display with tiny rtc so that it shows time on lcd screen. Please share me any diagram so i hookup tiny rtc and display both. And yes program also.

radudani
3 years ago

what is the real problem with that battery on the RTC?
do it needs some updates (I mean, Nov 2020), that is, perhaps the module accepts now CR2032 instead of LIR2032? there are lots of clones manufactured now…
thank you for the tutorial;

John Paul Pineda
3 years ago

Thanks for this tutorial, I’ve acquired additional knowledges.
Also, I did not know that it is possible to use 2 different modules at the same time and attach them to the same Analog pin like what you did on the Temperature and RTC modules. I will definitely apply this same technique to the device that I am going to build 🙂 .

Ron
3 years ago

Can you show a setup for 12 hour clock. Apparently it is set in register bits 5 and 6.

Thomas Valstedt
2 years ago

I use DS1307RTC lib as you do in the demo.
I got an error message “DS1307 read error! Please check the circuitry.” if the battery is inserted in the holder. This message is for both sketches ReadTest and SetTime.
If I remove the battery it works fine.
I wondering if the Tiny RTC card is broken. The battery voltage is 2,34 V when inserted in the holder and 3,3V if not

Last edited 2 years ago by Thomas Valstedt
fredricks
2 years ago

very well explained.

Segun B
2 years ago

I would like to thank you very much for all your excellent tutorials on Arduino p. I am a learner and have passion in the Arduino world. If you don’t mind, can you please add LCD to this RTC Project and i will be very grateful.

cliveo
1 year ago

it looks as if the square wave frequency is defined by setSQW(0x10). does anybody know how this resolves to 1 Hz? I would have thought (0x10) is hex for decimal 16.
Are you restricted to frequencies that are powers of two?
How do you resolve the frequency you want to “setSQW(0x??)”?
Can you change the duty cycle?
Ta
Clive