This issue has bee perplexing me for several years, today I decided to explore it further. You see, I need a reasonable accuracy on a long term clock for my chicken coop automation project. A minute or so a year is not an issue, but I often see 5 or more minutes a month in time errors. If I reset the RTC, all is good, but I can see the drift. So yesterday and today I spent large parts of the day researching to figure out the correct way to sync the RTC with the system clock. I learned this is supposed to happen automatically every 5 minutes with the library(ies) I am using. DS1307RTC - PJRC, and TimeLib. I wanted to see the sync actually happen, so I stuck a Serial.println into the timelib .cpp file. It simply prints "sync" when the setSyncProvider is called. (There is also a function to allow customization of the sync, but I am running the default 300 Sec) The serial monitor confirms the print during initialization, and then that is that...never see it again!
So, I did more searching, and found Jack Christensen's DS3232RTC lib. One of the examples compares the drift of the millis timer to the RTC. I had to move my exploration to a Duelmilanove I used for older libs, and found his code quite useful as I was able to set my DS3231 accurately with the serial example. Then I noticed the mcu-clock-drift example, and loaded it up. It reports that in 15 minutes I lost 2 seconds. The same sync annotated library is used, and no sync other than the initial has shown in hour or so this has been running...I also have not had another lost time report. No other hardware but the RTC module is running on this board. My long term board out in the coop is an Uno. And I am developing on a Nano_Every, (that is why the DS3232 doesn't work...it falls into INCOMPATIBLE libs)
In keeping with the forum rules, a copy of the running code is posted below:
// Arduino DS3232RTC Library
// https://github.com/JChristensen/DS3232RTC
// Copyright (C) 2018 by Jack Christensen and licensed under
// GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html
//
// Example sketch to demonstrate microcontroller clock drift vs. RTC.
// The MCU's time of day is synchronized with the RTC every five minutes (by default).
// Between syncs, the MCU's time of day is goverened by its system clock (which
// also is used for millis). Because the MCU system clock and the RTC cannot be
// expected to run at identical rates, discontinuities in the MCU's time of day
// will occur when its time is synchronized with the RTC.
//
// We can see the drift and discontinuities by printing both millis and
// the time of day together.
//
// Jack Christensen 27Dec2018
#include <DS3232RTC.h> // https://github.com/JChristensen/DS3232RTC
void setup()
{
Serial.begin(115200);
Serial.println(F("\n" __FILE__ " " __DATE__ " " __TIME__));
setSyncProvider(RTC.get); // the function to get the time from the RTC
Serial.print(F("RTC sync "));
if (timeStatus() == timeSet)
Serial.println(F("OK"));
else
Serial.println(F("FAIL!"));
}
// when the MCU's time of day changes, if it did not move forward
// by one second, or if millis changed by something other than about
// one second, then print the millis and time values before and after.
void loop()
{
static uint32_t msLast;
static time_t tLast;
uint32_t ms = millis();
time_t t = now();
if (t != tLast)
{
if (t - tLast != 1 || ms - msLast > 1010 || ms - msLast < 990)
{
Serial.print(msLast);
Serial.print(' ');
Serial.print(ms);
Serial.print(' ');
printTime(tLast);
Serial.print(' ');
printTime(t);
Serial.println();
}
tLast = t;
msLast = ms;
}
}
// format and print a time_t value
void printTime(time_t t)
{
if (t > 0)
{
char buf[25];
char m[4]; // temporary storage for month string (DateStrings.cpp uses shared buffer)
strcpy(m, monthShortStr(month(t)));
sprintf(buf, "%.2d:%.2d:%.2d %.4d-%.2d-%.2d",
hour(t), minute(t), second(t), year(t), month(t), day(t));
Serial.print(buf);
}
else
{
Serial.print(F("Start"));
}
}
Here is the serial monitor output generated thus far. under the path line, there is "sync", that is generated from my addition to Time.cpp. (The other "sync" is part of the program. Below is the last two functions in the library in which I added the Serial.print for debugging.
void setSyncProvider( getExternalTime getTimeFunction){
getTimePtr = getTimeFunction;
nextSyncTime = sysTime;
now(); // this will sync the clock
Serial.println("sync"); //added by me
}
void setSyncInterval(time_t interval){ // set the number of seconds between re-sync
syncInterval = (uint32_t)interval;
nextSyncTime = sysTime + syncInterval;
}
Conveniently, these are the last two listed functions in the file, should anyone want to look that deep.
My question of course is what do I need to do to get the RTC to update the system clock? I thought I might set the "setSyncProvider" into a millis() loop next to see what that causes, as I know it runs the update.
Any suggestions?
BTW, I want to thank Paul and Jack for all their work, not only on RTCs, but their activity all around! Great work and help!! Also, thanks to all those active here on the Forum! Happy New Year!
-fab