Keeping accurate time

more bullcrap from a newbie who claims to know what the original intent of the atmega was in regards to timekeeping. I cannot help that you are full of crap, that is your problem, deal with it.

your post count and registration date must have gotten hosed then (speaking of bad timekeeping). Still it is microcontrollers and logic what make possible small and accurate clocks that can make adjustments, combined with decent oscillators. But to be in the ballpark you do not need to pimp rtc modules. Use the library, tell vendors to not cut corners on oscillators so you can have a decent timepiece in your arduino by itself.

wbphelps:

MarkT:
In fact I got motivated enough to replace the resonator on my Uno board, partly to see how tricky it was to do.

By any chance to you have a part # for the crystal?

Thanks,
William

Just a standard 16MHz crystal I think - there are different suppliers and different grades but most are 50ppm or better.

You have to have proper load capacitance otherwise you may be off >100ppm. The datasheets contain the formula for proper matching of crystal load capacitance and the caps.

I saw this got pretty heated but I'm chiming in anyways. The original question was about making a clock. The simple fact is, the common resonator absolutely stinks for any reliable time reference over time. Furthermore, a simple MCU with a resonator makes for horrible accuracy. The drift alone is typically extremely noteworthy. And that completely ignores that the MCU only knows a relative time since last power up and not an absolute time reference.

This is why RTCs are so popular. Not only do they tend to have an absolute time reference, they tend to also be reasonably accurate (moreso than a simple resonator), take care of details like days, weeks, months, and especially leap years, and have extremely low power requirements to maintain time without external power. Even better, even cheap RTCs tend to have some form of modest calibration when installed according to their datasheet and more expensive units are both calibrated and actively compensated.

Frankly, creating anything other than the most simpletons of clocks without an RTC is highly questionable, unless its the trip than matters moreso than the destination.

I also read others talking about slamming time corrections from an external source. Be warned this also has some potential issues. If your application is dependent on alarms, relative time, and especially delays, its a great way to either miss them (if using poorly written software), potentially create alarm cascades (if using properly written software), or completely screw up fixed delays. Frequently, SNTP is what people incorrectly refer to when they mention NTP. There is a difference. A good implementation of time management which accommodates for drift will do so via tick interpolation over a finite period of time as well as rejection and error when skew is too large; typically based on accuracy requirements. So for example, if we have 100 ticks of error, it should be slowly interpolated over something like five seconds, minimizing the imposed error over those five seconds. Otherwise, simply slamming in 100 ticks over a 1 tick duration, may cause a cascade of alarms to fire, not to mention completely throw off all relative time measurements by 100 ticks (sleeping for 200 ticks just woke up 100 ticks short). And on real time systems, an alarm cascade can really screw things up royally.

Long story short, any clock should seriously consider even a modest RTC; especially when CPU clocking is a resonator. They have lots of advantages, especially where simple resonators are in use. I have created systems which managed clock skew and distributed time references (SNTP & NTP) for P25 digital radio systems. If you want to point at my low post count, I'll happily laugh in your face. Bluntly, proper time management is a surprisingly deep and complex subject with lots of subtleties waiting to whack the unprepared. Be extremely wary of anyone who attempts to trivialize time management, especially when their sole reference is a resonator. That's not to say CPU counters are without merit, but they can be deceptively alluring for the ignorant.

creating anything other than the most simpletons of clocks without an RTC is highly questionable, unless its the trip than matters more than the destination.

I agree with that, but point out that a high proportion of the Arduino projects one sees are more about the trip rather than the destination.

At Maker Faire I saw an LED clock that displayed time in base 12 on a charlieplexed 9 by 14 LED grid. However accurate or not that clock may be, the maker was more interested in the fun of getting it to work then using it to tell accurate time.

@gerg]
Thanks for this wisdom, you are right that SNTP and NTP are used mixed. I do too - I'm guilty :slight_smile: -

(S)NTP is most used for synchronizing RTC's (or a software datetime lib) in Arduinoland. All RTC (but one) I know can be set up to 1 second precision, so in practice NTP and SNTP have "too much" precision for them. It would be nice if the millis() or micros() could be set according to the decimal part but unfortunately this is not possible on an Arduino AFAIK. OK one can create NTPmillis() and NTPmicros() that uses an offset or a hardware timer or ... So in Arduinoland the decimal part of (S)NTP is mostly dropped, and yes sometimes it is used for rounding to which second is nearest. IN fact 99% of the Arduino sketches would just need the Time protocol (RFC868).

