Mictronics - DIY Electronic projects and more.

ADSB Receiver with GPS Precision Time

Here is an upgrade for my ADSB receiver - GPS precision time. The MLAT position calculation for aircrafts depends on a precise time. While there is already a time synchronization between MLAT receivers in a specific area it is also possible to add a precise time source to improve the calculation result. A GPS receiver is such source when equipped with a PPS (pulse per second) output. The PPS is a signal with a width of less than one second and a sharply rising or abruptly falling edge that accurately repeats once per second with low jitter. The GPS time and PPS signal  are then used to sync the internal ntp time service and keep a low offset and jitter.

My choice for GPS receiver was the Adafruit GPS v3 breakout board as it was a spare in my boxes. Beside the small size and high channel GPS receiver it has a PPS output and operates at 3.3V-5V input, but 3.3V TTL logic output, perfect for the Raspberry Pi. The additional backup battery come in handy in case of a power cut.

GPS board connection to Raspberry Pi 2/3 #
Adafruit GPS v3 pin     Raspberry Pi I/O header pin
VIN                     Pin 2 = 5V
GND                     Pin 14 = GND
TX                      Pin 10 = GPIO 15
RX                      Pin 8 = GPIO 14
PPS                     Pin 12 = GPIO 18
Enable PPS input and set UART baudrate #

To enable the PPS input and setting the correct baudrate for the GPS the Raspberry Pi config file /boot/config.txt must be changed. Add at the end:

# GPS PPS input
dtoverlay=pps-gpio,gpiopin=18
init_uart_baud = 9600
Disable serial console on UART0 #

The GPS is connected to the UART0 serial interface (ttyAMA0) that is usually occupied by the Raspberry Pi serial console. That needs to be disabled. So we edit /boot/cmdline.txt and change console=ttyAMA0 to console=tty1.

Also the getty instance on ttyAMA0 needs to be disabled:
$ sudo systemctl disable serial-getty@ttyAMA0.service

Install GPS service #

This service is required to access the GPS and it provides a shared memory the for the ntp service with its own time informations.

$ sudo apt-get install gpsd gpsd-clients python-gps

To successfully run the GPS service, its configuration needs to be changed to access the UART0. So edit /etc/default/gpsd as follows.

# Default settings for the gpsd init script and the hotplug wrapper.
# Start the gpsd daemon automatically at boot time
START_DAEMON="true"
# Use USB hotplugging to add new USB devices automatically to the daemon
USBAUTO="true"
# Devices gpsd should collect to at boot time.
# They need to be read/writeable, either by user gpsd or the group dialout.
DEVICES="/dev/ttyAMA0 /dev/pps0"
# Other options you want to pass to gpsd
GPSD_OPTIONS="-n"

Now we reboot and check that PPS and GPS are working.

$ dmesg | grep pps
[    5.957377] pps_core: LinuxPPS API ver. 1 registered
[    5.957515] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti giometti@linux.it;
[    5.973778] pps pps0: new PPS source pps.-1
[    5.973907] pps pps0: Registered IRQ 184 as PPS source

Installing pps-tools will provide some additional informations. This is a mandatory step in order to get ntp service with PPS working. Compiling ntp has a dependency for timepps.h that comes with pps-tools.

$ sudo apt-get install pps-tools
$ sudo 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 1482268186.000006148, sequence: 4647 - clear  0.000000000, sequence: 0
source 0 - assert 1482268187.000003768, sequence: 4648 - clear  0.000000000, sequence: 0
source 0 - assert 1482268188.000003324, sequence: 4649 - clear  0.000000000, sequence: 0

Checking that GPS service is running:

$ sudo service gpsd status
gpsd.service - GPS (Global Positioning System) Daemon
  Loaded: loaded (/lib/systemd/system/gpsd.service; static)
  Active: active (running) since Tue 2016-12-20 19:45:08 UTC; 1h 26min ago
  Main PID: 745 (gpsd)
   CGroup: /system.slice/gpsd.service
           └─745 /usr/sbin/gpsd -N -n /dev/ttyAMA0</pre>
