bclose

60 – Arduino and RTCs

Objectives

.

 
    • Introduce the Real Time Clocks (RTCs).
    • Assemble a prototype with a Tiny RTC.
    • Introduce the auxiliar Time libraries: DS1307RTC and TimeAlarms.
    • Arguments __DATE__ and __TIME__.
 

Bill of materials

Arduino UNO

 Arduino UNO o equivalent.

BreadboardJumper wires A breadboard and some jumper wires.
RTC clock A  TinyRTC digital clock with a backup battery.

 

THE REAL TIME CLOCKS OR RTCS

 

In the previous chapter, we introduced the new Time library for Arduino. We started using the internal clock for the examples, because it is an always available and free option.

But we said that it had several obvious drawbacks, such as the fact that the internal clock restarts every 50 days and besides when we power our Arduino off, the clock sets to 0 and starts counting again from 1 January 1970.

We need a solution, which allows us to use a reliable clock that keeps the time even when we power off Arduino. And what happens when we have to solve an electronic problem? Well, there is normally a manufacturer, or several, who supply us chip to solve it.

One very widespread chip used for digital watches is the Maxim DS1307. For very little money it performs all the functions needed to build a clock with calendar using only an external battery, in order to keep the time when you power it off. Their features are:

Maxim DS1307 RTC
  • RTC or Real Time Clock, that counts the seconds and hours plus days, months and years automatically, valid up to 2100.
  • 56 byte of RAM memory backup by an external battery, that keeps the date and tiem when power if off.
  • Automatic detection of power cut and change to battery mode.
  • Very low power consumption, which helps the battery to last between 5 and 10 years. .
  • I2C bus integrated in the chip itself.

 

RTC clock

In addition, it is quite easy to get a clock with a battery mounted on a breakout board and ready to be used in our projects, for a few euros.

In this chapter we are going to use one of these boards, the Tiny RTC, with the DS1307 chip, mounted in a breakout board with its clock, a backup battery and I2C bus, so we will only have to connect a few wires and start playing with it.

 

 

WIRING DIAGRAM

 

Again the connection is trivial. Simply connect SDA to Arduino pin A4 and SCL to pin A5.

Chapter 60, schematic diagram

And for the breadboard:

Chapter 60, schematic diagram

The SQW pin is a digital output of the DS1307 chip, which allows us to generate a programmable frequency square signal (1Hz, 4kHz, 8kHz, 32kHz) that can be used as a clock generator for the clock of any circuit, without the need for an additional quartz crystal and an oscillator circuit (which is already built in the Tiny RTC itself).

So in this case, as we will not use it, we leave it unconnected, after checking in the data sheet that it can be done without problems.

 

THE CONTROL PROGRAM

 

In the previous chapter we downloaded and installed the new Time library in our IDE. The advantage of using a coherent library is that all the functions we saw in the previous chapter are still valid and can be equally used, even if we now have a different clock.

It is enough to install the library corresponding to the new DS1307 clock. This is the link to the new library:

DS1307 RTC library

Normally when you install an RTC it doesn’t have the time set, so let’s start there and see if the chip has been set on time:

#include 
#include 
#include                              // The library that manages the DS1307 RTC for the Time library

void setup()
   {    Serial.begin(9600);
        while (!Serial) ;             // Only if you use an Arduino Leonardo
        setSyncProvider(RTC.get);     // Synchronize with the RTC
        if(timeStatus()!= timeSet)
             Serial.println("Unable to sync with the RTC");
        else
             Serial.println("RTC has set the system time");
   }

The first three lines load the necessary libraries. The first two were already used in the previous chapter and the one corresponding to the DS1307 is due to the RTC that we are going to use. Pay attention to the following line:

  setSyncProvider(RTC.get);     // Synchronize with the RTC

The libraries are written so that using the setSyncProvider() function we can define the clock model that we are going to use and that the rest of the program is the same, regardless of the clock. Not bad, is the advantage of using consistent libraries.

In the setup we use timeStatus() function to know if the clock is on time or not. In case it is not on time we can add to the setup one more line using the setTime() function to set the clock. In our case we added:

setTime(21,45,00,13,11,2016)// 13 November 2016, 21:45:00

Replace the time with the corresponding value and run the sketch to synchronize the clock.

 
  • Make sure that you run the setTime() once, because if you repeatedly do so, you will set again and again the same time on the DS1307’s internal clock.
  • Once you have run the sketch and checked that the time is correct, simply make a comment on the setTime() line.
 
