• Stars
    star
    123
  • Rank 290,145 (Top 6 %)
  • Language
    Shell
  • License
    GNU General Publi...
  • Created over 8 years ago
  • Updated 8 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

setup a Raspberry Pi as a Stratum One time server (GPS with PPS)

RPi-GPS-PPS-StratumOne

setup a Raspberry Pi as an Stratum One NTP server.
it is a private project i have made for myself.
i did not keep an eye on network security.

the script will override some existing configurations
(a backup of the changed configuration files will be stored to backup.tar.xz)

USE IT AT YOUR OWN RISK

Please give me a 'Star', if you find that project useful.

overview schematic:

                     โ•”โ•โ•โ•โ•—       โ•”โ•โ•โ•โ•โ•โ•โ•—         โ•”โ•โ•โ•โ•โ•โ•โ•—  GPS-Antenna
                   โ”€โ”€โ•ข s โ•‘       โ•‘RPi asโ•ŸRXโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ขGPS-  โ•‘    โ•โ•ชโ•
                     โ•‘ w โ•‘       โ•‘NTP-  โ•ŸTXโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ขmoduleโ•‘     โ”‚
                     โ•‘ i โ•‘       โ•‘serverโ•‘         โ• โ•โ•โ•โ•—  โ•‘     โ”‚
       โ•”โ•โ•โ•โ•โ•โ•โ•—      โ•‘ t โ•Ÿโ”€โ”€โ”€eth0โ•ข      โ•ŸGPIO#4โ”€โ”€โ”€โ•ขPPSโ•‘  โ•Ÿโ”€โ”€โ”€โ”€โ”€โ”˜
       โ•‘ RPi  โ•Ÿโ”€โ”€โ”€โ”€โ”€โ”€โ•ข c โ•‘       โ•‘      โ•‘         โ•šโ•โ•โ•โ•ฉโ•โ•โ•
       โ•šโ•โ•โ•โ•โ•โ•โ•   โ”Œโ”€โ”€โ•ข h โ•Ÿโ”€โ”€โ”    โ•‘      โ•ŸGPIO#7โ•ดโ•ดโ•ดโ•ขPPSโ•‘  โ•Ÿโ•ดโ•ด
                  โ”‚  โ•šโ•โ•โ•โ•  โ”‚    โ•šโ•โ•โ•โ•โ•โ•โ•         โ•šโ•โ•โ•โ•ฉโ•โ•โ•
               โ•”โ•โ•โ•งโ•โ•โ•—   โ•”โ•โ•โ•งโ•โ•โ•—
               โ•‘ PC1 โ•‘   โ•‘ PC2 โ•‘
               โ•šโ•โ•โ•โ•โ•โ•   โ•šโ•โ•โ•โ•โ•โ•

overview: path of time source

(without external NTP servers)

โ•”โ•โ•โ•โ•โ•โ•โ•โ•—       โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
โ•‘ GPS   โ•ซโ”€โ”€RXโ”€โ”€โ”€โ•ซโ”€โ”€โ” KERNEL        โ•‘
โ•‘ โ•”โ•โ•โ•โ•โ•โ•ฃ       โ•‘  โ”‚               โ•‘                                     โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
โ•‘ โ•‘NMEAโ”€โ•ซโ”€โ”€TXโ”€โ”€โ”€โ•ซโ”€[+]โ”€/dev/ttyAMA0โ”€โ•ซโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€NMEAโ”€โ”€x                  โ•‘ CHRONY
โ•‘ โ• โ•โ•โ•โ•โ•โ•ฃ       โ•‘                  โ•‘        โ”‚                            โ•‘
โ•‘ โ•‘ PPSโ”€โ•ซโ”€GPIO4โ”€โ•ซโ”€โ”€โ”€โ”€โ”€/dev/pps0โ”€โ”€โ”€โ”€โ•ซโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€)โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ซโ”€โ”€[+]โ”€โ”€โ”€โ”€PPS0
โ•šโ•โ•ฉโ•โ•โ•โ•โ•โ•      โ•ดโ•ซโ•ดโ•ดโ”               โ•‘      โ”‚ โ”‚                            โ•‘   โ”‚
  โ• โ•โ•โ•โ•โ•โ•ฃ      โ•ดโ•ซโ•ด[+]โ•ด/dev/ttyAMA1โ•ดโ•ซโ•ดโ•ดโ•ดโ”  โ”‚ โ”‚                            โ•‘   โ”‚