Dec 20 19:45:08 raspberrypi systemd[1]: Started GPS (Global Positioning System) Daemon.

Also $ cgps -s should output something like:

x    Time:       2016-12-20T21:14:35.000Z   xxPRN:   Elev:  Azim:  SNR:  Used: x
x    Latitude:    xx.xxxxxx N               xx  12    78    291    24      Y   x
x    Longitude:   xx.xxxxxx E               xx  24    67    133    00      Y   x
x    Altitude:   xxx.x m                    xx  25    36    261    29      Y   x
x    Speed:      1.1 kph                    xx  32    33    303    15      Y   x
x    Heading:    71.1 deg (true)            xx  19    32    050    17      Y   x
x    Climb:      0.0 m/min                  xx   6    21    087    00      N   x
x    Status:     3D FIX (5 secs)            xx  17    18    042    00      N   x
x    Longitude Err:   +/- 16 m              xx   2    15    122    00      N   x
x    Latitude Err:    +/- 27 m              xx  14    14    322    21      N   x
x    Altitude Err:    +/- 19 m              xx  15    10    182    19      N   x
x    Course Err:      n/a                   xx  29    04    203    00      N   x
x    Speed Err:       +/- 199 kph           xx  10    01    268    00      N   x
x    Time offset:     0.506                 xx 136    00    000    00      N   x
x    Grid Square:     xxxxxx                xx                                 x
Getting an NTP with PPS ("ATOM") support #

Unfortunately, the version of NTP supplied with the Raspberry Pi Linux does not support PPS. These are the steps to download, compile and install NTP. You can choose between a release and a development version.  The lines below are shown for release version ntp-4.2.8p9, but you will need to alter the version number to suit the version you wish to compile.

$ sudo cp /usr/include/sys/timepps.h /usr/include/.
$ mkdir ntp                          # make a convenient working directory, if you don't already have one
$ cd ntp                             # enter that directory
$ sudo apt-get install libcap-dev    # once-off, required to prevent later file not found error
$ sudo apt-get install libssl-dev    # once-off, you may not need this, but reports suggest you might to build keygen
$ wget https://www.eecis.udel.edu/~ntp/ntp_spool/ntp4/ntp-4.2/ntp-4.2.8p9.tar.gz
$ tar xvfz ntp-4.2.8p9.tar.gz
$ cd ntp-4.2.8p9
$ ./configure --enable-linuxcaps     # takes some minutes
$ make -j5                           # takes some minutes
(use "make -j5" for faster execution on the four-core Raspberry Pi 2/3.)
$ sudo make install                  # puts ntp* in /usr/local/bin/ntp*, takes some seconds
$ sudo service ntp stop
$ sudo cp /usr/local/bin/ntp* /usr/bin/  &amp;&amp; sudo cp /usr/local/sbin/ntp* /usr/sbin/
$ sudo service ntp start

Optional check for version and basic function
$ ntpq -crv -pn

Before we can alter the ntp service configuration we need to overcome a problem on Raspberry Pi's Debian OS. In fact, when you edit /etc/ntp.conf to use PPS and GPS time the DHCP or DHCP3 service will stealthy replace your ntp configuration by its own. So after reboot the ntp service will most like not use PPS and GPS as configured. This is why we disabled the DHCP behavior with overwriting the ntp configuration. Edit /etc/dhcp/dhclient.conf:

From:
request subnet-mask, broadcast-address, time-offset, routers,
        domain-name, domain-name-servers, domain-search, host-name,
        dhcp6.name-servers, dhcp6.domain-search,
        netbios-name-servers, netbios-scope, interface-mtu,
        rfc3442-classless-static-routes, ntp-servers;
To:
request subnet-mask, broadcast-address, time-offset, routers,
        domain-name, domain-name-servers, domain-search, host-name,
        dhcp6.name-servers, dhcp6.domain-search,
        netbios-name-servers, netbios-scope, interface-mtu,
        rfc3442-classless-static-routes;</pre>
