GPS w/PPS on the cheap - Stratum+PiAware

Since Piaware v3x is gpsd aware, figured I’d share an inexpensive (<$10) method to add a small GPS module to any existing Raspberry Pi for auto-location and Stratum-1 time keeping. I’m sorry if this was hit on before, I honestly didn’t search through the forums.

While there are several GPS hats available, most are over $40 and they wont fit inside most existing cases, so wanted to find something that would handle the duties that was small, cheap and accurate. Low and behold, after some testing of various modules and hats, I found a very small unit from AliExpress that fits the bill: GPS Module && Spec Sheet-ATGM332D

The link is an example, I suggest you shop around as I got mine for a buck cheaper through another reseller. At either rate, it’s basically a uBlox NEO-M8N clone for lack of better terms. Specs are nearly identical and it also handles BDS / GPS / GLONASS systems, so it picks up Chinese birds as well.

After searching seemingly forever around the internet and testing different and frankly terrible methods, I finally came across this link which explains in great detail how to set things up on the software front correctly:

If you don’t feel like reading everything, I created a small script for my own use that will do the install from a fresh Raspbian Lite image: {reboot is required after installation}
wget -O
chmod 755

I have a few modifications in the script that deviate slightly from the ntpsec outline. I do not recommend running the script, but use it as an outline instead as I have some things in there as it concerns my preferences like timezone locale, password changes for both Pi user and root, etc (Sorry for lack of comments, it wasn’t meant for public consumption). The script also completely bypasses wifi, bluetooth and HDMI, so if you need any of those things, it would need to be adjusted accordingly. That said, I do not advise keeping those things active if you want the most precise timing available. Though I have not tested an install on top of the existing piaware images, there is no reason it should not work - but please note the changes I just described so you are aware. Again - I do not recommend running the script as-is without understanding what it’s doing, you have been warned. (twice)

Here is a rather crappy picture of the wiring on my test platform for reference. The thing behind it hanging off pin1 of the GPIO is an RTC board DS3231 which plays nicely with the GPS module:

It can easily be tucked to another portion of the Raspberry and fit inside of any existing case if/as needed - again this is just the test setup and I wanted to show how easy it is to wire up.

No changes are required on the PiAware front and when rebooted, PiAware will automatically pickup your location for MLAT purposes, and your Raspberry will be very accurately clocked from GPS.

Here are timing results while running PiAware, dump1090, dump978:

There is a little bit of jitter due to the processor load, but it calms itself the longer it’s running. I hope someone finds this to be of use.


1 Like

Neat! Thanks for posting.

Since there is no native method to access PPS, it’s a better practice to recompile NTPD service to access PPS pulses directly instead using GPSD SHM. One less step, less jitter

For illustration purposes, I want to clarify to make sure I understood and that others can as well. What I believe you mentioned was to simply rebuild NTP from source since the repo version doesn’t have proper PPS support:

tar zxvf ntp-4.2.8p9.tar.gz  
cd ntp-4.2.8p9
./configure --enable-linuxcaps --prefix=/usr
sudo service ntp stop  
sudo make install
echo "ntp hold" | sudo dpkg --set-selections  #ELIMINATE APT UPDATE

#MODIFY /etc/ntp.conf FOR GPS/PPS
# Local
fudge stratum 10

# GPS with PPS enabled
server mode 17 minpoll 4 maxpoll 4 iburst true prefer  
fudge flag1 1 refid GPS

I hope this is correct. Will Piaware still link up without GPSD?

Exactly, but you have to use the .22 driver (xPPS)

# GPS Serial data reference
server minpoll 4 maxpoll 4
fudge time1 0.129 refid GPS

# the gps PPS
server prefer
fudge refid PPS

pi@raspberrypi:~ $ ntpq -p

     remote           refid      st t when poll reach   delay   offset  jitter
*SHM(0)          .GPS.            0 l    4   16  377    0.000   -3.689   4.434
xPPS(0)          .PPS.            0 l   51   64  377    0.000    5.302   0.254    2 u   52   64  377   11.627    5.494   0.524
+alpha.rueckgr.a    2 u    8   64  377  251.669   11.070   0.801
pi@raspberrypi:~ $

Piaware will use GPSD for coordinates and NTPD for time without bothering what’s behind them

What is Piaware doing with the GPSD data in comparison to when GPSD is not installed/running?

