Chronodot and split seconds

by odometer on Tue Jan 15, 2013 2:52 pm

I own a modified Alpha Clock Five.

I modified the firmware to use half-seconds, rather than seconds, as the base unit of timekeeping. This way, I have (depending on display mode) either a "spinning" seconds indicator which moves in proper, 1/8 minute steps (1 step = 15 units) or a normal digital display of seconds (1 step = 2 units). I do not have a blinking colon in any display mode, but if I wanted one, I would want it to blink at 1 Hz, and for that I would need fractional seconds. (The blinking colon in the firmware blinked at 0.5 Hz, that is, 1 cycle in 2 seconds.)

Now. As I understand it, the Chronodot must have some sort of internal count of fractional seconds, but there is no direct way to get at this count. So what I did was, I made the microcontroller act as a slave clock with the Chronodot as the master. Every 10 minutes (at xx:x9:59.5), the microcontroller freezes the time until the Chronodot reports the seconds as 00 (or 01), and only then does the microcontroller start a new minute.

As long as the clock has power, this method seems to work very well, with the clock keeping time to within 1 second in 2 months. However, when power to the clock is cut, this seems to disrupt the fractional seconds. I have already given my method for indirectly getting at the fractional seconds; this should (theoretically) restore them within the first 10 minutes that the clock has power, but it doesn't seem to work in practice.

As for my "master / slave clock" system: the "slave" reads the full date and time from the "master"/Chronodot only at power-up. After that, the "slave" does not read data from the "master" except for the seconds (and only the seconds) as described above.

Has anyone else had experiences similar to mine?
odometer
 
Posts: 98
Joined: Sun Aug 21, 2011 10:01 pm

Re: Chronodot and split seconds

by adafruit_support_bill on Fri Jan 25, 2013 8:42 am

The chronodot can be configured to put out a 1-second square-wave signal on the SQW pin. This would be the best way to sync your fractional seconds counter with the change of a second.
User avatar
adafruit_support_bill
 
Posts: 25582
Joined: Sat Feb 07, 2009 9:11 am

Re: Chronodot and split seconds

by odometer on Sat Jan 26, 2013 7:15 pm

Thank you for trying to help, but:

1) I'm not about to muck around with the hardware as I don't know what I'm doing.

2) What I am really wondering about is the Chronodot's timekeeping itself. It seems to me that as long as it has a continuous source of power (from an outside source, that is, not its battery), then it keeps time wonderfully -- however, when this source of power is interrupted, that seems to throw the Chronodot off by a fraction of a second. I say "seems" because I'm not 100% sure that that is "it" and not "me". Has anyone else had a similar experience?

Also:

3) How did Adafruit et al. settle on using a chip which uses the baroque Gregorian calendar, and on top of that, will not allow one to read its count of fractional seconds? (Think of a stopwatch application or the like.) Why not one which uses raw Unix time or something, and convert on the fly? Either that, or a straight count of days (1, 2, ..., 31, 32, ...) and conventional hours, minutes, and seconds.

4) Is the granularity of the Time library still 1 whole second, and if so, how does one deal with this?

By the way, I find this video inspiring:
http://www.youtube.com/watch?v=rxZ26SnzeUQ
odometer
 
Posts: 98
Joined: Sun Aug 21, 2011 10:01 pm

Re: Chronodot and split seconds

by adafruit_support_bill on Sun Jan 27, 2013 7:25 am

that seems to throw the Chronodot off by a fraction of a second. I say "seems" because I'm not 100% sure that that is "it" and not "me".

I would be inclined to trust the Chronodot. I have two Chronodot-based clocks that have been going for several years now and they are the most accurate ones in the house.

will not allow one to read its count of fractional seconds? (Think of a stopwatch application or the like.)

Consider that it takes some time to read and decode this data from the device too. High-resolution timing is best handled in the microprocessor itself. Once you read the time of day and date information, you can use the SQW output to generate a low-latency interrupt precisely on the second. In this way, the RTC provides an accurate time reference and correction for any drift in the microprocessor timing.

Is the granularity of the Time library still 1 whole second, and if so, how does one deal with this?

I believe it is. But internally you have "millis()" Once you sync to the SQW reference, you can calculate the milliseconds from the second boundaries with simple subtraction.

Nice video by the way :D
User avatar
adafruit_support_bill
 
