How to Setup a GPS PPS NTP Time server on Raspberry Pi

You can quickly determine fix status by looking at the Red LED on the GPS breakout:

  • Blinking on and off once every other second - NO FIX
  • Blinking once per 10 seconds or so - HAS FIX
You may need to put the Pi near a window or attach an external antenna. Once it has a fix, continue!

Serial test

Lets stat by just reading the raw data from the GPS on the command line. Run: # stty -F /dev/serial0 raw 9600 cs8 clocal -cstopb Now run # cat /dev/serial0 To read raw data directly from the GPS.

Configure the PPS (Pulse-Per-Second)

sudo apt-get install pps-tools Edit and add these lines to the end of the file: sudo nano /boot/config.txt Physical pin 7 = RPi Logical pin GPIO4 # PPS GPIO pin dtoverlay=pps-gpio,gpiopin=4
Edit and add these lines to the end of the file: sudo nano /etc/modules Add the following line: pps-gpio

After the reboot, check that the pps module is loaded, which is the case if lsmod lists some drivers such as this: # lsmod | grep pps pps_ldisc 2413 2 pps_gpio 3089 1 pps_core 8606 4 pps_gpio,pps_ldisc Try to get a tick every second (cancel it with Ctrl+c as always) sudo ppstest /dev/pps0

Remove DHCP hook

To prevent the Pi from getting NTP configuration from any DHCP servers, remove ntp-servers from the end of the request block: sudo nano /etc/dhcp/dhclient.conf ... request subnet-mask, broadcast-address, time-offset, routers, ... #rfc3442-classless-static-routes, ntp-servers; rfc3442-classless-static-routes; ... Reboot

Installing a GPS Daemon (gpsd)

To install gpsd, simply run the following commands from the console: sudo apt-get install gpsd gpsd-clients -y Edit: sudo nano /etc/default/gpsd Adjust the following values to: START_DAEMON="true" USBAUTO="false" DEVICES="/dev/serial0 /dev/pps0" GPSD_OPTIONS="-n"
The following symlink is needed to have gpsd started after boot correctly: sudo ln -s /lib/systemd/system/gpsd.service /etc/systemd/system/ Reboot

After the reboot, check that the daemon is running: sudo service gpsd status gpsd.service - GPS (Global Positioning System) Daemon Loaded: loaded (/lib/systemd/system/gpsd.service; enabled; vendor preset: enabled) Active: active (running) since Fri 2020-07-10 19:12:54 CEST; 4min 8s ago Process: 349 ExecStart=/usr/sbin/gpsd $GPSD_OPTIONS $DEVICES (code=exited, status=0/SUCCESS) Main PID: 364 (gpsd) Tasks: 3 (limit: 2319) Memory: 1.9M CGroup: /system.slice/gpsd.service +-364 /usr/sbin/gpsd -n /dev/serial0 /dev/pps0 Jul 10 19:12:53 Pi-NTPGPS systemd[1]: Starting GPS (Global Positioning System) Daemon... Jul 10 19:12:54 Pi-NTPGPS systemd[1]: Started GPS (Global Positioning System) Daemon.
With tools such as cgps -s you get user friendly information from your GPS module such as: $ cgps -s

Install chrony

In latest versions of Raspbian, ntp is replaced by a client-only systemd NTP implementation. Disable it and install chrony instead: sudo systemctl stop prefer-timesyncd.service sudo systemctl disable prefer-timesyncd.service sudo apt-get install chrony -y
And configure for use with GPS device: sudo nano /etc/chrony/chrony.conf refclock SHM 0 offset 0 delay 0 refid GPS noselect refclock PPS /dev/pps0 lock GPS refid GPPS pool offline iburst From the chrony.conf docs: refclock specifies a hardware reference clock SHM is the shared memory driver, which is utilized by gpsd PPS is for pulse-per-second signals, read from /dev/pps0 lock is used to link PPS samples to another refclock noselect is an optional flag used to signal the GPS shouldn't be used directly refid is the tracking label, "GPPS" indicates a PPS-enabled GPS source offset and delay are values which will be tuned after running overnight At this point, test the time synchronization using: # chronyc tracking # chronyc sources -v # chronyc sourcestats -v If necessary, apply a step-change to system clock:
(The -a argument is required in older versions of chronyc to prevent an error.) sudo chronyc -a makestep
Fine Tuning
After warming up, the GPS refclock showed an Offset value consistently between 400-500ms, generally on the higher end. This value can be incorporated directly to improve the source: sudo nano /etc/chrony/chrony.conf Edit delay: refclock SHM 0 offset 0 delay 0.5 refid GPS noselect refclock PPS /dev/pps0 lock GPS refid GPPS Although recommended, the makestep directive is not included in the default chrony configuration file. Manually add it: # Step the clock, if necessary, for a short window after starting # makestep 1 5 Reboot

Serving time to clients
Finally, to enable this device as an NTP server, add allow directives to /etc/chrony/chrony.conf as appropriate. See the user documentation for more details. Example, to permit all clients from local subnet 192.168.1.x: sudo nano /etc/chrony/chrony.conf ... # This directive designates subnets (or nodes) from which NTP clients are allowed # to access to chronyd. # allow everyone on home network allow #allow #allow 10/8 ...

Enable standalone mode
In case the server loses GPS and Internet access, but network clients are still attempting to sync, use the local hardware clock as a last resort source: sudo nano /etc/chrony/chrony.conf # Enable standalone mode local stratum 10 Reboot