The DS3231 by Maxim is a “low-cost, extremely accurate I2C
real-time clock (RTC) with an integrated temperature compensated crystal oscillator (TCXO) and crystal.” You can pick these up, battery and shipping included, for under $4 on eBay.
Note: I have updated this to use the DS3231 library by Andrew Wickert, Eric Ayers, and Jean-Claude Wippler. I have made this change for two reasons: firstly it is installable through the Arduino IDE library manager, and secondly it is compatible with the wire library. The old method is included at the end of this article.
There are two example sketches we are interested in that set and retrieve the date from the real-time clock. The first, which sets the clock, is DS3231_set. We can see in this code snippet that it is configured by a string on the serial port:
void GetDateStuff(byte& Year, byte& Month, byte& Day, byte& DoW,
byte& Hour, byte& Minute, byte& Second) {
// Call this if you notice something coming in on
// the serial port. The stuff coming in should be in
// the order YYMMDDwHHMMSS, with an 'x' at the end.
boolean GotString = false;
char InChar;
byte Temp1, Temp2;
char InString[20];
All we need to do to set the RTC is pass a suitably formatted string to the Arduino using the serial monitor.
The days of the week (Dw) is user-defined. Taken from the DS3231 datasheet:
The day-of-week register increments at midnight. Values
that correspond to the day of week are user-defined but
must be sequential (i.e., if 1 equals Sunday, then 2 equals
Monday, and so on). Illogical time and date entries result
in undefined operation.
So what day of the week should we start on? In the US (and Canada and Japan), it is generally Sunday that starts the week, but in Europe it is Monday. International standards to the rescue: Monday is the first day of the week according to the international standard ISO 8601.
So for my code Monday will be 1, Tuesday 2 and so on.
So to set the date and time to the time of this writing (Saturday, July 20th 2019 at 3:37pm I would pass the following string to the Arduino on the serial monitor using the YYMMDDwHHMMSS template:
1907206153700x
The x terminates the string and tells the Arduino to go ahead and process the command (this is because the loop within the Arduino sketch is reading by character and waiting for the terminator, in this case an ‘x’).
Reading the date from the real-time clock is equally simple. Just load the DS3231_test example, and examine the serial monitor.
2019 7 20 6 15 52 27 24h T=25.50 O+
Alarm 1: 6 DoW 15 52 50 enabled
Alarm 2: 20 Date 15 53 enabled148800
We see here on the first line the year, month, day, day of week, hour, minute, and seconds in 24-hour format. T= is the current temperature of the RTC, and O indicates whether the data form the RTC is reliable (O+) or not (O-).
The following two lines are related to the on-board alarms.
Depreciated method:
I am using the RTC library from Henning Karlsen. Download and install this library in the Arduino IDE.
Once installed into the IDE, simply open the DS3231_Serial_Easy demonstration sketch from the library examples.
In the setup() function of this code, there are four lines commented out that will set the clock:
// The following lines can be uncommented to set the date and time
//rtc.setDOW(WEDNESDAY); // Set Day-of-Week to SUNDAY
//rtc.setTime(12, 0, 0); // Set the time to 12:00:00 (24hr format)
//rtc.setDate(1, 1, 2014); // Set the date to January 1st, 2014
To change to today’s date and time (12:38:40 07/20/2019) I made the following changes:
// The following lines can be uncommented to set the date and time
rtc.setDOW(SATURDAY); // Set Day-of-Week to SATURDAY
rtc.setTime(12, 38, 40); // Set the time to 12:38:40 (24hr format)
rtc.setDate(20, 7, 2019); // Set the date to July 20th, 2019
We can see the correct serial output on the monitor for the date change:
Saturday 20.07.2019 -- 12:40:49
Saturday 20.07.2019 -- 12:40:50
One important consideration is that this library does not use the Arduino wire library. However, it is very lightweight and east to use. In the project I have for this, this will not be a consideration as I can simple change the SDA and SCL pins in use to a software implementation (there is also an I2C display in the project that does use the wire library).