Posts: 25582
Joined: Sat Feb 07, 2009 9:11 am

Re: Chronodot and split seconds

by odometer on Sun Jan 27, 2013 4:36 pm

I would be inclined to trust the Chronodot. I have two Chronodot-based clocks that have been going for several years now and they are the most accurate ones in the house.


I would trust it, as well... except that, for purposes of "battery backup", it seems to lose fractional seconds. I wonder: if you cycle power on and off a lot, will this loss be cumulative, and add up to many whole seconds?

Is the granularity of the Time library still 1 whole second, and if so, how does one deal with this?


I believe it is. But internally you have "millis()" Once you sync to the SQW reference, you can calculate the milliseconds from the second boundaries with simple subtraction.


What I meant to say is, the Time library assumes fractional seconds simply don't exist: if you want to get at them, you have to jerry-rig something yourself.

It seems that there are effectively two kinds of timekeeping here. One of them, accessible through millis() and micros(), has high precision, but its long-term accuracy is anywhere from mediocre to horrible. The other source of timekeeping is what you get from the Chronodot, and it has excellent long-term accuracy but low precision. The operating assumption seems to be that one does not want/need both precision and long term accuracy together.

If one wants to timestamp events using finer than 1-second precision, this is made difficult. If one wishes to construct a clock which counts time in increments other than 1.00000 second, this is made very difficult. The behavior of the seconds in a sidereal clock (1 "second" ≈ 0.99727 standard second) or Mars clock (1 "second" ≈ 1.02749 standard seconds) -- and both of these types of clock were discussed on these forums -- requires some wizardry to get right. (The former will appear to skip seconds; the latter, to stop for a second.) And as I've mentioned, even an interval of 0.5 second is not supported by the library.

For working with the Chronodot, I have had to create my own tools. I have already described how I worked around the lack of fractional seconds. I have also created an implementation of Daylight Saving Time, as a display hack (i.e. in the summer, the displayed time will be one hour later than the time from the Chronodot). The Time library doesn't support Daylight Saving Time, either.
odometer
 
Posts: 98
Joined: Sun Aug 21, 2011 10:01 pm

Re: Chronodot and split seconds

by adafruit_support_rick on Sun Jan 27, 2013 6:39 pm

I think you've missed adafruit_support's point. Briefly:

1) high-precision time-keeping on an external device which uses a serial communications protocol is impractical due to indeterminacy in the communications protocol. High-precision is best accomplished with the processor's built in hardware.
2) the built-in hardware has high precision but poor accuracy over the long-term. Therefore, the idea is to keep it synchronized with the accurate external time base via the SQW interrupt. That way, you get both accuracy and precision.
User avatar
adafruit_support_rick
 
Posts: 8612
Joined: Tue Mar 15, 2011 10:42 am
Location: Buffalo, NY

Re: Chronodot and split seconds

by adafruit_support_bill on Sun Jan 27, 2013 7:41 pm

I would trust it, as well... except that, for purposes of "battery backup", it seems to lose fractional seconds.

But your method of measuring these alleged lost fractional seconds is fundamentally flawed due to the latency of querying the RTC.
User avatar
adafruit_support_bill
 
Posts: 25582
Joined: Sat Feb 07, 2009 9:11 am

Re: Chronodot and split seconds

by odometer on Sun Jan 27, 2013 9:19 pm

Stephanie told me that one of her projects checked the time from the Chronodot something like 100 times a second with no problem.

I'm talking about something like 1/4 of a second.

The reason I posted the video is this: The clock in the video is a slave clock. It receives an impulse once each minute, yet it manages to show seconds. How does it do this? By counting seconds only up to 59, then waiting for the next impulse. If you look at the video, you will see that this scheme is not perfect: "59" lasts for around two seconds rather than only one.

This inspired me when I wrote my code. In my case, the Alpha Clock Five has its own crystal (not in the Chronodot) for timekeeping. This means that, on its own, it will keep time just fine for a number of minutes (or even hours). However, I want more long-term accuracy, hence the Chronodot. I already explained how, every ten minutes, the microcontroller resynchronizes with the Chronodot. Mind you, it only checks the seconds from the Chronodot, because that's all it needs. Only on initial power-up is there any need to read more than the seconds.

