home | projects / technotes | links


NTP logo

NTP + Stratum 1

Disclaimer: I know everyone and their sibling has a page on building a cheap stratum 1 solution. Anyway, here's another one :)

So I went down the NTP rabbit hole in about 2012. All of my solutions so far have been using Linux and ntpd.

For those who might not know - stratum in the world of timing systems refers to how far removed from a reference clock your unit/device is. As the stratum level increases, the accuracy decreases. A reference clock being a timing source that is extremely accurate, precise, and stable. Generally this is an atomic clock using cesium/rubidium/hydrogen. These clocks are then distributed out to users via some system (radio frequency, telephone signal/modem, etc.) These clocks would be considered stratum 0. Stratum 1 is a device providing it's time "downstream" with itself getting it from a stratum 0.

Some examples of distribution systems include:

If there's one you think I'm missing mentioning, please drop me an email at the link at the bottom !

What I Use

Well that background section above is much longer than I thought it would be :) So let's start off with a picture of my current setup:

Jetway mini PC and Raspberry Pi

This is two separate systems.
The one on the left is two components - a Syncbox and a Jetway x86 mini PC.
The one on the right is a Raspberry PI with the UPUtronics GPS hat and a custom case to fit it.

I went with the Jetway because it has a real UART serial port. This is important because most USB serial ports don't have all of the RS232 pins/circuitry present (not to mention the added latency of USB connections). In this case - I needed to make sure I had DCD (more on this below). Also - the SYNCBOX is GPS only.

The Pi is pretty standard. The hat connects to the GPIO pins of course, and exposes a serial port. The hat is multi-GNSS (BeiDou,Galileo,GLONASS,GPS/QZSS). You can have 3 active at once.

In both cases I am using the Type 20 refclock driver in NTP. This is the GPS NMEA driver that also supports embedded PPS (more on this below). On this page you cam also see lots of other old/exotic refclock drivers (including ones for all the radio signals and modems above).

So the GPS NMEA protocol includes a time "sentence" (the line based unit of NMEA information). Generally with any GNSS solution, you want to disable any/all extraneous sentences if possible to minimize the amount of data being sent in an interval (this is typically done with whatever configuration software is specific to your unit). The only sentence you need is GPRMC and it looks like this:

$GPRMC,014813.000,A,____._____,_,_____._____,_,000.1,151.2,070123,05.2,W*__

You can see the time is 014813 (UTC of course), and the date is 070123 ("non-American" format :) ). The underscore lines are ntpd sanitizing my latitude and longitude (done by setting fudge flag4 to "1").

So above I mentioned PPS. Let me explain what this is and why it matters. PPS is Pulse Per Second. Think of it as a perfect digital heartbeat happening exactly every one second. The reason this is important is because with just the time code from GPS NMEA - you know what second you are within, but you don't know when that second started. So without PPS, you will see jitter and less accurate offset readings. With PPS, ntp also knows exactly when the current second started. In linux this is realized with the ldattach (Line Discipline ATTACH) program. As I mentioned before - the DCD (data carrier detect) pin is where PPS is sent. It looks like this running in the background:

ldattach pps /dev/ttyS0

And once ldattach is running correctly, you should see something like this in dmesg:

[    5.993185] pps pps2: new PPS source serial0
[    5.993208] pps pps2: source "/dev/ttyS0" added

The ntp Type20 driver combines the GPS NMEA information and PPS into one source. There are other drivers you can use to access these separately (you would have "two" refclocks in this case). I personally like having them combined. Once all this is working, this is what I see on my devices:

pi@pi-gps:~ $ ntpq -pn
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
o127.127.20.0    .GNSS.           0 l   11   16  377    0.000   +0.001   0.002

The "o" at the beginning of the line indicates we have a good PPS signal. The offset and jitter are almost always single-digit microsecond values.

I find that the Pi is actually a bit more precise than the Jetway setup. Having said that - they both seem to always be within single digit microsecond values. Here's a graph showing something else interesting:

Raspberry PI NTP MRTG graph

Note: the 20 µs line in the middle is actually "0". I artificially offset the measured value in MRTG by +20 µs. This lets you see positive and negative dips instead of having everything on the "floor" and unreadable.

But see those spikes +/- ? That's when I turn the fan on in my home office :) NTP devices are very sensitive to temperature fluctuations. The values tightly hugging the middle line are the "normal" readings. In this case - you can see that I went to bed early that night (~ 20:00 previous day) and turned my fan on at about 11:00.

Updated: 20230106


email contact