Measuring phase diff - RTC's seconds vs. millis()

I want to measure "the phase difference" between the millis() and my RTC's seconds (external). The assumption is both millis and RTC's seconds are relatively stable.

So what I've done:

in a loop for example:
..
// sampling the two signals (RTC secs and millis)
rtc_sec = t.sec;    // I get RTC's seconds 0..59
mil_sec = millis();  // I get millis

// I am trying to measure the diff as: rtc_sec%10 - mil_sec%10000/1000, so the "window" is 10 secs
// I do filtering here - exponential moving average (EMA), because the diff jumps up and down

aver_dt = ( ( (float)(rtc_sec%10) - ( (float)(mil_sec%10000) / 1000.0) ) * 0.005 ) + (aver_dt * 0.995);

After some time the aver_dt shows something like -0.634 (an example) and it is relatively stable. Not sure the algorithm is ok, however.

Now, as my approach is somehow hairy - do you have any idea how to do it better?

The phase difference will depend on the time of day that the Arduino was started plus the drift over time from the difference from the RTC clock and the system clock.

What I would do is connect the 1 PPS signal from your RTC to an interrupt pin and use that interrupt to sample the millis() value. The millis() mod 1000 would be the phase difference.

The phase difference will depend on the time of day that the Arduino was started..

No problem with that - I want to see just the drift, the absolute value is not important at this stage.

Interestingly, after several starts (random against RTC) the number I get after a while (I am sampling the diff in a loop every aprox. 1.2secs) is always around -0.6 (the aver_dt is still noisy, but clearly around -0.6). So there must be some hidden "principle" in it. Trying to understand that.. :~

What I would do is connect the 1 PPS signal from your RTC to an interrupt pin

Still looking for a way how to do it with "RTC's seconds" and some math..

What I want to measure basically is a phase between two saw-tooth shaped signals (see below):

  1. first signal - with discrete values 0..9 (rtc_sec MOD 10),
  2. the second one - a "linear" 0.000 .. 9.999 ( (mil_sec MOD 10000) / 1000).

My working assumption to the process is following:
Let us have stable RTC and millis signals. When we sample both signals (we get rtc_sec and mil_sec values) ANYTIME, the difference (rtc_sec - mil_sec) shall be constant. In order to "normalize" both signals (as the rtc_secs run 0..59) we do MOD with the signals to get them into the same range. When we provide a moving average over a large number of differences (after the MOD, and even the first signal has discrete values), the result shall be constant.

The red colored are sampling times (for example). What I do is simply the difference between the values sampled, and the diff is then averaged by a moving average filter with a "time constant" of about ~400 sampling periods. Not sure I do understand the results yet, however.. (moreover the algorithm is just my first guess...)
PS: corrected MOD 10, and MOD 10000 (for 0 .. 9 and 0.000 .. 9.999).

sawtooth1.bmp (384 KB)

I am new to Arduino and forgive me if I am in the wrong discussion to ask this question. Is it possible to generate a very long wavelength (say 5 kilometers long) and measure the change in phase of the wavelength of the return signal (say from a reflector) and turn this into a distance measurement?

I remember for my Uni days (studying Engineering) that this was a technique used by early survey instruments. This gave an approximate length (say to the nearest kilometer). But then the wavelength was halved and then the phase difference in this signal was also measured which refined the distance and allowed someone to know the distance to the nearest 100 meters, then again halved to know to the nearest 10 meters etc. then it was a matter of adding the numbers obtained together to get the distance. This was the general principal (may not be the exact numbers of course).

Your graph there with the dots for the RTC output, should really look like a staircase, because when you have your red sampling times, they will be measuring the same value on the "flat" part of each step.

Your millis() value also increases in steps, but they are much more tiny.

So whenever you take a measurement, you are effectively calculating the vertical size of a very small triangle ( one tenth as high and wide as your big triangles ). The average size of these triangles is going to dominate your result more than the difference caused by the "phase difference" you are trying to measure, I think.

I really don't understand why use of millis() is so common. It skips numbers. Use micros() instead.(Well, yes, micros() skips numbers too: it counts in steps of 4 microseconds. But better to skip 4 microseconds than a whole millisecond.)