The Arduino has little resources and I assume that adjusting gradually for the drift for an Arduino is possible but it would take quite a bit of the resources leaving little room for the main sketch. (please let someone prove me wrong by building an Arduino NTP server library :slight_smile:

The one second precision of the RTC mentioned before also means - from observing the apps discussed at the forum - that the RTC is seldom (never?) used for high precision timing, in Arduino context most people use millis() and micros() for this. The time of the RTC is mostly used for display and logging, and yes also for low precision timing like switching on/off the light of an aquarium or so. I see two different kind of clocks working side by side each for their specific purpose. And I think it is not bad.

Please keep in mind I was speaking in generalities. I was purposely trying not to be overly specific. Some of my comments need not necessarily apply to the typical Arduino user. An example of this is one thread slamming in a new time while another thread is sleeping. Concurrency is not likely a typical Arduino user's concern. Though is possible if done via an ISR.

robtillaart:
(S)NTP is most used for synchronizing RTC's (or a software datetime lib) in Arduinoland. All RTC (but one) I know can be set up to 1 second precision, so in practice NTP and SNTP have "too much" precision for them. It would be nice if the millis() or micros() could be set according to the decimal part but unfortunately this is not possible on an Arduino AFAIK. OK one can create NTPmillis() and NTPmicros() that uses an offset or a hardware timer or ... So in Arduinoland the decimal part of (S)NTP is mostly dropped, and yes sometimes it is used for rounding to which second is nearest. IN fact 99% of the Arduino sketches would just need the Time protocol (RFC868).

The Arduino has little resources and I assume that adjusting gradually for the drift for an Arduino is possible but it would take quite a bit of the resources leaving little room for the main sketch. (please let someone prove me wrong by building an Arduino NTP server library :slight_smile:

The one second precision of the RTC mentioned before also means - from observing the apps discussed at the forum - that the RTC is seldom (never?) used for high precision timing, in Arduino context most people use millis() and micros() for this. The time of the RTC is mostly used for display and logging, and yes also for low precision timing like switching on/off the light of an aquarium or so. I see two different kind of clocks working side by side each for their specific purpose. And I think it is not bad.

I agree. Let's not lose track of the fact accuracy and precision is always relative to the purpose and requirements. For most people, accuracy to within a minute per year is acceptable for a wall clock. Whereas, accuracy to +- >2 minutes per week is pretty iffy. Still, for an electronics experiment its likely not a problem at all. For a clock beside the bed, its likely okay for the unemployed or soon to be, by the end of the year. :fearful:

Generally RTCs are a reference source of some type. This may include a square wave generator or simply periodic fetching of absolute time whereby interpolation is then used to synchronize CPU timers. As (IIRC) dbc said, there really isn't anything special about RTCs. He's right you can do it on common, non-specialized hardware if your tolerances allow and you use a clocking source which provides the required precision, and then take the time to calibrate and compensate with temp and so on. But then again, RTCs are so cheap, reliable, persistent with low power requirements, frequently with wake on interrupt (frequently allowing for additional power savings), typically fairly accurate, sometimes even highly precise, and all too often completely mitigate a whole slew of subtle software time management bugs, they become really hard to overlook - especially when no other external absolute time reference is readily available (time, sntp, ntp, etc). Whooo! That's a mouthful.

IMOHO, part of the confusion here people are conflating time with timers. Relative timers are easily possible without absolute time. Absolute timers require absolute time. Time, SNTP, NTP, and RTCs are all common sources for obtaining an absolute time reference. So the question becomes, assuming the easy path, do you require absolute time or relative timers; or both. IMOHO, if you require absolute time, your solution needs to include one or more of Time, SNTP, NTP, or an RTC. Again, you're requirements will guide, if not dictate.

Like with most engineering tasks, this is no different. Define your requirements. Understand the problem domain. Craft a solution. My primary purpose for chiming is is that many people don't define their requirements and frequently when they do, time is such a simple construct we all know, so its frequently falsely understood the domain is mastered. As such, crafting a faulty solution is all too easy.

As I've pointed out in another thread, time is subtly hard to get right. As long as you don't underestimate its complexities and truly define your requirements, you'll likely be okay. Otherwise, expect a bumpy road and lessons learned.

As I've pointed out in another thread, time is subtly hard to get right. As long as you don't underestimate its complexities and truly define your requirements, you'll likely be okay. Otherwise, expect a bumpy road and lessons learned.

I agree. "Accuracy" is a term that is vastly undefined and relies on too many unstated assumptions to be useful in most conversations. Unless you are in marketing where there is much to gained by riding on those unstated assumptions. :wink:

Lefty

time is subtly hard to get right

Yeah definitely hard, I did some research upon the NTP protocol and the work of Mills years ago. To my suprise (then) the NTP uses statistics to handle latencies of the network and the server. For me that looked like "the first signs of some variant of the Heisenberg principle" :wink:

I recall that Mills started to investigate NTP for intersolar communication (one time ref per solar system, NASA) to synchronize satellite data. Depending on the relative speed of things he needed to compensate for relativistic effects.

Definitely hard.

gerg:
...
Frankly, creating anything other than the most simpletons of clocks without an RTC is highly questionable, unless its the trip than matters moreso than the destination...

Frankly, building a development board with an irregular heartbeat (resonator) to save a dime is highly questionable to me.

A crystal will be usually ~10 ppm of the mark. So dedicated RTCs are still much better. A resonator will startup faster.

If you insist on precision timing without giving any details on how much accuracy you really need run your Arduino from an external clock and use a PLL to sync it with something like a Trimble Thunderbolt (can be bought for cheap from *bay). If this will not give enought precision then you have an issue :wink:

I have had great luck / happiness with the DS3231. Great chip, well-documented, easy to interface with, and even a couple of libraries to choose from. In the end though I wrote my own reading / bit-shifting routines since some of the libraries I dealt with didn't do that part perfectly for all the variables that the DS3231 supports. No big deal, there are plenty of examples out there that pointed me in the right direction.

Equally fun was writing a routine that turned these values into a float that reflected the microsoft way of tracking time in Excel.

@Constantin: they claim +/-2ppm/year and 5ppm aging - can you confirm that somehow?? Thnks.

pito:
@Constantin: they claim +/-2ppm/year and 5ppm aging - can you confirm that somehow?? Thnks.

Sorry, I hate to be punny but I don't have the time. It's good enough for me...

I did a number of tests with the DS3231. 2 ppm is reasonable If you power it so the temp compensation is maintained. I use 5 volts all the time since the rate does vary a bit at different voltages.

I used a gps pps signal to test the chip. My chips do 1 ppm for short times, a few days. That's as long as I ran them with the gps clock.

Here is a bit more http://forums.adafruit.com/viewtopic.php?f=19&t=17966&p=92197&hilit=ds3231#p92197

@fat16lib: thanks! So you may discipline it via gps and Vcc :).

Using a GPS receiver is about as good as you're going to get... hard to beat atomic clocks that operate under close supervision.

RuggedCircuits:
Try just using millis() directly instead of delay(). Something like (warning...untested code):

uint32_t lastTime;

void loop(void)
{
  if ((millis() - lastTime) >= 1000) {
    lastTime += 1000;
    digitalClockDisplay();
  }
  ......
}

This is actually a very smart way of doing it, because you avoid the problems with millisecond rollover.
I wonder why people seem to think that using the built-in millisecond counter inevitably results in problems at rollover.

Alternatively, I would suggest using the microsecond counter.

uint32_t lastTime = 0;
const int oneSecond = 1000000;

void loop(void)
{
  if ((micros() - lastTime) >= oneSecond) {
    lastTime += oneSecond;
    digitalClockDisplay();
  }
  ......
}

This rolls over every 1.2 hours or so, but that is not a problem in this sort of application. Another advantage -- in this application, quite a great one -- is that a clock that runs too fast or too slow is easily adjusted by changing the value of the constant oneSecond. (sort of like the fast/slow lever on a wind-up alarm clock)

"const int oneSecond = 1000000;"

Can this work? I'd like to think you need a long for such a big number. Beyond that, wouldn't one have to use 1000000L?