https://blog.networkprofile.org/gps-backed-local-ntp-server/
- Raspberry Pi 4
- GT-U7 GPS Module
- U.Fl to SMA Adapter
- SMA GPS Antenna
sudo bash -c "echo '# the next 3 lines are for GPS PPS signals' >> /boot/firmware/config.txt"
sudo bash -c "echo 'dtoverlay=pps-gpio,gpiopin=18' >> /boot/firmware/config.txt"
sudo bash -c "echo 'enable_uart=1' >> /boot/firmware/config.txt"
sudo bash -c "echo 'init_uart_baud=57600' >> /boot/firmware/config.txt"
sudo bash -c "echo 'pps-gpio' >> /etc/modules"
sudo apt update
sudo apt upgrade -y
sudo apt install gpsd gpsd-clients pps-tools chrony jq tcpdump -y
sudo shutdown -h now
Raspberry Pi | GPS |
---|---|
Pin04 - 5V | VCC |
Pin06 - GND | GND |
Pin08 - TXD | RXD |
Pin10 - RXD | TXD |
Pin12 - GPIO18 | PPS |
Turn the Raspberry Pi back on. Wait until you see the red light on the GPS module blink once per second.
sudo ppstest /dev/pps0
You should see something like this:
trying PPS source "/dev/pps0"
found PPS source "/dev/pps0"
ok, found 1 source(s), now start fetching data...
source 0 - assert 1689037624.000000607, sequence: 19592 - clear 0.000000000, sequence: 0
source 0 - assert 1689037625.000001413, sequence: 19593 - clear 0.000000000, sequence: 0
source 0 - assert 1689037625.999999218, sequence: 19594 - clear 0.000000000, sequence: 0
sudo tee /etc/default/gpsd <<EOF > /dev/null
START_DAEMON="true"
DEVICES="/dev/ttyS0 /dev/pps0"
GPSD_OPTIONS="-n"
USBAUTO="false"
EOF
sudo systemctl enable gpsd
sudo systemctl start gpsd
gpsmon
You need at least 4 satellites to get good time. This command will print the number of satellites we are locked on to.
Move your antenna around to get a good lock. Press CTRL-C
to quit.
gpspipe -w | jq ".uSat| select( . != null )"
sudo nano /etc/chrony/chrony.conf
Find the line that has pool.ntp.org
and add this on the next line:
refclock SHM 0 refid NMEA offset 0.000 precision 1e-3 poll 3 noselect
refclock PPS /dev/pps0 refid PPS lock NMEA poll 3
Find and uncomment the line that says log tracking measurements statistics
.
sudo systemctl restart chrony
After a few minutes, check the logs for our calculated offset:
sudo cat /var/log/chrony/statistics.log \
| sudo head -2; sudo cat /var/log/chrony/statistics.log \
| sudo grep NMEA
I'd recommend letting this run for a while, minimum of 10 minutes, but really as long as a day to get a really good offset.
Once you've let it run for a while, you can average the offsets and update the chrony config.
sudo cat /var/log/chrony/statistics.log \
| grep NMEA \
| awk -F" " '{ print $5 }' \
| awk '{ sum += $1 } END { if (NR > 0) print sum / NR; }'
Take the number this calculates and copy it.
sudo nano /etc/chrony/chrony.conf
Replace 0.000
on the line with the number you copied from above:
refclock SHM 0 refid NMEA offset 0.000 precision 1e-3 poll 3 noselect
Save and exit.
sudo systemctl restart chrony
watch -n 1 chronyc sources -v
After a few seconds you should see a *
next to PPS. This shows you are using the PPS signal from GPS for timing.
sudo nano /etc/chrony/chrony.conf
Add prefer
to the end of the refclock PPS
line.
refclock PPS /dev/pps0 refid PPS lock NMEA poll 3 prefer
and at the bottom of the file, add the following lines:
allow 0.0.0.0/0
manual
local stratum 1
Then reboot to ensure everything works correctly.
sudo reboot now