Hardware
- A very old Raspberry Pi 0 W v1.1
- A GT-U7 GPS receiver https://www.amazon.com/dp/B0CWL6QZN8
Software
- An 8gb MicroSD running raspberry pi os 32-bit lite
- Install all updates
apt update && apt upgrade -y
- Install additional packages
apt install -y pps-tools gpsd gpsd-clients python3-gps ntpsec
- Update firmware with
rpi-update
, no need to restart yet - Configure overlays in
/boot/firmware/config.txt
:
# the next 4 lines are for GPS PPS signals and serial UART
dtoverlay=pps-gpio,gpiopin=18
dtoverlay=disable-bt
enable_uart=1
init_uart_baud=9600
and load the pps-gpio module at boot /etc/modules
:
pps-gpio
- Use
raspi-config
interface options, no login shell and yes hardware enabled - Power off
Hardware Again
GPS to PI
- VCC to pin 4 (5V)
- GND to pin 6 (GND)
- RX to pin 8 (GPIO 14 TXD)
- TX to pin 10 (GPIO 15 RXD)
- PPS to pin 12 (GPIO 18 PCM_CLK)
Thankfully this is just a straight 5-pin wiring. Could even solder them straight together as long as the antenna is far enough away.
Software Again
- Verify module is loaded:
lsmod |grep pps
- Monitor the pps device manually:
ppstest /dev/pps0
- Add devices and flags in
/etc/default/gpsd
DEVICES="/dev/ttyAMA0 /dev/pps0"
GPSD_OPTIONS="-n -s 9600"
- Set gpsd to start on boot
systemctl enable gpsd
- Start gpsd:
systemctl start gpsd
- Verify gps fix:
gpsmon
may take a while to get a fix,cgps
is another tool to consider - Verify that gpsd is sending clock data to ntp via shm:
ntpshmmon -o
and find the ID of the source that is high precision (lowest offset) - Edit
/etc/ntpsec/ntp.conf
to add PPS and GPS sources:
driftfile /var/lib/ntpsec/ntp.drift
leapfile /usr/share/zoneinfo/leap-seconds.list
refclock shm unit 2 prefer refid PPS #NTP2 from ntpshmmon PPS
refclock shm unit 0 refid GPS #NTP0 from ntpshmmon GPS
tos maxclock 11
tos minclock 4 minsane 3
pool 0.debian.pool.ntp.org iburst #keep these in case the gps fix is lost
pool 1.debian.pool.ntp.org iburst
pool 2.debian.pool.ntp.org iburst
pool 3.debian.pool.ntp.org iburst
restrict default kod nomodify nopeer noquery limited notrap #let us be a time server
restrict -6 default kod nomodify nopeer noquery limited notrap #let us be a time server
restrict 127.0.0.1
restrict -6 ::1
- Restart everything
Is it working?
ntpq -pn
output shows the current state of ntp.
Find the entry that starts with an asterisk. That's the one your server is going to use. + are the ones it likes but not likes the best.
remote refid st t when poll reach delay offset jitter
=======================================================================================================
*SHM(2) .PPS. 0 l 4 64 377 0.0000 0.0683 0.0447
xSHM(0) .GPS. 0 l 1 64 377 0.0000 -133.252 1.2762
0.debian.pool.ntp.org .POOL. 16 p - 64 0 0.0000 0.0000 0.0019
1.debian.pool.ntp.org .POOL. 16 p - 256 0 0.0000 0.0000 0.0019
2.debian.pool.ntp.org .POOL. 16 p - 256 0 0.0000 0.0000 0.0019
3.debian.pool.ntp.org .POOL. 16 p - 256 0 0.0000 0.0000 0.0019
-216.66.48.42 .PPS. 1 u 2 128 377 56.2374 -0.8680 20.8313
-64.79.100.196 199.102.46.70 2 u 51 64 377 14.8558 2.1709 8.0471
+199.195.248.88 17.253.2.253 2 u 44 64 377 31.5927 2.8269 5.0408
+162.159.200.1 10.142.8.5 3 u 57 64 377 11.6038 1.1217 11.7965
+23.186.168.2 243.50.127.182 2 u 28 64 337 23.7234 2.9758 6.8061
Check it with nagios plugins too, just for fun:
check_ntp_peer -H localhost -w 0.2 -c 0.5 -j 0.2 -k 0.3 -m @4 -n @2 -C 1
Bibliography
- https://austinsnerdythings.com/2021/04/19/microsecond-accurate-ntp-with-a-raspberry-pi-and-pps-gps/
- https://blog.networkprofile.org/gps-backed-local-ntp-server/
- https://austinsnerdythings.com/2021/09/29/millisecond-accurate-chrony-ntp-with-a-usb-gps-for-12-usd/
- https://www.researchgate.net/publication/332543537_BUILDING_A_RASPBERRY_PI_ZERO-W_GPS_NETWORK_TIME_SERVER_FOR_UNDER_50
Pages that link here: