For the clock to know how much time has passed, it measures the number of tuning-fork oscillations.
But how much time has passed after a certain number of oscillations?
This is where an estimator comes into play. We need to estimate the frequency of the tuning fork with a given model and a given environment input.
Roughly speaking: If the model says: "Yup, at this temperature the fork oscillates at 440.1 Hz", then the passed time can be derived from the number of measured oscillations (let's say, 1000) by `1000 * 440.1 Hz = 2.272210861s`. The easiest model is that the tuning fork will always resonate at 440Hz, as the original project used.
They got drift of around 60-120 seconds per day, which is a drift of around 1ms/s.
(As a side note: phase noise is not considered in this project, but only drift.)
Nice, but how does the model know that? And what kind of model is that? And how precise can it get?
These are the main project questions that I wanted to find out.
For that, I separate the usage into two phases: Measurement and Application.
In the measurement phase, I use a precise reference* to log the actual frequency against the temperature.
Also, offline on the computer, I try to find and apply functions that can model the seen behavior, and find/optimize the parameters to fit the measured frequency as good as possible.
In the application phase, I then use the offline-trained (No AI! Only statistics!) now-constants for the given model in the clock to estimate the frequency and thus, the passed time since startup. Showing the actual current time is then nothing more than adding an time offset at setting-the-clock on top of the passed-time-since-setting-clock.
So, just to wrap up: We shift what is "knowns" and "unknowns" in the phases. First, in the Fork Measurement Phase, we know the Fork frequency and temperature, but don't know the model parameters that fit the behavior.
Then, in the Application Phase, we don't know the true fork frequency, but know the model, its parameters, and the temperature to estimate that!
Currently, with a fresh calibration phase and without standing in direct sunlight (I can't model that unless I add an illumination sensor), it achieves a drift of ~2.5 seconds per three days, which results in around 10µs/s of drift! That is a factor of 100 better than uncalibrated, which I consider a project success :)
