Raspberry Pi – GPS

I recently wanted to set up a Stratum 1 time source using a Raspberry Pi (running Arch Linux).  I bought the excellent Adafruit Ultimate GPS Hat and dutifully soldered on the connector.  So far so good.  Unfortunately, from that point on, I found lots of conflicting information.  Not, I hasten to add, because the sources were wrong, but rather that evolving kernels and NTP versions rapidly obsolete instructions.  Here is my version of requirements, as of October 2016.

Remove console from ttyAMA0.  The GPS wants this serial port for talking to the Pi.
/boot/cmdline.txt:

root=/dev/mmcblk0p2 rw rootwait console=tty1 selinux=0 plymouth.enable=0 smsc95xx.turbo_mode=N dwc_otg.lpm_enable=0 elevator=noop

Add Pulse Per Second modules to the kernel.
/boot/config.txt – Add new line:

dtoverlay=pps-gpio,gpiopin=4

Note: gpiopin=4 represents the pin number on the module that PPS is on.
Load the PPS module on boot.
/etc/modules

pps-gpio

At this point, it’s useful to be able to test PPS is working. There’s an excellent tool for this here.  Just run make and then run the tool from whatever directory you extracted it into. If all is well, you’ll see something like this:

root@ticktock:pps-tools# ./ppstest /dev/pps0
trying PPS source "/dev/pps0"
found PPS source "/dev/pps0"
ok, found 1 source(s), now start fetching data...
source 0 - assert 1477494632.000003379, sequence: 1210414 - clear  0.000000000, sequence: 0
source 0 - assert 1477494633.000001527, sequence: 1210415 - clear  0.000000000, sequence: 0

Now install the gpsd package:

pacman -S gpsd

And configure it in /etc/gpsd:

START_DAEMON="true"
GPSD_OPTIONS="-n -D 2"
DEVICES="/dev/ttyAMA0"
#USBAUTO="true"

At this point, everything is there and working. Unfortunately, the packaged version of NTP isn’t configured to use a PPS time source so it’s necessary to download and compile a local version:

./configure --enable-all-clocks --enable-parse-clocks --enable-SHM \
            --disable-debugging --without-ntpsnmpd --disable-local-libopts \
            --enable-ATOM

I’ve no idea if all these switches need to be enabled and I have no plans to perform a process of elimination. As of ntp-4.2.8, these work for me.

Finally, configure NTP to use the GPS and PPS time sources:

server 127.127.28.0 prefer
fudge 127.127.28.0 time1 +0.520 flag1 1 refid GPS stratum 1
server 127.127.22.0 minpoll 4 maxpoll 4
fudge 127.127.22.0 time1 +0.0 flag2 0 refid PPS

# Associate to Arch's NTP pool
server 0.arch.pool.ntp.org
server 1.arch.pool.ntp.org
server 2.arch.pool.ntp.org
server 3.arch.pool.ntp.org

restrict default kod limited nomodify nopeer noquery notrap
restrict 127.0.0.1
restrict ::1

# Location of drift file
driftfile /var/lib/ntp/ntp.drift

This retains the default NTP pool which provides some sanity that the local clock is accurate. A query of the NTP should produce something like this:

root@ticktock:~# ntpq -pn
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*127.127.28.0    .GPS.            1 l   59   64  377    0.000   53.155  21.298
o127.127.22.0    .PPS.            0 l    9   16  377    0.000    0.002   0.004
+46.36.198.130   185.53.93.157    3 u   33   64  377   30.713   -3.681   0.170
+85.119.80.233   20.139.208.232   3 u   42   64  377   20.914   -3.539   0.348
+2001:418:3ff::5 249.224.99.213   2 u   52   64  377   20.722   -3.742   0.090
+176.58.109.199  241.76.5.73      2 u   63   64  377   21.381   -3.664   0.346

The GPS clock is pretty inaccurate, thanks to serial connectivity, but it doesn’t matter as the PPS provides very accurate pulses per second to provide the fine granularity. It’s only important that GPS is accurate to within 500ms to ensure NTP can ascertain which second the pulses relate to. Enjoy!

Leave a comment