ropg / ezTime

ezTime — pronounced "Easy Time" — is a very easy to use Arduino time and date library that provides NTP network time lookups, extensive timezone support, formatted time and date strings, user events, millisecond precision and more.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Idea : Improve accuracy aiming sub millisecond

jcdevaux opened this issue · comments

Hi Rop !
First, I'd like to thank you for that nice library.

Millis() and micros()

As far as I can see in sources, you use millis() to compute a timestamp offset from last NTP sync to produce an NTP corrected accurate date aiming ms accuracy (ezTime.cpp:103, 384, ...).

First, why not using micros() instead of millis() as even on smallest Arduino boards @16 MHz (@8 MHz) we got 4 µs (8µs) resolution ?

Local crystal drift compensation

Second, when you use your millis() values, you logically divide by 1000 (which we can call CONSTANT_MS_TO_S).

Couldn't we compensate crystal drift altering that CONSTANT_MS_TO_S value using two (or more) distant NTP sync ?
Something like (in µs) : (micros_sync2-micros_sync1)/((ntp2-ntp1)*1000000) or even with millis(). Kind of temperature compensated crystal but using NTP.

Do you think this will allow to acheive sub millisecond accuracy time sync in local networks ?

Looking forward to hearing from you !

I have modified ezTime with microsecond resolution, and linear interpolation of a set (32) of recent NTP sync events. It also gradually increases the sync interval until it's only checking every 8 hours. The result is accuracy better than 1ms and compensation for crystal drift. It's only tested on ESP32. If there's interest I could clean it up and document it and submit it for merging here. This is an example of the performance (I have a Stratum 0 NTP server on my LAN, but its good on pool.ntp.org too).

image

Yay, nice!

Yes please.

Hi there ! That's nice !

Your linear regression of NTP offset describes a constant drift of you ESP32. That's why you can increase delay between NTP sync. This is not true when you have some temperature variations for example if your crystal is not temperature compensated.

Naturally: keeping a constant eye on it is much better...

How did you mesure your overall accuracy @alwynallan ?

Thanks for encouragement. I'll have it cleaned up and submitted in a week.

Regarding accuracy, I've been using this approach in an ESP8266 application for years. There are statistical techniques to put confidence bands on the locus of the regression line, and reasonable to assume that the accuracy is the half-width of the band at the current time. In my current application the accuracy is limited by millisecond resolution of the time, but usually settles around 2ms as seen below. With microsecond resolution I'm sure it'll be better that 1ms. Below is a typical chart from my ESP8266 application.

image

Regarding quartz crystals they are very strange when studied closely over a long period of time. Identical parts can have positive and negative temperature coefficients, and they can have different natural modes that they stay in for weeks, and then suddenly change, with slightly different frequencies. The also change frequency slightly as they age. The consumer-grade parts are usually "binned" so they'll be within spec (say +-20ppm) but seldom in the middle of the range. I have some that slowly change frequency in a repeating sinusoidal pattern, but the period is 2.5 days, while the temperature variation has a 1-day period. Regression does a good job smoothing all this out and improving on both the crystals and NTP.

An idea about the source of the 2.5 days period ? I agree that temperature is around 1-day period if it's due to ambiant temperature. Is your MCU core load constant ?
What about supply voltage fluctuation ?

For our readers, here 2 interesting links about crystal drift for Arduino and ESP32 :