This is the first of (hopefully) several “notes to self”. They are intended as a record of my various tinkerings and processes that I’ve learned. Although publicly readable, they’re meant as notes to myself in the context of my personal setup and are not really intended as complete “how-to” guides. If you find it useful, awesome! If not, sorry.
The version of NTPd packaged in Raspbian Jessie doesn’t have support for PPS (why?!) or the Motorola Oncore driver enabled. It needs to be recompiled to support those options. The Oncore hardware is quite old, so I understand them not wasting a bit of space by enabling the Oncore driver at compile-time (though really, disk space is cheap and abundant), but no PPS? C’mon.
Anyway, here goes:
First, get the source and needed dependencies:
$ apt-get source ntp
$ sudo apt-get build-dep ntp
$ sudo apt-get install pps-tools libcap-dev libssl-dev build-essentials
Next, cd into the source directory. Edit the
debian/changelog file to add a note about PPS being added. Append
~pps0 or something to the version. This is needed to generate a package later.
Next, cd into
ntp/ntp-4.2.6.p5+dfsg/ntpd/ and edit
refclock_oncore.c. If using the Oncore, change
syslog(log_level, "%s", Msg); to
msyslog(log_level, "%s", Msg);. This allows the chatty Oncore logs to go to a (optional) user-specified log file rather than filling up syslog (and wasting SD card writes).
Next, cd back to the ntp source directory. Configure NTPd to enable the needed modules:
$ ./configure --enable-linuxcaps --enable-ATOM --enable-NMEA --enable-oncore
Next, build the package:
$ dpkg-buildpackage -b -j5 (-j5 lets the compiler use all 4 cores on the Pi, as well as having one compiler thread ready to go. This speeds things up significantly.)
Install the package:
$ sudo dpkg -i <package_name>.deb
Finally, make sure apt doesn’t automatically update it without our knowledge:
$ echo "ntp hold" | sudo dpkg --set-selections (check the status with
sudo dpkg --get-selections | grep hold)
Cool. NTP is now ready. Now configure the hardware. Be sure to use 3.3V-level signals — the Pi is not 5V tolerant!
Turn off the serial console:
$ sudo raspi-config
Advanced Options -> Serial -> Would you like a login shell to be accessible over serial? -> No
sudo nano /boot/config.txt
dtoverlay=pi3-miniuart-bt,pps-gpio,gpiopin=18 (assuming it’s connected to GPIO 18; use a different pin if desired.) to enable PPS and disable the Bluetooth setup on the hardware UART (only needed on Pi3 and presumably future versions). Presumably
pi3-disable-bt would also work but has not been tested; one might need to switch ttyAMA0 and ttyS0 in that case. Add
pps-gpio to a new line of
enable_uart=1 is enabled. (This is disabled by
raspi-config while turning off the console above, but it’s needed to re-enable it here.)
Disable the serial console in /boot/cmdline.txt:
dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
#dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
Prevent the Bluetooth connection from trying to connect to the UART:
$ sudo systemctl disable hciuart
$ sudo systemctl mask serial-getty@ttyAMA0.service
Check if everything works with
$ lsmod | grep pps. It should look something like this:
pps_ldisc 1972 0
pps_gpio 2655 1
pps_core 6779 3 pps_ldisc,pps_gpio
Also check this:
$ dmesg | grep pps
[ 3.307915] pps_core: LinuxPPS API ver. 1 registered
[ 3.311030] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti
[ 3.322724] pps pps0: new PPS source pps.-1
[ 3.322784] pps pps0: Registered IRQ 190 as PPS source
[13737.731304] pps_ldisc: PPS line discipline registered
[13737.733650] pps pps1: new PPS source serial0
[13737.733769] pps pps1: source "/dev/ttyS0" added
[17035.124787] pps pps1: removed
Test that serial data is coming in:
$ sudo stty -F /dev/ttyS0 9600
$ 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 1477954884.000004092, sequence: 26867 - clear 0.000000000, sequence: 0
source 0 - assert 1477954885.000000979, sequence: 26868 - clear 0.000000000, sequence: 0
source 0 - assert 1477954886.000003753, sequence: 26869 - clear 0.000000000, sequence: 0
source 0 - assert 1477954887.000005433, sequence: 26870 - clear 0.000000000, sequence: 0
Configure udev to create symlinks to make it so NTPd knows where to find the serial and PPS source:
$ sudo nano /etc/udev/rules.d/50-oncore.rules, the contents of which are:
For Pi1/2, replace ttyS0 with ttyAMA0.
/etc/ntp.conf for the Oncore:
# Oncore driver. May need to fudge the timing slightly, but seems to work fine out-of-the-box for me.
server 127.127.30.0 minpoll 4 prefer
# The Oncore driver logs are very (once-per-second) chatty. Let's put those in /tmp which is mounted as tmpfs, so I can save on SD writes.
If using other servers, be sure to add
minpoll 10 to the server line: when using a refclock, NTPd keeps the query time at 64 seconds. This is fine, but a bit impolite to internet servers, so I like to crank it up to 10 (1024 seconds). This can make NTPd slower to detect and respond to the GPS receiver going crazy, but I run non-critical systems so that’s fine.
/etc/ntp.oncore.N (where N is from 127.127.30.N) file with the necessary configuration options:
# Reference Clock configuration for Motorola Oncore M12
# Five Choices for MODE
# (0) ONCORE is preinitialized, don't do anything to change it.
# nb, DON'T set OD mode, DON'T set Delay, position...
# (1) NO RESET, Read Position, delays from data file, lock it in, go to OD mode.
# (2) NO RESET, Read Delays from data file, do SITE SURVEY to get position,
# lock this in, go to OD mode.
# (3) HARD RESET, Read Position, delays from data file, lock it in, go to OD mode.
# (4) HARD RESET, Read Delays from data file, do SITE SURVEY to get position,
# I have a supercap on the memory backup, so the board should have the almanac and other data ready to go (MODE 1) . If not, the system starts up in MODE 3 automatically.
# NB. If a POSITION is specified in the config file with mode=(2,4)
# then this position is set as the INITIAL position of the ONCORE.
# This can reduce the time to first fix.
# If we open one or the other of the files, we read it looking for
# MODE, LAT, LON, (HT, HTGPS, HTMSL), DELAY, OFFSET, ASSERT, CLEAR, HARDPPS,
# STATUS, POSN3D, POSN2D, CHAN, TRAIM
# then initialize using method MODE. For Mode = (1,3) all of (LAT, LON, HT) must
# be present or mode reverts to (2,4).
LAT DD.DDDDDD # Positive is North.
LONG DD.DDDDDDD # Negative is West
HTGPS XX.XX M # Height in meters. Can also use FT for feet.
DELAY 52.32 NS # Cable delay in nanoseconds. Could also use MS or US for milli and microseconds.
TRAIM YES # Sanity-check the results. Turn off PPS and report errors if something goes wrong.
Now I need to setup logrotate so the logs in /tmp/ don’t grow too large.
$ sudo nano /etc/logrotate.d/ntp and add:
su root root
copytruncate is the important one: NTPd doesn’t close out logfiles on its own, so logrotate needs to copy-and-truncate the existing file when it rotates.
Cool. Everything should now be setup and working!
remote refid st t when poll reach delay offset jitter
oGPS_ONCORE(0) .GPS. 0 l 8 16 377 0.000 0.047 0.004
+bwntp2.bluewin. 188.8.131.52 2 u 587 1024 3 10.875 -0.048 1.627
*time2.ethz.ch .PPS. 1 u 581 1024 3 8.870 -1.234 1.513
-aquila.init7.ne 184.108.40.206 2 u 549 1024 3 10.421 3.085 2.825
+bwntpo.bluewin. 220.127.116.11 2 u 562 1024 3 9.407 -1.155 1.663
+chilipepper.can 18.104.22.168 2 u 607 1024 3 26.632 -1.598 1.091