Prerequisites

  • Raspberry Pi 3B with Raspberry Pi OS installed (Lite or Desktop version).
  • GPS module (e.g., u-blox module or similar).
  • 5 GPIO Jumper Cables
  • Access to the Pi via SSH or a connected monitor, keyboard, and mouse.

Step 1: Hardware Setup

Connect the GPS module to the Raspberry Pi:

    GPS to Raspberry Pi pin connections:
        VCC (or VIN) → Pin 2 or 4 (5V) on the Raspberry Pi.
        GND → Pin 6 (Ground) on the Raspberry Pi.
        TX → Pin 10 (GPIO 15, UART RX) on the Raspberry Pi.
        RX → Pin 8 (GPIO 14, UART TX) on the Raspberry Pi.
        PPS → Pin 12 (GPIO 18) on the Raspberry Pi.

Step 2: Update the Raspberry Pi OS

Before proceeding, make sure your Raspberry Pi is fully up to date.

sudo apt update
sudo apt upgrade -y

Step 3: Disable Serial Console and Enable UART

The serial interface may be used by the system for console access, so we need to disable it.

Open the Raspberry Pi configuration tool:

sudo raspi-config

Navigate to Interface Options → Serial.

When asked if you want a login shell over the serial interface, select No.

When asked if you want to enable the serial hardware, select Yes.

Exit and reboot the Raspberry Pi:

sudo reboot

Step 4: Configure GPIO pin for PSS

Open /boot/firmware/config.txt

sudo nano /boot/firmware/config.txt

Add the following to the bottom under the [all] section.

[all]
enable_uart=1
dtoverlay=pps-gpio,gpiopin=18
init_uart_baud=9600

Now add the PPS module

sudo bash -c "echo 'pps-gpio' >> /etc/modules"

Now reboot the device

sudo reboot

Step 5: Install and Configure GPSD

GPSD is a service that will handle communication between the GPS module and the system.

Install GPSD and its tools:

sudo apt install gpsd gpsd-clients python3-gps

Stop the GPSD service for manual configuration:

sudo systemctl stop gpsd
sudo systemctl disable gpsd

Edit the GPSD configuration file:

sudo nano /etc/default/gpsd

Set the GPSD config as below (you may need to change /dev/ttyS0 depending on your Pi)

START_DAEMON="true"
USBAUTO="true"
DEVICES="/dev/ttyS0 /dev/pps0"
GPSD_OPTIONS="-n"

Start GPSD manually:

sudo systemctl start gpsd

Verify GPS data with the following command:

cgps

You can also use gpsmon or gpsmon -n

If everything is working, you should see satellite data and timing information from the GPS module.

Step 6: Enable PPS (Pulse Per Second) Support

PPS provides highly accurate timing data that will be used alongside the NMEA data from the GPS.

Install the necessary PPS tools:

sudo apt install pps-tools

Test the PPS signal: Check if the Raspberry Pi is receiving the PPS signal:

sudo ppstest /dev/pps0

You should see output indicating a pulse every second. If you don’t, check your wiring and ensure the correct GPIO pin is being used.

Step 7: Install and Configure Chrony

Chrony is a lightweight and efficient NTP implementation, perfect for use on systems like the Raspberry Pi.

Install Chrony:

sudo apt install chrony

Configure Chrony to use both the GPS and PPS signals as time sources: Edit the Chrony configuration file:

sudo nano /etc/chrony/chrony.conf

Add the following lines to configure the GPS and PPS sources:

# Use the GPS as a time source
refclock SHM 0 offset 0.5 delay 0.2 refid GPS precision 1e-1 noselect

# Use the PPS signal as a time source
refclock PPS /dev/pps0 refid PPS lock GPS precision 1e-9
  • refclock SHM 0 refers to GPSD’s shared memory segment where GPS data is available.
  • refclock PPS uses the Pulse Per Second signal from /dev/pps0 for precise timing.
  • The lock GPS option ensures that PPS is used in combination with the GPS time data.

Restart the Chrony service:

sudo systemctl restart chrony

Step 8: Verify the Chrony Setup

Check that Chrony is properly synchronizing with the GPS and PPS signals.

View the status of Chrony:

chronyc sources -v

You should see output indicating that both the GPS (SHM0) and PPS (PPS0) sources are being used for time synchronization.

Example output:

210 Number of sources = 2
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
#* PPS0                        0   4   377    1    -123ns[-131ns] +/-  127ns
#? SHM0                        0   4   377    2    -0.01s[-0.01s] +/- 16.0ms

The PPS0 line should have a * next to it, indicating that Chrony is using the PPS signal for accurate time synchronization.

Monitor Chrony synchronization:

chronyc tracking

This will show information about the current system clock and the sources being used for synchronization.

Step 9: Allow clients to Use the Raspberry Pi as an NTP Server (Optional)

For clients to access the Raspberry Pi as an NTP server you need to add the allow line in your chrony config

sudo nano /etc/chrony/chrony.conf

To allow all clients from ANY source add the below line

allow 0.0.0.0/0

To allow clients from a specific subnet use the CIDR notation

allow 10.0.0.0/24

Troubleshooting

No GPS data in cgps:

  • Check the wiring and ensure the serial interface /dev/ttyS0 is correctly configured.
  • Ensure the GPS module has a clear view of the sky.

PPS not working:

  • Verify that GPIO 18 is correctly configured for PPS in /boot/firmware/config.txt (Older Raspberry Pi OS version may use /boot/config.txt)
  • Use ppstest to confirm PPS signals.

Chrony not using GPS or PPS:

  • Check that Chrony is configured correctly and restart the service.
  • Use chronyc sources to see which time sources Chrony is using.