Go Down

Topic: Keeping accurate time (Read 20 times) previous topic - next topic

dcb

...
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.

Udo Klein

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 ;)
Check out my experiments http://blog.blinkenlight.net

Constantin

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.

pito

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

Constantin


@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...

fat16lib

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

pito

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

Constantin

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

odometer


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

Code: [Select]

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.
Code: [Select]

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)

Constantin

"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?

odometer


"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?


OOPS! (Well, I told you it was untested code.)

Okay, so try:
Code: [Select]

uint32_t lastTime = 0;
const long oneSecond = 1000000L;

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

Coding Badly


I suspect the compiler is smart enough to know what you intended but, technically, because you are comparing an unsigned value to a signed value the comparison should be extended to 64 bits; which is rather undesirable.  This is probably a better choice...

[font=Courier New]const unsigned long oneSecond = 1000000UL;[/font]

Go Up