-
1Step 1
The first step is to get your Raspberry Pi networked. For this, the strong recommendation is Ethernet connectivity rather than WiFi. WiFi by its very nature has wildly unpredictable latency that will have an impact on the obtainable accuracy and stability of your NTP service. For the Raspberry Pi, the only option is Ethernet over USB (even the USB ports built in to the larger Pis are in actuality USB devices). This somewhat degrades the available stability if you're going to use the USB bus for other purposes, but it won't be noticeable if you're building a dedicated NTP server with little other traffic and no other USB peripherals.
-
2Step 2
On the hardware side, you're going to need (in addition to the Pi) a GPS receiver breakout board of some sort. Your breakout board should have a bidirectional serial interface and active-high PPS, with the leading edge synchronized. It should also be powered by either 5v or 3.3v (5v is preferable). The serial I/O and PPS should be 3.3v TTL level serial. If it's 5 volt serial, then you'll need to use diode+pull-up level shifting.
Connect the ground of the GPS module to pin 6 of the Pi GPIO header. Connect either a +5 power input to pin 2 or a +3.3 power input to pin 1. Connect the serial input of the GPS module to pin 8, the serial output to pin 10 and the PPS to pin 12.
-
3Step 3
Run raspi-config and go into the advanced menu and disable the login on serial. The serial port is being given over to the GPS module instead.
-
4Step 4
Edit /boot/cmdline.txt Remove the part that says
console=ttyAMA0,115200
Edit /boot/config.txt and add this line:
dtoverlay=pps-gpio,gpiopin=18
This will configure the Pi for PPS input on GPIO 18, which is pin 12 - where we connected the PPS output of the receiver.
Edit /etc/modules and add this line:
pps-gpio
Reboot the pi for this to take effect.
After rebooting, you should see /dev/pps0.
-
5Step 5
Run this (as root):
apt-get install pps-tools gpsd gpsd-clients
As root, run
ppstest /dev/pps0
You should see
trying PPS source "/dev/pps0" found PPS source "/dev/pps0" ok, found 1 source(s), now start fetching data... source 0 - assert 1474694802.999938248, sequence: 466791 - clear 0.000000000, sequence: 0 source 0 - assert 1474694803.999931101, sequence: 466792 - clear 0.000000000, sequence: 0 source 0 - assert 1474694804.999950952, sequence: 466793 - clear 0.000000000, sequence: 0
The actual output may vary, but you should see one of those "source" lines every second.
As root run
dpkg-reconfigure gpsd
and set the GPSD device to /dev/ttyAMA0.
As not root run
gpsmon
You should see an ASCII-art pseudo-graphical display showing the GPS information being sent by the receiver.
-
6Step 6
Edit /etc/init.d/ntp. Find the line that looks like this:
# Required-Start: $network $remote_fs $syslog
Add " gpsd" to the end of that line. This will cause ntp to delay its startup until after gpsd, which allows gpsd to create its socket before ntpd goes and looks for it.
-
7Step 7
At this point, we must install a special customized version of ntpd, as, unfortunately, the standard packaged version lacks the NTP driver support for getting time from GPSD and PPS.
We're going to simply overwrite the NTP daemon installed on the system. To prevent aptitude from upgrading (and therefore wiping out) our customized version, do this (as root):
apt-mark hold ntpd
Next, download the latest NTP daemon from ntp.org.
Untar the distribution somewhere convenient, cd into it and run
apt-get install libcap-dev configure --enable-linuxcaps make
This will take a long time on a Pi Zero. If you have another Pi handy (and why wouldn't you?), then you should do this on a heftier Pi and then copy the result to the zero.
copy the resulting ntpd to /usr/sbin, overwriting the one that's there.
-
8Step 8
Edit /etc/ntp.conf, adding this to the end:
server 127.127.22.0 #minpoll 4 maxpoll 4 fudge 127.127.22.0 refid PPS fudge 127.127.22.0 flag3 1 # enable kernel PLL/FLL clock discipline server 127.127.28.0 prefer #minpoll 4 maxpoll 4 fudge 127.127.28.0 time1 0.235 refid SHM stratum 10
The 127.127 entries are 'virtual' reference clocks. The 22.0 one is the PPS refclock. It will use the /dev/pps0 device to get kernel timestamps on the PPS leading edges and use them to steer the kernel clock to synchronicity with GPS seconds.
The 28.0 clock is the shared memory interface to GPSD. The time1 value is an estimate of the latency to the timecode messages. The correct value will depend on the GPS receiver. 0.235 is a good value for the SkyTraq Venus838LPx-T receiver. It's not tremendously important to tune this value. The purpose for this refclock is to get the seconds close enough to allow the PPS clock to take over. You can also set up other hosts as servers instead of using the SHM refclock. Anything that will cause ntpd to get a good sync will allow the PPS refclock to begin working.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.
well, yes and no. jitter is definitely an issue but the big problem appears to be in the offset between the PPS signal and NMEA stream. to test this i configured ntp to use a stratum 2 WAN server and ran it for about twelve hours. the PPS server was stable as a pps.peer and the WAN server as a sys.peer. the GPSD server was "falsetick" within thirty minutes. i took the average offset between the PPS and GPSD server over that twelve hours, set "time1" to that value (600ms), set GPSD to "prefer" and rebooted. the system has been running for about four hours without a problem. i need to let it run for a day or two to see if it is stable.
now i need to go off and figure out what a "trust yourself" pseudo peer is...
Are you sure? yes | no
Yup. As you noted, you can tune the offset of the NMEA sentences with the 'fudge' line. time1 is the offset. I find that the jitter is still sometimes bad enough that ntpd distrusts it, but that will vary depending on your receiver.
The "trust yourself" peer is 127.127.1.0. Use the fudge line to set its stratum to 10.
Are you sure? yes | no
thanks for the info. i am pretty sure i wouldn't try this with a ten buck gps dongle. i wonder if asking the gps device to only spit out the NMEA sentence with time information would improve the situation? more research!
Are you sure? yes | no
I've found that the price point of the receiver isn't necessarily predictive of the quality of the NMEA sentence timing. I think it's just something the makers don't care about. For other than timing modules, their excuse is that navigational sentences are what matters anyway. And for timing, their excuse is that you're supposed to use PPS if you care that much.
Are you sure? yes | no
I've set one up using a combination of these instructions and a lot of man page reading (to understand why you do what you do). NTPD goes through a cycle of accepting 127.127.22.0 as a PPS peer and 127.127.28.0 as the primary reference, works for ten minutes or so and then both are marked with "x" (checked using ntpq -p) which means "Out of tolerance, do not use (discarded by intersection algorithm)".
Here's the ntpq output "before" and "after"
==============================================================================
oPPS(0) .PPS. 0 l 1 64 1 0.000 166.863 0.002
*SHM(0) .GPSD. 3 l 4 16 17 0.000 73.027 23.226
==============================================================================
xPPS(0) .PPS. 0 l 10 64 377 0.000 -0.261 7.270
xSHM(0) .GPSD. 3 l 9 16 377 0.000 -137.35 48.432
Any ideas why? Thanks!
Are you sure? yes | no
The NMEA sentence timing isn’t stable enough for ntpd. And if you have no other reference at all, it will not trust a PPS source. For best results add an Internet host as a secondary reference for situations like this, or - worst case - add a “trust yourself” pseudo peer to disallow the stratum rising beyond, say, 10. With that, your PPS will remain trusted, which is enough to score.
Are you sure? yes | no