A RTC is a real time clock that runs on a battery and keeps time even if the power fails. With a real-time clock you can keep track of long time series even if you reprogram your microcontroller or disconnect it from USB or a power plug.
Most microcontrollers, including the Arduino, have a built-in timer called millis (). There are also timers built into the chip that can track longer periods of time like minutes or days.
So why should you have a separate RTC chip?
Well, the main reason is that millis () only keeps track of time since the last time power was applied to the Arduino. That is, when the power is turned on, the millisecond timer is reset to 0. The Arduino does not know that it is "Tuesday" or that it is "March 8". The Arduino can only indicate that, for example, 14,000 milliseconds have passed since it was last turned on.
While this type of timing is fine for some projects, some projects such as data loggers, clocks, etc. need to have a consistent time measurement that does not reset when the Arduino battery fails or is reprogrammed and this is where the RTC comes in!
The RTC chip is a special chip that only tracks time. It can count leap years and knows how many days there are in a month.
Arduino and the RTC DS3231
You can easily connect the RTC breakout to any microcontroller. You just need to make sure I2C is available, and then port the code - it's pretty easy!
This example uses an Arduino microcontroller board.
Pinout and Wiring:
- Connect Vin to the power supply, 3-5V is fine. Use the same voltage that the microcontroller logic is based on. For most Arduinos, this is 5V.
- Connect GND to the common power / data ground.
- Connect the SCL pin to the I2C clock SCL pin on your Arduino. On an Arduino Uno this is also known as A5, on a Mega it is also known as digital 21 and on a Leonardo / Micro digital 3.
- Connect the SDA pin to the I2C data SDA pin on your Arduino. On a UNO this is also known as A4, on an Arduino Mega also as digital 20 and on a Leonardo or Micro as digital 2.
The DS3231 has a default I2C address 0x68. This cannot be changed.
Download of the RTCLib
For the RTC library a fork from JeeLab's excellent RTC library RTClib is used.
To start reading data, you need to download Adafruit's RTCLib from the Github repository. You can do this by visiting the Github repo and downloading manually or by downloading the zip file directly.
Rename the uncompressed folder to RTCLib and verify that the RTCLib folder contains the RTCLib.cpp and RTCLib.h files.
Place the RTCLib library folder in your arduinosketchfolder / libraries / folder.
You may need to create the library subfolder if this is your first library. Restart the Arduino IDE.
RTC Test
Use a test sketch to read the time from the RTC once per second. First, remove the battery from the holder if the Arduino is not powered or connected to USB. Wait 3 seconds and replace the battery. This will reset the RTC chip.
Load demo
Open File-> Examples-> RTClib-> DS3231 and load the demo on your Arduino wired to the RTC.
Check the serial console for 9600 baud. After a few seconds, you will see the report that the Arduino has noticed that the DS3231 RTC has been turned on for the first time, and the time is set based on the Arduino sketch.
Disconnect your Arduino and the RTC for a few seconds (or minutes, hours, or weeks) and reconnect it.
The next time you run it, it won't display the same "RTC lost power" message, but it will immediately display and inform you of the correct time!
From now on, you will not have to set the time: The battery will last at least 5 years.
Query the time
To be able to query the time, let's look at the sketch again.
void loop () {
DateTime now = rtc.now();
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(" (");
Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
Serial.print(") ");
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
Serial.println();
There is only one way to get the time using the RTClib, which is to call now (), a function that returns a DateTime object describing the year, month, day, hour, minute, and second when you called now ().
There are some RTC libraries where you call something like RTC.year () and RTC.hour () instead to retrieve the current year and hour. However, there is a problem if you ask for the minute right before the next minute at 3:14:59, and then the second right after the minute (that is, at 3:15:00). You then see the time as 3:14:00, which dedects a minute pause. If you do it the other way around, you might get 3:15:59 - that is, one minute in the other direction.
Since this is not a particularly unlikely event - especially if you are polling the time frequently - we take a snapshot of the RTC and then can divide it into day () or second () (as seen above). It's a bit more work, but it's worth it to avoid the error!
You can also get a "timestamp" from the DateTime object by calling unixtime, which will then count the number of seconds (not leap seconds) since midnight (January 1, 1970).
Serial.print(" since midnight 1/1/1970 = ");
Serial.print(now.unixtime());
Serial.print("s = ");
Serial.print(now.unixtime() / 86400L);
Serial.println("d");
Since there are 60 * 60 * 24 = 86400 seconds in a day, we can count days from this point. This can be useful if you want to keep track of how much time has passed since the last query.