It passes it to the FA servers which use it for the mlat receiver location and updates the receiver position on the stats page.
It’s also used in places where the FA-stats-page-provided location would otherwise be used (dump1090-fa receiver location on the map, receiver location for faup1090 sanity checks)

When gpsd is not running, that data comes from the FA servers using the last set location on the stats page.

Ahh, ATOM driver :smiley: Need to make sure that prefer is set on another source or PPS will be discarded like above since it’s only “second” aware. That said, went back and performed more testing - the .22 driver is indeed showing very solid results so far. I had only dabbled with it once then went back to the .20 (NMEA) driver for subsequent tests. Thanks for the head’s up - so far it’s proving quite stable (.22 ATOM driver):

So here is a good question for everyone.
I recently added an Adafruit GPS hat to my piaware box.
My Raspberry pi is down in my basement, and I have a FA 1090 antenna on the roof. I previously had a lna4all preamp at the antenna, but it failed. For now I am just feeding my ADS-B traffic down about 50’ of LMR-400.

I have and external GPS antenna connected to the GPS hat, and it is located outside my basement egress window. The GPS antenna and the ADS-B antenna are not located in the exact same place. They are about 40’ laterally and maybe 20’ vertically away from each other

Will this cause any MLAT issues?

Are there any good ways to run both antennas through a diplexer on each end to share coax? The frequency spread might make that possible, but I am concerned about the dc over coax powering the active GPS antenna.

That’s close enough it’s unlikely to cause problems. The error from the sloppy timing of the rtlsdr dongle itself is on the order of 150m / 500ft; a receiver position error of 10% of that is probably OK.

Would be a different story with something like a Radarcape though.


Is there any way to receive some help with the Stratum-1-Microserver HOWTO?
Uhhm, I mean, how to bring it up with my UBlox M8N… I didn’t found any forum, group…

I have an UBlox M8N and according to ntpshmmon theres only NTP0 available, no entries for NTP1, NTP2…
And - with my old self build ntp an distri gpsd I could swap between pps or GPS time with 127.127.28.(0/1)
(Btw.: The .28 was the only driver who gave infomations to my ntp…).
For me, it seems, that the M8N gives me timepulses. So I’m changing in the ntp.conf:

# GPS PPS reference (NTP1)
refclock shm unit 0 refid PPS

# GPS Serial data reference (NTP0)
refclock shm unit 1 refid GPS

And I never saw a “oSHM(0)”, just the “thrown out” "xSHM(0).

Raspberry Pi 2B → Linux raspi 4.9.70-v7+ #1068 SMP Mon Dec 18 22:12:55 GMT 2017 armv7l GNU/Linux
cat /etc/debian_version → 9.3

Complete install according to: Stratum-1-Microserver HOWTO

  • remote           refid      st t when poll reach   delay   offset   jitter

xSHM(0) .PPS. 0 l 41 64 3 0.0000 -59.6504 12.9393
SHM(1) .GPS. 0 l - 64 0 0.0000 0.0000 0.0019
x192.53.103.108 .PTB. 1 u 36 64 3 35.8154 77.3238 80.5039

status=0018 leap_none, sync_unspec, 1 event, no_sys_peer,
version=“ntpd ntpsec-1.0.1+189 2017-12-25T17:10:14Z”, processor=“armv7l”,
system=“Linux/4.9.70-v7+”, leap=00, stratum=1, precision=-19, rootdelay=0.0,
rootdisp=7948.182, refid=PPS,
reftime=ddebf1f5.3b3c9a3c 2017-12-25T21:53:57.231Z,
clock=ddebf23d.4ef2a5e3 2017-12-25T21:55:09.308Z, peer=0, tc=6, mintc=0,
offset=-9.601829, frequency=55.061, sys_jitter=0.0, clk_jitter=3.39476,

ntpshmmon version 1
# Name Seen@ Clock Real L Prec
sample NTP0 1514237708.005410397 1514237708.004840211 1514237708.000000000 0 -20

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 1514237722.311077265, sequence: 1219551 - clear 0.000000000, sequence: 0

Hello, you are probably way past this now, but my quick comments are:

  1. You can in principle do what you want, I think, but you need to properly filter (diplex) the signals. DC is just another signal, a bias-T can remove it before the receivers (that’s what GPS does anyway). But, GPS signals are REALLY weak, so you will probably have trouble sharing the line and removing the non-GPS signals sufficiently, I believe that function is normally at the GPS antenna, before the preamp, so you would basically need to do it again at the other end. Not worth it!