[time-nuts] accurate 60 hz reference chips/ckts

Tom Van Baak tvb at LeapSecond.com
Sat Dec 16 07:02:23 EST 2017


I sent a note to Vlad off-list about the bug in the MCU code, but it's worth a reminder to the list as well since many of you are programmers and this arcane issue comes up every once in a while here and on the web.

The way to compute time differences of free-running binary time counters is subtraction. One line of code. There is no need to special case overflow / rollover / wraparound. It is the very nature of unsigned or 2's compliment signed binary arithmetic that subtraction is sufficient. So the bug-free code is just this:

         uwIC2Value2 = (HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1));
         uwDiffCapture = (uwIC2Value2 - prevtimer);
         prevtimer = uwIC2Value2;

If you'd like a simple example why this is correct and a demonstration of what the bug was, see:

http://leapsecond.com/tools/deltatim.c

/tvb

----- Original Message ----- 
From: "Vlad" <time at patoka.org>
To: "Jeremy Nichols" <jn6wfo at gmail.com>
Cc: "Discussion of precise time and frequency measurement" <time-nuts at febo.com>
Sent: Friday, December 15, 2017 9:41 AM
Subject: Re: [time-nuts] accurate 60 hz reference chips/ckts



My setup is pretty simple indeed. This is 9.830400MHZ OCXO which 
clocking MCU. Then it is Zero-Cross detector which connected to capture 
timer.
The MCU counting the intervals between of each zero-cross event and 
number of events occurred.

     if (htim->Instance == TIM5 && htim->Channel == 
HAL_TIM_ACTIVE_CHANNEL_1) {
         uwIC2Value2 = (HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1));
         if (uwIC2Value2 >= prevtimer) {
             uwDiffCapture = (uwIC2Value2 - prevtimer);
         } else {
             uwDiffCapture =((0xFFFFFFFF - prevtimer) + uwIC2Value2);
         }

         prevtimer = uwIC2Value2;

         // MAIN Time calculation
         if(++uwCapT > 59) {                  // Every 60 cycles (60hz)
             if(++maintime.Seconds > 59) {
                 maintime.Seconds = 0;
                 if(++maintime.Minutes > 59) {
                     maintime.Minutes = 0;
                     if(++maintime.Hours > 23)
                         maintime.Hours = 0;
                 }
             }
             uwCapT = 0;
        }

Once an hour the program prints its internal clock (MCU time), RTC time 
and MAIN time

# Uptime:       476 hours
# RTC time:     13:00:00
# MCU time:     13:00:00
# MAIN time:    13:00:01

The graph shows the "delta" between of RTC and MAIN.




More information about the time-nuts mailing list