Pi OS 12 M8Q - BYO-NTP/recipes GitHub Wiki

date server os gnss daemon 🎯 🗣️
2025-05 Raspberry Pi 4
Raspberry Pi 5
Pi OS
12
Waveshare MAX-M8Q
GNSS HAT
chrony
NTPsec
ntp
2.8 µs
0.7 µs
discuss

1. Install OS

Instructions for Pi 4 or Pi 5

2. Configure the GNSS

Configure the jumpers on the HAT to A mode and plug a USB cable into the HAT and a Windows computer with u-blox u-center installed. Configure the GNSS per the recommendations on the gnss page.

3. Configure UART

Liberate the serial port from the console:

systemctl disable --now [email protected]
systemctl mask [email protected]
raspi-config nonint do_serial_cons 0
raspi-config nonint do_serial_hw 0

Create a symlink to /dev/gps0 and enable low_latency on the serial port:

apt install -y setserial
cat > /etc/udev/rules.d/10-gps.rules <<EOL
# symlink /dev/ttyAMA0 to /dev/gps0
KERNEL=="ttyAMA0", SYMLINK+="gps0", GROUP="dialout", MODE="0660"

# configure the serial port for low latency.
KERNEL=="ttyAMA0", RUN+="/bin/setserial /dev/ttyAMA0 low_latency"
EOL

4. Configure PPS

apt install -y pps-tools
grep -q pps-gpio /boot/firmware/config.txt || cat >> /boot/firmware/config.txt <<EOWV

# Waveshare MAX-M8Q GNSS hat
dtoverlay=pps-gpio,gpiopin=18

EOWV
reboot

Verify the PPS module loaded:

lsmod | grep pps
pps_gpio               12288  0

Verify PPS is working (Control-C to cancel)

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 1747026175.000003161, sequence: 4756 - clear  1747023968.100025259, sequence: 2549
source 0 - assert 1747026176.000000660, sequence: 4757 - clear  1747023968.100025259, sequence: 2549
^C

Hooray!

5. Install a NTP daemon

Each section heading is a link with many more details about installing, configuring, and verifying that particular NTP daemon.

export NTP_REFCLOCKS=$(cat <<EO_CHRONY
refclock SHM 0 refid NMEA offset 0.057 precision .02
refclock PPS /dev/pps0 refid PPS lock NMEA poll 2 precision 3e-6 trust
EO_CHRONY
)
curl -sS https://byo-ntp.github.io/tools/chrony/install.sh | sh
export NTP_REFCLOCKS=$(cat <<EO_NTPSEC
refclock nmea refid NMEA minpoll 3 maxpoll 4 time2 0.052 prefer mode 8 baud 115200
refclock pps  refid PPS  minpoll 1 maxpoll 2
EO_NTPSEC
)
curl -sS https://byo-ntp.github.io/tools/ntpsec/install.sh | sh

or with gpsd, via the SHM driver:

export NTP_REFCLOCKS=$(cat <<EO_NTPSEC_SHM
refclock shm unit 0 refid NMEA minpoll 3 maxpoll 4 time1 0.053
refclock shm unit 2 refid PPS  minpoll 1 maxpoll 2 prefer
EO_NTPSEC_SHM
)
curl -sS https://byo-ntp.github.io/tools/ntpsec/install.sh | sh
export NTP_REFCLOCKS=$(cat <<EO_NTP
server 127.127.20.0 minpoll 3 maxpoll 4 mode 88 prefer
fudge  127.127.20.0 refid NMEA time2 0.052 minjitter 0.03

server 127.127.22.0 minpoll 3 maxpoll 4
fudge  127.127.22.0 refid PPS
EO_NTP
)

Observe

  • watch the status in near real time:
    • printf '\e[8;9;80t'; ssh -t pi5 watch -n2 chronyc sources
    • printf '\e[8;9;80t'; ssh -t pi5 watch -n2 ntpq -c peer
  • Measure the offset
  • Gather statistics with telegraf + influxdb + grafana or similar.

References

Performance

Chrony

NTPsec

ntp

⚠️ **GitHub.com Fallback** ⚠️