I wanted to experiment with using temperature measurement to augment a NTP stratum 1 server. I started with a very similiar setup to this one. [Edit: the8thlayerof.net is gone, link changed to archive.org]. This will cover just getting NTP+PPS working.
GPS receiver: Adafruit Ultimate
- GPS PPS -> BBB P8.7
- GPS TX -> BBB P9.11 (UART4)
- GPS RX -> BBB P9.13 (UART4)
- GPS Vin -> BBB +3.3V
- GPS GND -> BBB GND
DTS overlay file for GPS (slightly modified to fix the 0-based vs 1-based resource reservations)
Temperature Sensor: DS18B20
- DQ -> BBB P8.11 (including a pullup resistor to +3.3V)
- Vdd -> BBB +3.3V
- GND -> BBB GND
These instructions are dependant upon what kernel and distribution you are running. This is for the 3.8.13-bone* kernel and Debian.
First thing that needs to happen is to tell the pinmux system about the pins needed. Take the DTS overlay files above and compile them to .dtbo files:
dtc -@ -I dts -O dtb -o DD-TEMP-00A0.dtbo DD-TEMP-00A0.dts dtc -@ -I dts -O dtb -o DD-GPS-00A0.dtbo DD-GPS-00A0.dts
Put those .dtbo files in
/lib/firmware. Next, tell capemgr about these two shields:
echo DD-TEMP >/sys/devices/bone_capemgr.9/slots echo DD-GPS >/sys/devices/bone_capemgr.9/slots
dmesg should have added a bunch of new lines, the main ones you're looking for are:
[ 341.544360] bone-capemgr bone_capemgr.9: slot #7: dtbo 'DD-GPS-00A0.dtbo' loaded; converting to live tree [ 341.555818] 481a8000.serial: ttyO4 at MMIO 0x481a8000 (irq = 45) is a OMAP UART4 [ 341.563682] pps pps0: new PPS source pps.15.-1 [ 345.295338] bone-capemgr bone_capemgr.9: slot #8: dtbo 'DD-TEMP-00A0.dtbo' loaded; converting to live tree
The DD-TEMP cape will complain that of_get_named_gpio_flags "can't parse gpios property", but this doesn't seem to be a problem. ttyO4 is the new serial device, and pps0 is the new pps device.
To make your changes permanent, edit the file /etc/default/capemgr and change
I installed gpsd and modified /etc/systemd/system/gpsd.service to contain:
[Unit] Description=GPS (Global Positioning System) Daemon Requires=gpsd.socket [Service] ExecStart=/usr/sbin/gpsd -n -N /dev/ttyO4 [Install] Also=gpsd.socket
The -n flag tells gpsd to run without a client connected.
I then installed chrony from source (to make sure the pps driver was enabled). To configure it, I put the following in /etc/chrony/chrony.conf:
# change the clock slower for less jitter minsamples 10 # get NMEA data from gpsd over shared memory refclock SHM 0 offset 0.395 delay 0.2 refid NMEA noselect # get PPS data from pps-gpio, summarize every 16 seconds, prefer it refclock PPS /dev/pps0 refid PPS poll 4 prefer keyfile /etc/chrony/chrony.keys commandkey 1 driftfile /var/lib/chrony/chrony.drift log tracking measurements statistics logdir /var/log/chrony maxupdateskew 100.0 dumponexit dumpdir /var/lib/chrony # if local stratum is configured and there's a local clock issue, the PPS changes stratum to match this stratum #local stratum 10 allow logchange 0.5 rtconutc # change this to the proper country code pool us.pool.ntp.org iburst offline
Enabling the overlays via the capemgr and starting gpsd+chrony gives this result after running for a few hours:
# chronyc sources 210 Number of sources = 2 MS Name/IP address Stratum Poll Reach LastRx Last sample ===================================================================== #? NMEA 0 4 377 12 +41ms[ +41ms] +/- 108ms #* PPS 0 4 377 12 -159ns[ -181ns] +/- 997ns
The PPS jitter is nice and low (just under 1us) and has a 377 reach history, which is good. The sample was last updated 12 seconds ago.
Some things to try: "nohz=off" kernel command line in /boot/uboot/uEnv.txt at the end of mmcargs. This should work around possible jitter introduced CONFIG_NO_HZ.
For the temperature compensation, see Part 2
For pictures, see cape construction