It's an SBC-scale OXCO. I half wonder if adding a larger heatsink, or even putting thermal mass around the existing oscillator could also help, or if the heating is more localized in the PCB itself.
Always fun new things to learn when doing something "simple" like setting up an NTP server!
You might have even better precision if you stay away from CPU0 and also set idle=poll in your kernel command line. Lots of things (including other interrupts) often land on CPU0. It would not be my first choice for something where I wanted high timing precision.
Amazing project, great write-up. Would love to see a temperature graph as well! I'm wondering how good the PID controller here is working.
For future improvements, a cheap but effective win might be to put a temperature sensor on the oscillator (or two or three in various places). And use that to drive the PID loop.
Even if just experimental & not long term, it would be nice to have data on how strong the correlation is between the cpu & oscillator temperatures. To see their difference and how much that changes over time. Another graph! CPU vs txco (vs ambient?) temperatures over time.
Why not put a resistor (for heating) and a bit of foam insulation on the crystal?
This is way more direct than spacebar heating.
You could also add a transistor attached to the resistor and a GPIO and use the clock drift as a proxy for temperature. PID is probably enough but since you have a 24 hour cycle you could calculate a baseline heating schedule.
What's the point in reading posts like this when the solution "they" came up with is basically, "tell Claude to make a script which does whatever"? I read blog posts to read thoughts from people, not computers
Couldn't you model the effect of temperature on clock drift and try to factor that in dynamically (e.g. using a temperature sensor) instead of burning CPU unnecessarily?
That's a neat software solution. My first inclination would be to grab a soldering iron and replace the crystal with either a TCXO or a socket to provide an external clock disciplined to the 1PPS.
1. using a second hand single frequency Ublox LEA-M8T GNSS receiver is not a good idea in 2025 when a dual frequency GNSS receiver chip can be purchased online for as little as $20-30. buy one of those ublox ZED-F9P receivers with the 2018/2019 firmware, they get you the exact same timing performance as ZED-F9T with QEerr support. PPS jitter is going to drop from 20ns to less than 2ns after qErr compensation.
2. you can replace that highly unstable crystal oscillator with a $10 used OCXO + $20 PLL board and save that PID temperature controller to be used as the secondary oven for that OCXO. people have been doing that for Raspberry Pi for ages.
3. or you can configure your GNSS receiver to output a 10Hz signal from the PPSOUT pin so chrony can get 10 updates per second, GNSS receiver's internal TCXO is going to be more stable than raspberry Pi's crystal oscillator.
4. for more fun - just keep measuring the frequency drift vs. temperature change. a sample set of 24-48 hours of such measurements should be enough to figure out the tempco of that unstable crystal oscillator so you can get chrony to do the drift compensation. from memory, chrony supports such a temperature compensation lookup table to be specified.
Instead of dedicating an entire Raspberry Pi with fancy pinning and temperature management by burning CPU time, wouldn't a micro-controller and a precise external oscillator fare better for time-keeping stability? I would assume that a STM32 discovery kit running a NTP server on its Ethernet port could probably do better.
Austin from austinsnerdythings.com here! Posted this last night and went to sleep. Definitely didn't expect to wake up to it #1 on HN this morning!
Some notes that weren't included in this post:
I do have my LEA-M8T generating time pulses at 16 Hz, with a dpoll of -4 in the chrony config. The poll interval of 16 seconds means it gets 256 samples which also improved the stability.
I do also have that mentioned BH3SAP GPSDO sitting next to me on my desk. I had Claude update the firmware to allow "flywheel" behavior so it continues to generate pulses in the absence of GPS PPS. That's coming in another post. Also had Claude update the firmware to spit out TSIP (trimble proprietary protocol) info for lady heather.
Going to go through the comments and answer a couple other things I see.
Second: Is the Pi in an enclosure? You’ll get even more consistency if it is (vs a bare PCB). Even if it’s thin and metal it’ll insulate the system from things like your home heater or AC cycling.
> Instead of software thermal control, I could add an actively cooled heatsink with PWM fan control. This might achieve similar temperature stability while using less power overall.
38 comments
[ 3.7 ms ] story [ 49.9 ms ] threadAlways fun new things to learn when doing something "simple" like setting up an NTP server!
For future improvements, a cheap but effective win might be to put a temperature sensor on the oscillator (or two or three in various places). And use that to drive the PID loop.
Even if just experimental & not long term, it would be nice to have data on how strong the correlation is between the cpu & oscillator temperatures. To see their difference and how much that changes over time. Another graph! CPU vs txco (vs ambient?) temperatures over time.
Is the Pi going the Pentium 4 route?
https://www.usenix.org/conference/nsdi22/presentation/najafi
This is way more direct than spacebar heating.
You could also add a transistor attached to the resistor and a GPIO and use the clock drift as a proxy for temperature. PID is probably enough but since you have a 24 hour cycle you could calculate a baseline heating schedule.
1. using a second hand single frequency Ublox LEA-M8T GNSS receiver is not a good idea in 2025 when a dual frequency GNSS receiver chip can be purchased online for as little as $20-30. buy one of those ublox ZED-F9P receivers with the 2018/2019 firmware, they get you the exact same timing performance as ZED-F9T with QEerr support. PPS jitter is going to drop from 20ns to less than 2ns after qErr compensation.
2. you can replace that highly unstable crystal oscillator with a $10 used OCXO + $20 PLL board and save that PID temperature controller to be used as the secondary oven for that OCXO. people have been doing that for Raspberry Pi for ages.
3. or you can configure your GNSS receiver to output a 10Hz signal from the PPSOUT pin so chrony can get 10 updates per second, GNSS receiver's internal TCXO is going to be more stable than raspberry Pi's crystal oscillator.
4. for more fun - just keep measuring the frequency drift vs. temperature change. a sample set of 24-48 hours of such measurements should be enough to figure out the tempco of that unstable crystal oscillator so you can get chrony to do the drift compensation. from memory, chrony supports such a temperature compensation lookup table to be specified.
good luck and have fun
That should give you 4-5x less drift than his results (though you could pair the techniques for even better figures)
https://jila.colorado.edu/news-events/articles/spare-time
Works about as good as a heated rock in your sleeping bag.
Some notes that weren't included in this post:
I do have my LEA-M8T generating time pulses at 16 Hz, with a dpoll of -4 in the chrony config. The poll interval of 16 seconds means it gets 256 samples which also improved the stability.
I do also have that mentioned BH3SAP GPSDO sitting next to me on my desk. I had Claude update the firmware to allow "flywheel" behavior so it continues to generate pulses in the absence of GPS PPS. That's coming in another post. Also had Claude update the firmware to spit out TSIP (trimble proprietary protocol) info for lady heather.
Going to go through the comments and answer a couple other things I see.
Happy to answer any other questions!
Do 16Hz pulses make much difference? I found conflicting information and haven't yet tried it myself.
What do you use to get the data into influxdb? I'm using collectd but it doesn't gather a lot of useful info.
Second: Is the Pi in an enclosure? You’ll get even more consistency if it is (vs a bare PCB). Even if it’s thin and metal it’ll insulate the system from things like your home heater or AC cycling.
Love this (honestly). Interesting article!