My portable network time server / GPS feeder is about done

Ryan - KJ7GIE

I've had this idea for a while and finally bought the parts and started working on it a couple weeks back. For the most part, as of this past weekend, it works. What is it? Why?

Some digital modes require accurate time and some radio software is easier to use if it knows your location. Examples of these are FT8, JT65, APRS, Fldigi / Flmsg, some Winlink forms, D-Star (if the Icom radio knows your location it will auto-populate nearby repeaters), and a handful of others. My idea was to use a Raspberry Pi with GPS module to both follow the Pulse Per Second (PPS), to keep the clock accurate, as well as send the NMEA data out a serial port to whatever device is attached. The Raspberry Pi would also act as a Network Time Protocol (NTP) server so other devices could use the high accuracy of the PPS to keep their clocks synced. The Raspberry Pi can also act as a DHCP server so, in the field for example, anything plugged into it on the network will obtain an IP address as well as auto-configure to use the Pi as the time source. The Pi can be run from any 5v power source. I have not identified the actual power draw yet.

Parts List:
Raspberry Pi 4 - I'm using a 3 because that's what I had on hand. There are issues with the 3 that make it less accurate. I recommend get a 4 if you can but a 3 does work.

Adafruit Ultimate GPS HAT - There are other options that should work but this was straightforward and works as advertised.

Adafruit Active GPS Ant - The GPS HAT has an embedded antenna on the circuit board but I wasn't sure how good it was so got this antenna anyway. More on this below.

SMA - UMCC pigtail - The external antenna connector on the GPS HAT is one of those silly tiny, expect you'll damage it, UMCC connectors. Need this adapter to use the ant.

AB Electronics Serial Pi Plus - More on this below

One 1220CR battery - This allows the GPS HAT to keep time even if powered off which allows for _really_ fast GPS locks times once it is powered.

Short write-up:
I can go into more detail but essentially here is my set-up. The GPS HAT starts trying to acquire a signal as soon as it has power. I used Raspberry Pi OS. There is only 1 serial port on the Raspberry Pi and that, by default, is used for the console. This console configuration gets disabled which allows the HAT to take-over the serial UART. Now the Raspberry Pi can read the GPS output from the HAT. Configure the Raspberry Pi to read the PPS on the GPIO pin and enable the kernel PPS module. The UART of the Pi works with 2-wires and +/- 3 volts. That is completely unreliable for anything that is expecting RS232 (including my radio and the PC I used for testing). The Serial Pi Plus converts the UART signals to proper RS232 which the attached device can understand. This is the only reason the Serial Pi is required. There may be better options than the Serial Pi but this was a quick path to solve the UART problem. Note! This is a _giant_ hack as the GPS HAT is expected to feed the Raspberry Pi and _not_ an external device but we'll all just nod our heads, smile, and move on (again, this is the short write-up).

Software used: ntp-4.2.8p15 compiled with minimal configuration + gps/pps module. A couple start-up scripts and a script to hack-up getting the Serial Pi to spit-out the NMEA lines periodically. I am not using gpsd as that causes issues with the serial port. NTP has its own modules for reading time from a GPS / PPS and that's working just fine. Various other bits of software were used for testing but I settled on NTP stand-alone. It ended-up being the cleanest way to accomplish the goal.

Testing: I currently have NTP running on the raspberry pi using both the PPS as well as the GPS feed. I also added all the Ubuntu pool servers. I've let the thing stabilize over the last 12 hours (NTP wants multiple days but this is closer to what it looks like shortly after boot which is how it would work in the field) and the results are below. Surprisingly the GPS HAT board antenna, in a south facing window sill, acquires a GPS lock without issue but it's location drifts a bit. For testing this works fine but I'm looking forward to seeing if it gets better with the external antenna. I am waiting to get to a more "permanent" installation before using the little UMCC pigtail. I may even wait until I have a proper case to keep that cable stable (I'm fearful of busting the connector on the board). The serial port is connected to a PC in my shack and I'm using VisualGPS which will graph Lat / Long / Altitude so I can see any drift from the GPS. So far, feeding the NMEA from the serial port is reliable enough to keep VisualGPS within a house of my actual location. Additionally, on the Windows 10 PC I loaded NTP and disabled Windows time sync. Immediately after doing this I fired WSJT to receive some FT8 and was averaging 0.5 DT. I think that's pretty good.

Next: I have a DB9 -> 2.5mm cable ordered so I can plug the thing into my IC-7100. I need to get the Raspberry Pi integrated with my home network and update my DHCP server so all the machines in my house will use it for time sync. Need to identify power draw with the ext ant. I'm on the hunt for someone who can 3D print me a custom case. I think that's about it. Onto the next project. And, of course, work on my field kit since this whole thing is intended to be portable. ohh... maybe do a more in-depth write-up on some of the things I learned but that will be towards a targeted audience so I don't bore the whole club.

I'll post a picture on FB.

73's all!

$ ntpq -pn
remote refid st t when poll reach delay offset jitter
o127.127.22.0 .PPS. 0 l 1 64 377 0.000 +0.084 0.027
* .GPS. 0 l 2 64 377 0.000 -121.72 118.636
+ 2 u 44 64 377 0.578 +4.665 0.085
0.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 +0.000 0.002
1.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 +0.000 0.002
2.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 +0.000 0.002
3.ubuntu.pool.n .POOL. 16 p - 64 0 0.000 +0.000 0.002 .BCST. 16 B - 64 0 0.000 +0.000 0.002
+ 2 u 57 64 377 178.121 +0.388 4.187
+ 2 u 11 64 377 75.812 +0.772 10.082
+ 2 u 5 64 377 180.309 -0.108 2.777
+ 2 u 63 64 177 77.774 -3.311 1.599
+ 2 u 62 64 377 67.850 +2.049 3.642
+ .SOCK. 1 u 52 64 377 211.595 +2.115 1.557
+ 2 u 61 64 377 33.015 +4.361 6.329
+ 2 u 43 64 377 42.220 +6.381 3.827
+ 2 u 43 64 377 75.821 +0.706 3.661
+ 2 u 10 64 377 175.342 -2.247 6.280
+ .PPS. 1 u 14 64 377 76.507 -2.168 4.968
+ 2 u 49 64 377 85.071 -2.373 7.619
+ 2 u 48 64 377 92.448 +0.481 6.708

NOTE: The "o" means NTPd is using a PPS source and this row is available to adjust the system time. The * is the current "active" reference clock. When using GPS and PPS together NTP will adjust ticks to PPS but pull current time from GPS. The high "offset" on the GPS is caused by tremendous jitter / latency of the UART on the Raspberry Pi 3 since the UART speed is tracked against CPU frequency. That's terrible for precise time keeping. I've configured the Pi to minimize this as much as possible but this is why I recommend using a Pi 4. The rest of the lines are standard NTP server configuration for most Linux distributions and are currently being used just to make sure my GPS source is staying accurate against other sources. If the GPS was to drift too much it would "x" those lines and * a more accurate source. The +'s are candidates if the current reference were to fail.