โ•‘ โ•‘*PPSโ•ดโ•ซโ•ดGPIO7โ•ดโ•ซโ•ดโ•ดโ•ดโ•ดโ•ด/dev/pps1โ•ดโ•ดโ•ดโ•ดโ•ซโ•ดโ”ฌโ•ด)โ•ดโ•ด)โ•ด)โ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ซโ•ดโ•ดโ•ด)โ•ด[+]โ•ดPPS1*
โ•šโ•โ•ฉโ•โ•โ•โ•โ•โ•       โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• โ•ต โ•ต  โ”‚ โ”‚ โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—       โ•‘   โ”‚  โ•ต
                                     โ•ต โ•ต  โ”‚ โ”‚ โ•‘ GPSD             โ•‘       โ•‘   โ”‚  โ•ต
                                     โ•ต โ•ต  โ”‚ โ”‚ โ•‘                  โ•‘       โ•‘   โ”‚  โ•ต
                                     โ•ต โ•ต  โ”‚ โ””โ”€โ•ซโ”€GPS0โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ซโ”€SHM0โ”€โ”€โ•ซโ”€โ”€โ”€)โ”€โ”€)โ”€โ”€GPS0
                                     โ•ต โ•ต  โ”‚   โ•‘       โ”‚        โ”Œโ”€โ•ซโ”€SHM1โ”€โ”€โ•ซโ”€โ”€โ”€โ”ดโ”€โ”€)โ”€โ”€PSM0
                                     โ•ต โ•ต  โ””โ”€โ”€โ”€โ•ซโ”€PPS0โ”€[+]โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ•ซโ”€SOCK0โ”€โ•ซโ”€โ”€โ”€โ”€โ”€โ”€)โ”€โ”€PST0
                                     โ•ต โ•ต      โ•‘                  โ•‘       โ•‘      โ•ต
                                     โ•ต โ””โ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ซโ•ดGPS1โ•ดโ•ดโ•ดโ•ดโ•ดโ”ฌโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ซโ•ดSHM2โ•ดโ•ดโ•ซโ•ดโ•ดโ•ดโ•ดโ•ดโ•ด)โ•ดโ•ดGPS1*
                                     โ•ต        โ•‘          โ”‚     โ”Œโ•ดโ•ซโ•ดSHM3โ•ดโ•ดโ•ซโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ”ดโ•ดโ•ดPSM1*
                                     โ””โ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ซโ•ดPPS1โ•ดโ•ดโ•ดโ•ด[+]โ•ดโ•ดโ•ดโ•ดโ”ดโ•ดโ•ซโ•ดSOCK1โ•ดโ•ซโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดโ•ดPST1*
                                              โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•       โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
*) optional second PPS device

requirements

hardware:

software:

  • Raspberry Pi OS Bullseye (2021-10-30 or newer, (link))

installation:

assuming,

  • your Raspberry Pi is running Raspberry Pi OS Bullseye (2021-10-30 or newer),
  • and has a proper connection to the internet via LAN.
  • and your SD card is expanded,
  • and you connected the GPS module direct to the RPi's RX/TX pins of the GPIO and the GPS PPS pin to the RPi' GPIO 4
    (you can use other GPIO pins for PPS by changing dtoverlay=pps-gpio,gpiopin=... in /boot/config.txt)
  1. run bash install-gps-pps.sh to install necessary packages and setup Kernel PPS, GPSD, and NTP with PPS support.
  2. reboot your RPi with sudo reboot
  3. in case you have a RPi3, RPi3+, RPi4 or RPi0w with a built-in Bluetooth adapter, and the script didn't disabled Bluetooth successfully, please run sudo raspi-conf and disable the Bluetooth adapter there. otherwise the built-in Bluetooth adapter will block the serial port of the GPIO pins.

