Raspberry Pi Statum 1 NTP Server (GPS/PPS)

Several weeks ago I decided to build my own stratum 1 NTP server using a Raspberry Pi 2B. Just like many other hobby projects, this doesn't really serve a purpose, other than learning something new. There are many articles about similar setup on the internet (see references below), these are just my own notes.

To build a stratum 1 NTP server, we need a reference clock. These are typically very expensive cesium chips. A much cheaper solution is to use a GPS receiver. These GPS receivers will receive the current time from GPS satellites which contain cesium chips.

The hardware

The setup is made up of the following components:

I used the expansion board from Hab Supplies because it does not require any soldering. It contains a Ublox MAX-M8Q module connected via serial to the RPi. The PPS output from the module is connected to GPIO18 (pin 12).
Assembling the hardware is easy, just follow the instructions provided. Once powered on, a red led on the expansion board lights up. Place the antenna in a location with a clear view of the sky and after a while, the timepulse led should start blinking. This could take several minutes.

GPS data

Some might wonder what kind of data we can get from the GPS module and how we can use it to determine the exact time. There are two signals, the NMEA sentences and the PPS signal.


The GPS module is connected via serial (9600 baud) to the RPi. Every second it sends NMEA sentences. This are simple lines of text values in a comma separated format. The first column indicates the type of data that follows. The most important ones are $GPRMC, $GPGLL, $GPGGA. These all indicate the current position, but more important in this case, they also contain the current time. The downside is that this time information isn't very accurate, it could easily be 100ms off and there is quite a bit of jitter as well. In practice, you get a more accurate time using sources on the internet. So this information is mainly useful when you do not want to depend on internet connectivity.


The PPS signal is the most important for accurate time keeping. It does not provide the current time but instead its a signal that sends one pulse every second. This pulse indicates the start of the second with a high accuracy. The signal is simply a voltage being applied on a GPIO pin for 100 milliseconds, after which it goes back to 0 for 900ms. Visually this looks like this:

In case of the Ublox module, the rising edge indicates the start of the second. Combined with a coarse grained time (accurate to ~0.4 seconds) obtained from the NMEA sentences on the serial port, or another time source such as an NTP server on the internet, this results in a very accurate clock.


PPS source

You need a kernel with PPSAPI support. Luckily this is included in the current raspbian kernels so this does not require any recompiling. Install the operating system as usual. I used "MINIbian" instead of the official distribution because I don't like installing more packages than needed. Whichever one you choose, start by installing all the latest updates first and assign a static IP to the machine. If you want to use DHCP, beware that some additional configuration may be required to prevent it from overwriting the NTP configuration file.

First of all, change the kernel parameters so that GPIO18 is used as PPS source and disable the serial console:

  • Add the following line to /boot/config.txt: dtoverlay=pps-gpio,gpiopin=18
  • Edit /boot/cmdline.txt and remove the following two items: console=ttyAMA0,115200 kgdboc=ttyAMA0,115200

After making these changes, reboot the Pi. During boot (or in dmesg) you should now see the following:

pps_core: LinuxPPS API ver. 1 registered
pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti
pps pps0: new PPS source pps.-1
pps pps0: Registered IRQ 466 as PPS source

Don't worry about PPS source pps.-1, this output is normal on the Raspberry Pi 2.

Install the "pps-tools" package via apt-get and run ppstest /dev/pps0. You should see one new line per second of output, similar to this:

trying PPS source "/dev/pps0"
found PPS source "/dev/pps0"
ok, found 1 source(s), now start fetching data...
source 0 - assert 1424290504.449416110, sequence: 81 - clear  0.000000000, sequence: 0
source 0 - assert 1424290505.449422255, sequence: 82 - clear  0.000000000, sequence: 0
source 0 - assert 1424290506.449430223, sequence: 83 - clear  0.000000000, sequence: 0

Recompile NTPd

The ntp package included in raspbian does not support the ATOM (PPS) reference clock so next you need to recompile the ntp package. Many articles build NTP from source, but I prefer rebuilding the raspbian package. This allows me to compile the package on one RPi and easily copy it to another.

  • Add the following line to /etc/apt/sources.list: deb-src http://mirrordirector.raspbian.org/raspbian/ wheezy main contrib non-free rpi
  • run apt-get update
  • Install the dependencies required to build the ntp package from source: apt-get build-dep ntp
  • Download the source code: apt-get source ntp
  • Go into the directory that was just created and add --enable-ATOM to the configure parameters in the debian/rules file
  • Increase the version number in debian/changelog. Change from 4.2.6.p5+dfsg-2+deb7u3 to 4.2.6.p5+dfsg-2+deb7u4~pps1 or similar.
  • Recompile the NTP package (this will take a while): dpkg-buildpackage -b
  • Once compiled, install the new ntp package: dpkg -i ntp_4.2.6.p5+dfsg-2+deb7u4~pps1_armhf.deb

Now that NTP is installed, add the following udev rules which create the symlink required so that ntpd can use the GPS module. Create a new file /etc/udev/rules.d/09-pps.rules with the following contents and restart the RPi:

KERNEL=="ttyAMA0", SYMLINK+="gps0"
KERNEL=="pps0", OWNER="root", GROUP="tty", MODE="0777", SYMLINK+="gpspps0"