Remove the DHCP service hook and the stealthy created ntp configuration:

$ sudo rm /etc/dhcp/dhclient-exit-hooks.d/ntp
$ sudo rm /var/lib/ntp/ntp.conf.dhcp

Reboot.

No we can edit the ntp service configuration to use PPS and GPS inputs for precision time. My configuration in /etc/ntp.conf

# /etc/ntp.conf, configuration for ntpd; see ntp.conf(5) for help

driftfile /var/lib/ntp/ntp.drift

# coarse time ref-clock, not really needed here as we have LAN &amp; WAN servers
server 127.127.28.2 minpoll 4 maxpoll 4 iburst true prefer
fudge 127.127.28.2 flag1 1 refid SHM2 stratum 1

# Kernel-mode PPS ref-clock for the precise seconds
server 127.127.22.0 minpoll 4 maxpoll 4
fudge 127.127.22.0 refid PPS

# Enable this if you want statistics to be logged.
#statsdir /var/log/ntpstats/

statistics loopstats peerstats clockstats
filegen loopstats file loopstats type day enable
filegen peerstats file peerstats type day enable
filegen clockstats file clockstats type day enable

# pool.ntp.org maps to about 1000 low-stratum NTP servers. Your server will
# pick a different set every time it starts up. Please consider joining the
# pool: &lt;http://www.pool.ntp.org/join.html&gt;
server 0.de.pool.ntp.org minpoll 10 iburst prefer
server 1.de.pool.ntp.org minpoll 10 iburst
server 2.de.pool.ntp.org minpoll 10 iburst prefer
server 3.de.pool.ntp.org minpoll 10 iburst
server fritz.box minpoll 5 maxpoll 5 iburst

Note that when using a PPS source you must have one other server marked "prefer".  In the example above I have added prefer to the shared memory driver (type 28) so that the combination of PPS and GPSD would provide the correct time even with no Internet servers. The ntp service needs a restart then.

$ sudo service ntp force-reload

Now the ntp service should use PPS and GPS input for precision time keeping.
$ ntpq -crv -pn

associd=0 status=0115 leap_none, sync_pps, 1 event, clock_sync,
version="ntpd 4.2.8p9@1.3265-o Tue Dec 20 15:33:14 UTC 2016 (1)",
processor="armv7l", system="Linux/4.4.38-v7+", leap=00, stratum=1,
precision=-19, rootdelay=0.000, rootdisp=1.075, refid=PPS,
reftime=dc042552.9b78088d  Tue, Dec 20 2016 21:46:58.607,
clock=dc042558.9751bae5  Tue, Dec 20 2016 21:47:04.591, peer=44360, tc=4,
mintc=3, offset=0.011402, frequency=-8.472, sys_jitter=0.001907,
clk_jitter=0.107, clk_wander=0.011
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
 127.127.28.0    .GPS.            1 l    7   16  377    0.000    4.899   5.445
o127.127.22.0    .PPS.            0 l    6   16  377    0.000    0.011   0.002
 192.168.178.255 .BCST.          16 B    -   64    0    0.000    0.000   0.002
+192.168.178.1   131.188.3.221    2 u   44   64   77    0.515    0.967   0.038
*131.188.3.221   .DCFp.           1 u  359 1024    1   34.215    0.470   0.172
+2003:63:2737:e7 131.188.3.221    2 u   30   32  377    0.547    0.910   0.114

The PPS and GPS drivers are present and connected (reach = 377).

References:

https://frillip.com/raspberry-pi-stratum-1-ntp-server/

http://www.satsignal.eu/ntp/Raspberry-Pi-quickstart.html

http://www.satsignal.eu/ntp/Raspberry-Pi-NTP.html

http://www.catb.org/gpsd/gpsd-time-service-howto.html

http://serverfault.com/questions/329596/how-to-override-the-ntp-information-sent-by-dhcp-in-debian

http://www.catb.org/gpsd/troubleshooting.html

https://www.adafruit.com/product/746

👈 Home