done.

NOTES:

gpsd v3.20 available on bullseye repository may have an issue with autobaud feature (finding the correct baud rate of the gps device automatically).
you may have to set the correct baud rate explicitly in the file /etc/default/gpsd
e.g. for baud rate 115200:
GPSD_OPTIONS="--listenany --nowait --badtime --passive --speed 115200"

note1:

the chrony configuration files are in the /etc/chrony/statum1 folder. only files with *.conf will be included to the configuration. all other files in that folder will be ignored. by renaming the files you easily can enable and disable different configuration files.

note2:

PPS is a high precise pulse, without a time information.
GPS (NMEA) has date/time information, but with mostly lower precision.

to combine GPS and PPS in chrony, there is a specific requirement, (link)
that GPS data and PPS signal must have a time offset of less than +/-200ms
otherwise the PPS signal is seen as false-ticker and will be rejected by chrony.

depending on your GPS device the offset used in my script can be way too off.

to adjust the offset of GPS0 edit the file /etc/chrony/stratum1/10-refclocks-pps0.conf

refclock SHM 0 refid GPS0 precision 1e-1 offset 0.0 ...

to find the actual offset, you can use gnuplot (already installed by the script) and run the plot script 99-calibrate-offset-gps0.gnuplot to visualize the actual histogram of the measured offsets.

# stop gpsd and chrony, delete all log files, restart chrony and gpsd
# wait few seconds to give time to create a log file,
# and start the histogram.

sudo systemctl stop --now gpsd.{service,socket} && sudo systemctl stop --now chrony && \
sudo rm -r /var/log/chrony/*.log && \
sudo systemctl start --now chrony && sudo systemctl start --now gpsd && \
sleep 10 && \
gnuplot ~/RPi-GPS-PPS-StratumOne/gnuplot/99-calibrate-offset-gps0.gnuplot

the histogram will updated every minute. keep it running for at least 30 minutes. the longer you keep it running the better offset value you can find. (but not longer than 24h. every 24h a new log will started from zero)

the x-value of the highest spike in the histogram is the offset value for the GPS0 you can once you got a good offset, you can use your RPi + GPS offline.

note3:

  • GPS0 (NMEA), has a mostly a low accuracy.

  • PPS0, has the highest accuracy.
    it is passed throught by the kernel to /dev/pps0.
    in chrony there is a specific timing offset requirement to PPS, that may cause the PPS0 to be seen as false-ticker by chrony and may be rejected.
    (see note2)

  • PSM0, is coming from the gpsd service via shared memory and is a combination of PPS0+NMEA, but handled by gpsd service.
    it has a similar accuracy than the PPS0 directly.

  • PST0, is used by gpsd socket to provide PPS0+NMEA information.
    it has the same accuracy as PSM0 because they have the same time source.

  • GPS1, PPS1, PSM1, PST1, same as above, but only for the second GPS/PPS device.

to properly restart chrony, use:

sudo systemctl stop --now gpsd.{service,socket} && \
sudo systemctl restart --now chrony && \
sudo systemctl start --now gpsd

this will disconnect all connected gpsd-clients.

enable second PPS:

to enable a second PPS source (/dev/pps1), please uncomment the prepared lines in the following files:

  • /boot/config.txt
    uncomment the line to:
    dtoverlay=pps-gpio,gpiopin=7,capture_clear # /dev/pps1

  • /etc/default/gpsd
    uncomment the line to:
    DEVICES="/dev/ttyAMA0 /dev/pps0 /dev/pps1"

  • rename file /etc/chrony/stratum1/11-refclocks-pps1.conf.disabled to
    /etc/chrony/stratum1/11-refclocks-pps1.conf

and reboot the system.

be warned: as long the kernel of the RPi uses "soft"-interrupts for the second PPS its accuracy is questionable.
for tests i feeded both gpio-pins with the same signal from the same pps-device (shorted both pins) and noticed a time difference of about 20ยตs in chrony between /dev/pps0 and /dev/pps1
see (two gpio pins has different delays?)