Configure NTPd

Now that PPS is working and can be used by NTPd, all that is left is configuring NTPd to use the PPS source. There are several ways in which this can be configured, either using the NMEA driver with PPS support enabled, or using the ATOM driver with a preferred peer.

NMEA driver

The easiest and most reliable if there is no internet access is to use the NMEA driver (20) with flag1 (PPS) enabled. The configuration required is:

# NMEA /dev/gps0, /dev/gpspps0. Mode 17: 9600 baud (16) and process $GPMRC
server mode 17 minpoll 4 maxpoll 4 prefer
fudge time2 0.115
fudge flag1 1 # enable PPS signals processing
fudge flag2 0 # capture PPS pulse on rising edge
fudge flag3 0 # Do not use kernel clock dicipline - ntp comment claims this one is more accurate, and it does not appear to work?
fudge refid GPS
fudge stratum 15

Restart ntpd after making the configuration changes. After a little while, check the status using ntpq -p and the result should be something like this:

     remote           refid      st t when poll reach   delay   offset  jitter
oGPS_NMEA(0)     .GPS.            0 l    6   16  377    0.000   -0.198   0.017

Note the o in front, this means that the PPS signal is used.

Other tweaks

Not sure if these make a noticeable difference, but the other changes I made to this device are:

  • Set the CPU scaling governor to performance.
  • Set the low_latency flag on the serial port using setserial.


  • I have several different configuration other than the one mentioned above, using different drivers (NMEA only, ATOM+NMEA, ATOM+GPSd SHM). The plan is to compare the different options and see if there is a big difference. So far it seems the NMEA only setup performs better when there is no other network-based clock source available.
  • I wrote some C code to put the GPS module in "stationary" dynamic mode. Need to compare this over time to see if it makes a noticeable difference.

Blog Category:

Conflicting VIBs upgrading from VMWare vSphere 5.1 to vSphere 5.5 U1

I had a DL360 Gen8 server running VMWare vSphere 5.1 which was installed using the HP custom image. When trying to upgrade this server to vSphere 5.5u1 using the new HP ISO, the upgrade failed with the following error message:

The upgrade contains the following set of conflicting VIBs:
Remove the conflicting VIBs or use Image Builder to create a custom upgrade ISO image that contains the newer versions of the conflicting VIBs, and try to upgrade again.

It seems that the version of the broadcom drivers in vSphere 5.5u1 are older than those included in v5.5 and v5.1u2.

As a workaround, upgrade the host to v5.5, then downgrade the broadcom driver to 2.2.5d, and upgrade the host to v5.5u1 again. It might not be the easiest solution if you have many hosts to upgrade but in my case there were only two so this was the fastest.

  1. Download http://vibsdepot.hp.com/hpq/jun2014/esxi-550-devicedrivers/BCM-NetXtremeII-4.0-1796156.zip and extract the BCM-NetXtremeII-4.0-offline_bundle-1796156.zip
  2. Copy this file to /tmp on the ESXi host
  3. Run esxcli software vib install --depot=/tmp/BCM-NetXtremeII-4.0-offline_bundle-1796156.zip

After a reboot, upgrading to 5.5u1 should now work as expected.

Blog Category:

hpacucli on esxi 5.5 - no controllers detected

After upgrading a Proliant DL360 Gen8 ESXi host from vSphere 5.1 to vSphere 5.5, I noticed that the hpacucli command no longer worked. Instead of providing the usual output, it failed to detect the controllers:

~ # /opt/hp/hpacucli/bin/hpacucli ctrl all show status
Error: No controllers detected.

The solution is quite simple, instead of using hpacucli, use hpssacli instead:

~ # /opt/hp/hpssacli/bin/hpssacli ctrl all show status
Smart Array P420i in Slot 0 (Embedded)
   Controller Status: OK
   Cache Status: Temporarily Disabled
   Battery/Capacitor Status: Recharging

Blog Category:

Mobistar iPhone tethering possible again (personal hotspot)

Mobistar has always blocked tethering on their network. Years ago their was a workaround but that was only for very old iOS versions.

Today, it is once again possible to enable tethering. This time without "hacks". Rumor has it this will be officially announced on monday but the functionality is already working. All you need is an up-to-date iOS version and the latest carrier update.

To obtain the latest carrier update, go to Settings > General > Usage. Here a popup will appear asking if you want to install the carrier update.
Select update, and as soon as you have done that, the Settings > General > Network > Personal Hotspot item should appear.

Configuration is quite simple. At the top of the page, enable the personal hotspot.
You will be asked if you want to use USB or Bluetooth/Wireless. USB requires iTunes to be installed on the computer, if you use this option, don't forget to disable the hotspot after use, otherwise the computer will use it every time the iphone is connected.
Wireless/Bluetooth are especially useful if you want to use a second device to access the internet (such as an iPad), or if you don't want to install any additional software on your computer.

The main disadvantage for now is the poor 3G coverage of the mobistar network. In most of the places all you get is Edge, which is enough to synchronize email but to slow for anything else.


Subscribe to Bart Jansens RSS Subscribe to Bart Jansens - All comments