Stratum 0 GPS+PPS Time Source for $50

New amateur time nut here,

I thought it would be fun to add a GPS+PPS source to my pfSense firewall to serve time to clients. I tested three different Garmin GPS receivers connected via DE9 or RJ45 RS232 communication and the NTP package in http://pfsense.org

  • GPS 16X LVS
  • GPS 18X LVC
  • GPS 19X HVS

I am sure others with more experience will find faults with my NTP solution, but it seems to achieve less than 10-15 usec offset/jitter. Might not be good enough for a financial institution or high speed data acquisition, but good enough for homelab use.

Comments welcome.

2 Likes

Welcome!
Personally i don’t have any experience with Garmin gps receivers. Sorry :blush:

uBlox based GPS modules from 7th to 9th gen, can be purchased for half that price, or even less, if a naked chip on a tiny board and possibly some soldering isn’t a problem. Pratically all support PPS, even if there is no dedicated PPS pad/pin on the board.

Thanks. I preferred the COTS outdoor rated GPS receivers vs a Rube Goldberg option.

1 Like

Hmm, I guess it lies in the eyes of the beholder as to whether to consider any option a Rube Goldberg one. E.g., due to the much better performance of the u-blox units, there may be no need for an outdoor rating. Depending on circumstances, it may be possible to operate such a unit indoors and get reception good enough for timing (less so for positioning), as discussed in another recent thread.

Or, if that doesn’t work in particular circumstances, the receiver may reside indoors, and it’s only a COTS puck antenna with attached coaxial cable run that gets placed outdoors.

Either way, slightly different handiwork needed than what you did for your solution, but to me, it seems pretty much on par with what you did for your solution as far as Rube Goldberg worthiness is concerned. But the performance would arguably be better with a recent u-blox unit than with the slightly older Garmin units.

A bit pricier, but if reducing handiwork is a must, some vendors such as NaviSys and Navilock also offer outdoor rated units with PPS and serial (non-USB) interface based on u-blox chips, e.g., the NaviSys GR-801R.

3 Likes

I use a couple of these receivers, but they are tricky to setup.
And they need DB9 as well as USB (for 5V power).

There are various good sites on how to work with these.

It all depends on your situation, because if the roof of your building isn’t steel-enforced-concrete often indoor simple U-blox will work fine.

You can install a app on your mobile-phone and see how well it received and how many sat’s. That will give an idea what you need for good timekeeping.

Mine are under a wooden roof and do not need to be outdoors.

Bas.

@Bas

Thanks for the suggestion.

I already have them working as a stratum 0 time source. I was just sharing my solution.

Cabling was the easy part. Can be connected to DE9 (PPS on DCD) or RJ45 (PPS on CTS) RS232 ports.

The trick is enabling statistics logging and calculating the right fudge time 1 and time 2, but that applies to any GPS receiver with PPS.

[2.7.2-RELEASE][root@pfSense.[redacted].com]/root: ntpq -pn
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
o127.127.20.0    .GPS.            0 l   16   16  377    0.000   +1.303   0.004
 time.nist.gov   .POOL.          16 p    -   64    0    0.000   +0.000   0.000
+132.163.96.4    .NIST.           1 u   58   64  377   53.366   +1.465   0.429
+132.163.96.6    .NIST.           1 u   63   64  377   53.155   +1.537   0.513
+132.163.97.6    .NIST.           1 u   61   64  377   56.764   +1.674   0.460
[2.7.2-RELEASE][root@pfSense.[redacted].com]/root: ntpq -c sysinfo
associd=0 status=041d leap_none, sync_uhf_radio, 1 event, kern,
system peer:        GPS_NMEA(0)
system peer mode:   client
leap indicator:     00
stratum:            1
log2 precision:     -21
root delay:         0.000
root dispersion:    1.598
reference ID:       GPS
reference time:     e98e7294.6b78e6ce  Sat, Mar  2 2024 22:52:52.419
system jitter:      0.002500
clock jitter:       0.002
clock wander:       0.014
broadcast delay:    -50.000
symm. auth. delay:  0.000

Sorry to say, but the PPS line doesn’t contrain time and date info.
It only pulses and is normally locked to the normal NMEA driver to combine the two for correct time and date.

That is the reason there are always 2 lines in there.

If you don’t do that and the internet drops, it won’t know what to do with those pulses.

Bas.

I am by no means a NTPD algorithm expert, but I noticed if a source is marked as a valid PPS Peer o, NTPD uses that to sync and serve time to clients regardless if there a separate Active Peer * used for time data. If a GPS is being used for both a PPS Peer o and source of time data, it will be marked as PPS Peer o and there will be no other Active Peers * marked. The NTP Widget seems to display the Active Peer * even when the PPS Peer o is actually being used to sync and serve time to clients. Which source is actually served to clients can be confirmed with “ntpq -c sysinfo”.

As a test, I removed the NIST pool and added a single NIST server and marked it as no select. Seems to be using GPS for both time and PPS.

[2.7.2-RELEASE][root@pfSense.[redacted].com]/root: ntptime 
ntp_gettime() returns code 0 (OK)
  time e98edb42.843b1d0c  Sun, Mar  3 2024  6:19:30.516, (.516527909),
  maximum error 3633 us, estimated error 34 us, TAI offset 0
ntp_adjtime() returns code 0 (OK)
  modes 0x0 (),
  offset -861.970 us, frequency -33.804 ppm, interval 256 s,
  maximum error 3633 us, estimated error 34 us,
  status 0x2107 (PLL,PPSFREQ,PPSTIME,PPSSIGNAL,NANO),
  time constant 4, precision 0.001 us, tolerance 496 ppm,
  pps frequency -33.804 ppm, stability 0.024 ppm, jitter 8.414 us,
  intervals 7152, jitter exceeded 877, stability exceeded 0, errors 1.