We can already write a complete sketch that returns the date and time on the serial port.

sketch_60_1
#include <Time.h> 
#include <Wire.h> 
#include <DS1307RTC.h>            // A basic DS1307 library that returns time as a time_t

void setup() {
    Serial.begin(115200);
    while (!Serial) ;             // Needed for Leonardo only
    setSyncProvider(RTC.get);     // the function to get the time from the RTC
 
    setTime(18,30,00,14,11,2016); // Sets date-time as 14 November 2016, 18:30:00 
    if (timeStatus() != timeSet)
        Serial.println("Unable to sync with the RTC");
    else
        Serial.println("RTC has set the system time");
   }
void loop()
   {     digitalClockDisplay();
         delay(1000);
   }
void digitalClockDisplay()
   {     Serial.print(hour());
         printDigits(minute());
         printDigits(second());
         Serial.print(" ");
         Serial.print(day());
         Serial.print(" ");
         Serial.print(month());
         Serial.print(" ");
         Serial.print(year());
         Serial.println();
   }
void printDigits(int digits)
   {     Serial.print(":");
         if(digits < 10)
            Serial.print('0');
         Serial.print(digits);
   }

The printDigits() function ensures that there are always two digits in the corresponding numbers, adding a leading zero when the number is less than 10, so we have a nice calendar on the serial port.

Serial monitor output

 

USING COMPILER’S DATE AND TIME

 

If you are testing the library out of hours, you often have to recompile your code over and over again, and if you have to set the clock on time each time, you usually end up screaming with frustration . If you were a quiet person it is unlikely that you were reading this, you would have a sensible job as an accountant or councilman).

Thinking about your neighbours, the Arduino compiler, has a couple of arguments that inform us of the date and time of the last compilation: __DATE__ and __TIME__.

We can take advantage of this to set the internal clock on time running a sketch that converts these values to date format time_t and assign it to the value of the internal clock.

This way, although we will drag a couple of seconds of error, we will assign a reasonably good time to the clock, without needing to be continually recompiling to put it in time.

Just run this sketch and magic will take care of the rest. Those who do not believe in magic can take a look at the sketch, because although it contains some C++ instructions that we have not seen, you will not have much trouble following it.
Here you have the sketch: Automatic date and time set

 

TIMEALARMS LIBRARY

 

There is one more library called TimeAlarms, related to the Time library, that allows us to define alarms in our sketch, very much as when we set an alarm in a clock. When an alarm triggers, it calls an specific function that is executed in a preset time.

We can download here the TimeAlarms library:

TimeAlarms library

It provides several functions that we will list here:

 Function  Descripction
Alarm.alarmRepeat(hours, minutes, seconds, function); Creates an alarm that repeats itself every day at the specified time and executes the function.
Alarm.alarmRepeat(dayofweek, hours, minutes, seconds, function); Creates an alarm that is triggered only the specified day of the week at the specified time.
Alarm.alarmOnce(hours, minutes, seconds, function); Creates an alarm that is triggered only once at the set time and executes the function.
Alarm.alarmOnce(dayofweek, hours, minutes, seconds, function); . Creates a single alarm that is triggered the next day of the specified week and executes the function.
Alarm.timerRepeat(seconds, function); Creates an alarm that will execute the specified function every few seconds.
Alarm.timerOnce(seconds, function); Creates an alarm that will only execute the function once after the specified seconds.

It is an interesting library if you have to repeat tasks periodically (like sending data to a site) and also offers us a comfortable timers that are executed in a programmed way, without needing to define interruptions that could interfere with other functions.

 
  • The TimeAlarm library does not use interruptions, but relies on the internal management of Time.
  • TimeAlarm needs no specific hardware or RTC, it only requires the Time library to be loaded.
  • We can define up to 6 alarms by changing the header of TimeAlarm.h
  • Intervals shorter than 1 second can not be set. For lower periods it is required to use a programmed interrupt or Timer (which we will see in a further chapter).
 

SUMMARY

 

 

    • We have seen how to use an RTC with the Time library. There is no difference with using the Arduino internal clock, beyond setting the setSyncProvider().
    • We saw some examples of how to set the clock with setTime() and using the compiler arguments __TIME__ and __DATE__.
    • We have also introduced the TimeAlrms library to trigger functions in programmed alarms.
 

 

 

 

 

No Comments

Give a Reply