If there is no external RTC, how does the Time library know when to start a new second? What if I want to get at these fractional seconds together with the whole seconds? (I want both in one go, so as to avoid errors caused by reading just as a new second starts.)
odometer
 
Posts: 98
Joined: Sun Aug 21, 2011 10:01 pm

Re: Chronodot and split seconds

by adafruit_support_bill on Mon Jan 28, 2013 5:48 am

Stephanie told me that one of her projects checked the time from the Chronodot something like 100 times a second with no problem.

Not saying it can't be done. Just very inefficient.

This inspired me when I wrote my code. In my case, the Alpha Clock Five has its own crystal (not in the Chronodot) for timekeeping. This means that, on its own, it will keep time just fine for a number of minutes (or even hours). However, I want more long-term accuracy, hence the Chronodot. I already explained how, every ten minutes, the microcontroller resynchronizes with the Chronodot. Mind you, it only checks the seconds from the Chronodot, because that's all it needs. Only on initial power-up is there any need to read more than the seconds.

So take that strategy a step[ further. You read the Chronodot at startup. Then once a second you get an interrupt and re-sync the time library. You clock is never of by more than a few picoseconds at most and you never have to wait for the seconds to roll over. You never even have to poll the Chronodot again until the next power cycle.

If there is no external RTC, how does the Time library know when to start a new second?

It uses a millis() which is derived from the processor clock.
User avatar
adafruit_support_bill
 
Posts: 25582
Joined: Sat Feb 07, 2009 9:11 am

Re: Chronodot and split seconds

by adafruit_support_rick on Mon Jan 28, 2013 11:24 am

odometer wrote:If there is no external RTC, how does the Time library know when to start a new second? What if I want to get at these fractional seconds together with the whole seconds?

Ah. I think perhaps you don't quite understand how the Time library works. First of all, the Time library is designed to support the C language time functions, which, by definition, have a resolution of 1 second. The time function now() returns a 32-bit value representing the number of seconds since Jan 1, 1970. To get the equivalent number of milliseconds, you would need at least a 42-bit number. The C time system was never designed for high-resolution timekeeping.

Secondly, the Time library does NOT keep time. It does not "know" when to start a new second. In fact, it does nothing at all between calls to now(). Instead, it relies on the system time kept by the computer, which is simply a count of milliseconds since the last reset (and also a 32-bit number, so it overflows every 49.7 days). Whenever you call now(), the library uses the system time in milliseconds to compute the C-language time in seconds.

So, the system time has the precision you're looking for, and the Time library does not. Further, the Time library is no more accurate than the system clock. Inaccuracies in the system clock are down to variations in individual crystal frequencies, power fluctuations, temperature variations, etc.

The Chronodot is designed to address the inaccuracies of the system clock by using a temperature-controlled RTC chip. It is also designed to support the C-language/Unix/wall-clock style of timing, where nothing more than 1-second resolution is required.

However, to support higher-precision applications such as yours, the Chronodot is also designed to produce the 1Hz SQW signal. The intention is that this signal be used to sync the millisecond-level system clock once per second. The worst system clock I've ever seen was off by about 1 in 10,000 (it wasn't on an arduino, BTW), but that is still ten times better than you need if you're correcting it every 1000ms.

So, to answer your questions:

- There is no other time system besides that provided by the system clock. The Time library is strictly derived from that. The system clock can be made more accurate by using the SQW signal from the Chronodot.

- If you want fractional seconds, you don't use the Time library at all*. You do the same thing the Time library does, and call millis() to get the system time.

------------------
*Unless, of course, you want to modify the Time library. In that case, you would add a function to the Time Library to return the value of prevMillis, which is the fractional time left over after each call to now():
Code: Select all
time_t now(){
  while( millis() - prevMillis >= 1000){     
    sysTime++;
    prevMillis += 1000;   
#ifdef TIME_DRIFT_INFO
    sysUnsyncedTime++; // this can be compared to the synced time to measure long term drift     
#endif   
  }
  if(nextSyncTime <= sysTime){
   if(getTimePtr != 0){
     time_t t = getTimePtr();
      if( t != 0)
        setTime(t);
      else
        Status = (Status == timeNotSet) ?  timeNotSet : timeNeedsSync;       
    }
  } 
  return sysTime;
}
User avatar
adafruit_support_rick
 
Posts: 8612
Joined: Tue Mar 15, 2011 10:42 am
Location: Buffalo, NY