[2.7.2-RELEASE][root@pfSense.[redacted].com]/root: ntpq -pn
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
o127.127.20.0    .GPS.            0 l   14   16  377    0.000   +0.391   0.565
 132.163.96.4    .NIST.           1 u   13   64    3   53.417   +0.811   0.334
[2.7.2-RELEASE][root@pfSense.[redacted].com]/root: ntpq -c sysinfo
associd=0 status=041d leap_none, sync_uhf_radio, 1 event, kern,
system peer:        GPS_NMEA(0)
system peer mode:   client
leap indicator:     00
stratum:            1
log2 precision:     -21
root delay:         0.000
root dispersion:    1.261
reference ID:       GPS
reference time:     e98edb4d.97dd5492  Sun, Mar  3 2024  6:19:41.593
system jitter:      0.392407
clock jitter:       0.007
clock wander:       0.000
broadcast delay:    -50.000
symm. auth. delay:  0.000
[2.7.2-RELEASE][root@pfSense.[redacted].com]/root: 

My understanding would be that the NMEA driver (20) is used to get both the second numbering from the NMEA data stream as well as the PPS pulses from the same driver, as also discussed in another recent thread. Note the server address, the RefID, and the lack of a star in front of any of the other servers on the billboard.

Thanks for sharing your solution! Small item, but quite interesting to see that BSD natively supports both DCD and CTS lines to serve as PPS input for kernel PPS. Linux typically only uses DCD, like illustrated by Dan Drown adding PPS capability to the CDC USB-UART bridge driver, as shared in a recent thread. Avoids having to muck around with the cables/connectors if a GNSS unit natively provides PPS on the CTS pin, as various units do.

2 Likes

Just have to set a tunable to use CTS line in a loader.conf.local file

Example

dev.uart.0.pps_mode="1"
1 Like

Normally you run it like this:

server 127.127.28.0 minpoll 4
fudge  127.127.28.0 time1 0.183 refid NMEA
server 127.127.28.1 minpoll 4 prefer
fudge  127.127.28.1 refid PPS

See here…

https://rjsystems.nl/en/2100-ntpd-garmin-gps-18-lvc-gpsd.php

@Bas

Thanks. I think that assumes you are using GPSD.

NOTE: The GPSD client driver (type 46) uses the GPSD client protocol to connect and talk to GPSD , but using the SHM driver is the ancient way to have GPSD talk to NTPD . There are some tricky points when using the SHM interface to interface with GPSD , because GPSD will use two SHM clocks, one for the serial data stream and one for the PPS information when available. Receivers with a loose/sloppy timing between PPS and serial data can easily cause trouble here because NTPD has no way to join the two data streams and correlate the serial data with the PPS events.

pfSense uses NTPD and the configuration GUI does not allow custom options.

Sure you can manually change the ntpd.conf file, but it will not persist on NTPD restart, reboot, or pfSense upgrade.

NTPD NMEA drivers support both NMEA messages and PPS in the same driver. I’ve had a Garmin GPS receiver connected to my pfSense firewall more than a year without issues.

1 Like

Yes I’m using GPSD and Chrony.

Not a fan of NTPD.

I also do not believe in firewalls as in seperate servers :rofl:

For the record, this is the relevant section of the ntpd.conf for my pfSense GPS+PPS config.

# GPS Setup
server 127.127.20.0 mode 176 minpoll 3 maxpoll 3 prefer
fudge 127.127.20.0 time1 0.0013 time2 0.369 flag1 1 flag3 1

time1 PPS offset to account for any electrical or interrupt delay.
time2 NMEA message offset from PPS, length, and baud rate.
flag1 enable PPS.
flag3 enable kernel PPS discipline.

2 Likes

Plotted loopstats clock offset over 24 hour period. Garmin GPS 18x sitting on a an interior window ledge, so not getting full sky view. Seems good enough for my homelab.

I would min/max-poll at 1, there is no reason to let it poll at 2^4.
Poll 1 is every 1~2 seconds, your computer has no problem doing that.

Every 16 seconds will fill the buffer with a lot of data and that takes time to collect and process.

I suggest you change 4 to 1 for better results.

Also, I would remove time1, the PPS is so fast, if you correct it you make it more in-accurate…in my opinion. As it’s typical in the nanosecond range already.

My 2 cents.

@bas

Thanks.

pfSense WebGUI lowest poll setting is 3 (8 sec), default is 4 (16 sec).

If I set time1 to 0, NTPD will use a time.nist.gov pool source for time data, although it will still report GPS stratum 1 served to clients. (ntpq -c sysinfo)

[2.7.2-RELEASE][root@pfSense.[redacted].com]/root: ntpq -c sysinfo
associd=0 status=041d leap_none, sync_uhf_radio, 1 event, kern,
system peer:        GPS_NMEA(0)
system peer mode:   client
leap indicator:     00
stratum:            1
log2 precision:     -21
root delay:         0.000
root dispersion:    1.542
reference ID:       GPS
reference time:     e9b0edd5.ce147334  Fri, Mar 29 2024  3:35:49.804
system jitter:      0.004529
clock jitter:       0.003
clock wander:       0.001
broadcast delay:    -50.000
symm. auth. delay:  0.000

IMHO, it’s about low jitter and adding a firewall rule to force all clients to use the local NTP server vs reaching out to the internet for time which will have several orders of magnitude higher offset and jitter.