Lab: Using a Real-Time Clock

Introduction

In this lab, you’ll learn how to use a real-time clock on a microcontroller. Though this is written for the Arduino Nano 33 IoT and MKR modules, the principles apply to any real-time clock.

A real-time clock (RTC) is an application-specific integrated circuit (ASIC) that’s designed to keep accurate time in hours, minutes, seconds, days, months, and years. Most real-time clocks have a synchronous serial interface to communicate with a microcontroller. The DS1307 from Dallas Semiconductor is a typical one. Each RTC generally has a library to interface with it as well.  Many microcontrollers are incorporating an RTC into the microcontroller chip itself now as well. The SAMD M0+ chip that is the CPU of the MKRs and the Nano 33 IoT has an RTC built into it.

What You’ll Need to Know

To get the most out of this lab, you should be familiar with the following concepts and you should install the Arduino IDE on your computer. You can check how to do so in the links below:

Things You’ll Need


Arduino Nano on a breadboard.
You’ll need an Arduino Nano 33 IoT or any of the MKR series Arduinos for this exercise. You don’t need any other parts, unless you plan to connect to external sensors.

Figure 1. An Arduino Nano mounted on a solderless breadboard. The Nano is mounted at the top of the breadboard, straddling the center divide, with its USB connector facing up. The top pins of the Nano are in row 1 of the breadboard.

Image made with Fritzing

Program the Arduino

Make sure you’re using the Arduino IDE version 1.8.9 or later. If you’ve never used the type of Arduino module that you’re using here (for example, a Nano 33 IoT), you may need to install the board definitions. Go to the Tools Menu –> Board submenu –> Board Manager. A new window will pop up. Search for your board’s name (for example, Nano 33 IoT), and the Boards manager will filter for the correct board. Click install and it will install the board definition.

You’ll need to install the RTC library too. Go to the Sketch menu –> Include Library… Submenu –> Manage Libraries. A new window will pop up. Search for your the name of the library (RTCZero) and click the Install button. The Library manager will install the library. You might want to open the RTC library documentation in a browser as well. This library should work on any board that uses the SAMD M0+ processor.

Real-time clocks are simple devices. You set the time, then it runs. When you want the time, you read the time. Depending on the software interface of the RTC you’re using, sometimes you can set the time using UNIX Epoch time as well, which is the number of seconds that have elapsed since 00:00:00 Thursday, 1 January 1970. The API may differ from one library to a next, but all RTC libraries will have commands to get and set the hour, minute, second, day, month, and year. The RTCZero is typical in that sense. Here is an example of how to set the time:

  
#include <RTCZero.h>  // include the library
RTCZero rtc;           // make an instance of the library

void setup() {
  Serial.begin(9600);

  rtc.begin(); // initialize RTC

  // Set the time
  rtc.setHours(12);
  rtc.setMinutes(34);
  rtc.setSeconds(56);

  // Set the date
  rtc.setDay(23);
  rtc.setMonth(6);
  rtc.setYear(19);

  // you can also set the time and date like this:
  //rtc.setTime(hours, minutes, seconds);
  //rtc.setDate(day, month, year);

  // if you know the epoch time, you can do this:
  rtc.setEpoch(1564069843);
}

To read the time, you use the getter methods: getSecond, getMinute, getHour, etc.:

 
void loop() {
  int h = rtc.getHours();

  int m = rtc.getMinutes();
  int s = rtc.getSeconds();
  int d = rtc.getDay();
  int mo = rtc.getMonth();
  int yr = rtc.getYear();
  long epoch = rtc.getEpoch();

  // make a String for printing: 
  String dateTime = "";
  if (h < 10) dateTime += "0";
  // add a zero for single-digit values:
  dateTime += h;
  dateTime += ":";
  if (m < 10) dateTime += "0";
  // add a zero for single-digit values:
  dateTime += m;
  dateTime += ":";
  if (s < 10) dateTime += "0";
  // add a zero for single-digit values:
  dateTime += s;
  dateTime += ",";
  if (d < 10) dateTime += "0";
  // add a zero for single-digit values:
  dateTime += d;
  dateTime += "/";
  if (mo < 10) dateTime += "0";
  // add a zero for single-digit values:
  dateTime += mo;
  dateTime += "/";
  if (yr < 10) dateTime += "0";
  // add a zero for single-digit values:
  dateTime += yr;
  Serial.println(dateTime);
  delay(1000);
}

Using the RTC Alarm

The RTCZero library also has the capability to set an alarm and call a function when the alarm goes off. Not all RTCs offer this feature, but since it’s built into the processor, it’s possible for the Nano 33 IoT and the MKR boards. Here’s a simple example that prints a message once a minute:

#include <RTCZero.h>
RTCZero rtc;

void setup() {
  Serial.begin(9600);

  rtc.begin(); 
  rtc.setTime(12, 23, 56);
  rtc.setDate(23, 06, 19);

  // set the alarm time:
  rtc.setAlarmTime(0, 0, 0);
  // alarm when seconds match the alarm time:
  rtc.enableAlarm(rtc.MATCH_SS);
  // attach a function to the alarm:
  rtc.attachInterrupt(alarm);
}

void loop() {
  // nothing happens here 
}

void alarm() {
  Serial.println("Top of the minute");
}

You can match just the seconds for an alarm once a minute (rtc.MATCH_SS) or the minutes and seconds for once an hour (rtc.MATCH_MMSS) or hours, minutes, seconds for once a day (rtc.MATCH_HHMMSS).

Maintaining Time

In order to be truly “real” time, an RTC needs constant power. The built-in RTC of the SAMD M0+ microcontroller will reset to “zero” when power is interrupted (but will continue to increment through a reset provided an initial time is not hardcoded in setup).

For this reason, many RTC breakout boards, such as Adafruit’s DS3231 board, include a battery holder, typically for the kind of long lasting coin-cell batteries found in watches. RTCs powered this way can maintain accurate time for several years without additional power. The Arduino RTC page has notes on maintaining power for the built-in RTC on Arduino Zero and later boards.

Originally written on July 25, 2019 by Tom Igoe
Last modified on August 21, 2019 by David Rios