Chrony (the NTP server software) has temperature compensation built in, using a quadratic forumla to estimate the effect of temperature changes have on the speed of the local oscillator the clock is based off of. Chrony can use this while it is offline (for non stratum 1 servers) or while its local source of time is unavailable (such as GPS signal too low).
To evaluate this feature, the first thing I did was gather data on the relationship between the speed of the local clock in relation to the room temperature.
I logged the room temperature every 5 minutes from the DS18B20 and compared it to the local clock rate in this graph:
Looks like a pretty good match, which is what I would expect. The spike around 13:00 is from a spike in CPU usage. The CPU has a temperature sensor, but it isn't as precise. Comparing the CPU temperature to the clock rate results in this graph:
You can see the spike in CPU temperature at around 13:00 driving the clock frequency slower. The first graph doesn't show this temperature spike because the DS18B20 probe is farther away from the CPU than the clock oscillator. Moving the DS18B20 probe closer would result in better data. But where it is is good enough for now.
Next, let's look closer at the relationship between clock speed and temperature. I've taken all the local clock speed samples from chrony's tracking.log and associate them with the latest temperature sensor sample.
From this, you can see there's a pretty clear relationship between the two. I've fit an exponential equation by hand to the data
40.8 - 0.2*(T-25) + ((T-25)**2) * 0.015.
Testing the results
Plugging this into chrony.conf:
# ppm_from_temp = k0 + (T - T0) * k1 + (T - T0)^2 * k2 # tempcomp [path] [update] [T0] [k0] [k1] [k2] tempcomp /dev/shm/roomtemp 60 25 0.0 0.2 -0.015 log tracking measurements statistics tempcomp
Notice that the signs are opposite in chrony.conf vs my equation. Also, chrony is only interested in differences of these numbers over time and is limited to +/- 10ppm. This means I drop my k0 of 40.8ppm.
To test these numbers out, I disabled my refclocks in chrony and added a S1 NTP server over the LAN. I let chrony sync up over the LAN and then told it to go offline. I left the GPS running, but chrony wasn't hooked up to it. I saved the PPS offsets every 16 seconds and compared it to chrony's tempcomp log:
From this, you can see the clock was off between 495ppb and 438ppb. The largest error in clock rate was probably due to switching from local PPS to an on-net S1 server having a small offset difference. This offset difference drove the clock slower than it should have been.
But the real story here is the temperature compensation limited the error to around 60ppb. That's roughly 1ms per 5 hours. The temperature compensation moved the local clock 400ppb during this test. This is useful for when your NTP server temporarily has no GPS signal and has to rely on its last measurements.
Here's what it looks like with the 466ppb error removed:
So if the frequency was accurate at the time the GPS signal was lost, it would have only lost 400us in 5 hours (roughly 25ppb).
This isn't the whole story though, see part 2
Other sources of information: A similiar setup in 2001