In this article I will introduce you swRTC, a software implementation, based on timers, of a Real-Time Clock (or RTC) for Arduino boards and Atmel microcontrollers.
The library actually it supports several Atmel microcontrollers:
- Atmega640/1280/1281/2560/2561 and Arduino MEGA boards
- Atmega48/88/168/328 and Arduino 2009/UNO boards
- Atmega644/1284 and Sanguino boards
- the swRTC library needs the Arduino IDE v. 0022 to work with Atmega48/88/168/328/328 (with or w/out the “P”, PicoPower, core), with Atmega640/1280/1281/2560/2561 and with Atmega8/8A;
- to work Attiny24/44/84, Attiny25/45/85 and Attiny2313/4313 you need the Tiny Core libraries that you can download from http://code.google.com/p/arduino-tiny/
- to work with Atmega644/1284 you need the Sanguino core libraries that you can download from http://sanguino.cc/useit
Directions to install and use the Tiny and Sanguino cores are provided from their respective authors.
- uncompress the archive and copy the swRTC folder inside the /librariesfolder inside your sketchbooks’ folders. If that folder doesn’t exist, you have to create it.To know where the sketchbooks folder is located, open the Arduino IDE then select from the menu “File/Preferences” and look at the path in “Sketchbook location”.At the end, you should have something similar to this (for Linux): /home/username/sketchbook/libraries/swRTC
- After that, you have to replace a file of the Tiny core. Make a backup copy of it in case you need to roll back to the original one.To do this, find the file named core_build_options.h that is located in your-arduino-IDE-folder/hardware/tiny/cores/tiny/ and rename it to core_build_options.bck (or a name you like it).
- Then, copy the core_build_options.h that comes from the swRTC into the previous path.
This will permit to have both the swRTC library and the delay/millis functions from Arduino IDE up and running on Tinyx5/x4/2313 microcontrollers.
Usage & methods
Include the library in your sketch with
To use the library, first you have to create an instance of the library, i.e.:
Then you have to set up the internal clock with valid time&date. This can be done via software or by the user through a user interface (i.e. LCD display) using the following methods:
rtc.setTime(hours, minutes, seconds);
rtc.setDate(day, month, year);
It is suggested to stop the swRTC before to change the time and/or the date with:
and then to start it again, after changes are done, with:
The method startRTC() also sets the HW timer according to the clock frequency of your Arduino/Atmel microcontroller, synchronizing the prescaler of the timer to match the correct timings.
To get the time&date you can use the following methods:
Most of the above methods return a byte value, only getYear() returns a signed integer value.
If you want to know if a specific year is a leap year, you just have to call:
to get a boolean value that is true in case of a leap year. The argument “year” is optional: if you don’t provide it, the library will check the current year.
The library can work with timestamps too.
The first function returns the number of seconds since the beginning of a particular dateepoch (1900 or 1970). By default, it returns the number of seconds since 1970.0, or 1970/01/01 but, the UNIX era, but you can also use the epoch 1900.0, or 1900/01/01. The second one sets the internal clock using a timestamp (i.e. a timestamp provided from an NTP server). If specified, epoch will be used. The third and the forth functions return a number indicating the weekday of a given timestamp of of the current day, starting from 0 for sunday to 6 for saturday.
There are two more functions that are used to correct the difference between the time of the internal clock and the real time.
Allowed values are integer values between -8,400 and 8,400 (max -14.0 or +14.0 minutes/day). The deltaT is the number of decimal seconds per day to apply to the RTC to correct the deviation from the real time. If your RTC is faster than the real time, try adjusting deltaT with positive values, if your RTC is slower, try a deltaT with a negative values.
I.e. 102 means a correction of 10200 ms/day, 10.2 seconds/day.
getDeltaT(), on the other hand, returns the current value of the time correction.
Since release 1.2.0, the library supports the use of the internal Real-Time Counter (RTC) present on several MCUs. This module permits to use the timer 2 in asynchronous mode with an external 32,768 Hz crystal. Setting up the timer 2 with a prescaler of 128, we get 1 overflow every 1 secon so that we can increment the software clock in a more accurate manner. At the moment, the use of deltaT is not supported with the use of the RTC module.
To use the RTC module (that is present only in Atmega88/168/328, Atmega8, Atmega344/644/1284 and Atmega1280/256x), just add the following #define before the inclusion of the library:
The Real-Time Counter can only be used with the internal oscillator due to the fact that the external 32,768 Hz crystal must be connected to the same pins used for the normal crystals (don’t forget to add 2 18/22pF ceramic capacitors).
The library has been modified and now the .cpp file has been removed, while its content has been included in the header file. This does not change the usage of the library itself.
Supported frequencies/microcontrollers and limitations
The library is interrupt driven and uses an 8-bit internal timer. This is the complete list of the supported microcontrollers:
- ATMEL Atmegax0: Atmega640/1280/1281/2560/2561
The library supports the Atmel microcontrollers Atmega640/1280/1281/2560/2561; the Atmega1280/2560 are the chips that are installed on Arduino MEGA/MEGA2560 boards
- ATMEL Atmegax8: Atmega48/88/168/328/328 and their /P (PicoPower core) variants (this does not mean that the specific micro is supported from the Arduino IDE and/or avrdude too)
The library supports the Atmel microcontrollers Atmega48/88/168/328 and their /P variants. The library uses the timer 2. No limitations are on Arduino INT0/timer0 based functions like delay() or millis() but keep in mind the you cannot use the PWM functions on pins 3 and 11 because PWM on those pins uses INT2/timer2, that is used by swRTC.
- ATMEL Atmega8/8A
This is the micro prior to Atmegax8 series. It has been used on ArduinoNG. With this micro the library uses the timer 2.
- ATMEL Attinyx5: Attiny25/45/85
On this family of micros the library uses the INT0/Timer 0. Delay() & millis() functions, that in the Tiny core are based on INT1/timer1, so we can use the INT0/timer 0 with no conflicts.
- ATMEL Attinyx4: Attiny24/44/84
The library uses the INT0/Timer 0 because timer 1 is a 16 bit counter. To do this, we have moved the delay() and millis() functions on INT1/timer1 thanks to the modified core_build_options.h file.
- ATMEL Attiny2313/4313
Same for Attiny24/44/84: we have moved delay() and millis() functions to timer 1 to use the 8-bit timer 0.
- ATMEL Atmega644/1284 and their /P variants
The library uses the timer 2.
How it works
The library sets an internal timer in counter mode to have 1 overflow interrupt exactly every 1 millisecond. Every 1000 ms it increments the internal registers starting from seconds to finish with years to keep the running of the time.
To do this, is calculates the correct starting value of the counter and the prescaler of the timer, depending on the system frequency. It also chooses the correct timer because this trick only works with 8-bit counters. On some Attiny micros, the library must move the delay/millis functions on timer 1 because these micros have only 2 timers, and only timer 0 is a 8-bit timer.
deltaT introduces an anticipation or a delay while the register of the seconds is updated so that we can have 1 “software” second that is longer or shorter than 1 real second.
- 1.1.1: fixed a bug in setDeltaT
- 1.1.0: new syntax for setDeltaT – new method getDeltaT
- 1.0.6: fixed a bug in the function used to set the clock given a timestamp
- 1.0.5: new the method getWeekDay
- 1.0.3: added support for clocks at 4MHz
- 1.0.2: fixed a bug in the getTimestamp function
- 1.0.1: minor update to introduce the new license of the library: now it’s released under GNU GPL3 or newer
- 1.0: first stable release
- 1.1.2: getDelta now returns the value of deltaT with the right sign
- 1.2.0: now it supports the internal Real-Time Counter (if present)
- 1.2.1: minor adjustments
- 1.2.2: fixed a bug that prevented the getWeekDay from returning the correct weekday for leap years for dates before the 1st of march
- 1.2.3: fixed the type of the prototype of the function setClockWithTimestamp
- 1.2.4: updated to use with latest Arduino IDE branches (>=1.6.7)
This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
Written by Leonardo Miliani with the contribution of lesto from the forum of www.arduino.cc.