- Notifications
You must be signed in to change notification settings - Fork0
Create A Raspberry Pi 3 Model B and u-blox CAM-M8C GPS NTP server
License
johnsom/rasp-gps-ntp
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Contents
- Introduction
- Hardware
- Soldering
- Booting the Raspberry Pi
- Test the BerryGPS-IMUv3 Integration
- Configuring NTPsec
- Graphing with ntpviz (Optional)
- Configuring the u-blox Module (Optional)
- Setting up a watchdog timer (Optional)
- Enabling the u-blox DDC / I2C Device (Optional)
- u-blox Multi GNSS AssistNow Online (Optional)
- Raspberry Pi 4
- Future Work
- Disclaimers
This is a project to create a Network Time Protocol (NTP) server using aRaspberry Pi 3 Model B and a u-blox CAM-M8C GNSS module.
Yes, there are a lot of existing web pages describing how to setup a RaspberryPI to be a GPS based NTP server, but none of them had the level of detail Iwanted.
- GPS time pulse output for Pulse Per Second (PPS) synchronization.
- A full Linux server OS to support additional services on the Raspberry Pi.
- U-blox based chipset (I have used them for projects at a previous employer).
- Multiple independent interfaces for the GPS chip so it can be used formultiple purposes.
- Reasonable cost as this is a hobby project.
I should note that a Raspberry Pi can be used as an NTP server without GPSintegration by simply synchronizing to NTP server pools available on theinternet. However, this project was to setup GNSS synchronized stratum 1 NTPserver.
I started out usinggpsd andchrony for the NTP service, but found bothto be fairly opinionated and added unnecessary layers to the software stackwhich added latency. It was a useful learning experience, but I ended upremoving those packages and installing NTPsec instead. Both gpsd and chronyare useful for simple deployments and for intermittently connected clients, butthey did not let me control the u-blox module the way I want to.
Chrony does have one advantage, which is kernel or hardware timestamping whensynchronizing over the network. However, the Raspberry Pi 3 network interfacedoes not support hardware timestamping. I plan to setup linuxptp to providePrecision Time Protocol (PTP) on my network in the future. This will leveragethe timestamping features of the kernel and/or network interface. I expect thiswill require a Raspberry Pi 4, possibly with a USB network interface thatsupports hardware timestamping. See theFuture Work section for moreinformation.
I selected parts that I already had available or were familiar with. Asmentioned in the introduction, I have used u-blox modules before and have beenimpressed with their capabilities. I also already had a Raspberry Pi 3-Bhosting my other network services.
- Raspberry Pi 3 model B
- CanaKit setup for the Raspberry Pi 3 (Note: Some of these kits include the Raspberry Pi 3 modelB board)
- Heatsinks
- Power supply
- Case
- 128GB "high endurance" microSD card
- OzzMaker BerryGPS-IMUv3 (contains theu-blox CAM-M8C module)
- Active GPS antenna with the required uFL to SMA adapter
In addition, I already had the required USB keyboard, USB mouse, HDMI,microSD to USB adapter, and network cables required to set this up.
I have created an Amazon "Idea List" with thelist of parts here. (Note: I do not get anycompensation if you order from this list, it's just there for your convenience)
You may be able to source these parts cheaper or substitute alternate parts.
I selected the OzzMaker BerryGPS-IMUv3 over the other GPS offerings for a fewreasons:
- It uses a modern u-blox module.
- It pulls the UART, I2C, and PPS pins out from the u-blox module.
- Supports an external antenna.
In the end, the BerryGPS-IMUv3 has more capability in the IMU than I need andis a bit more expensive than some options, but I am happy with the board andthe responsiveness I got from OzzMaker when I had a question about the board.
Note
The BerryGPS-IMUv3 does require some solder work for this project.The 5x2 header for the Raspberry Pi needs to be soldered to theBerryGPS-IMUv3 board. You will also need to solder a wire from the PPS pinhole on the BerryGPS-IMUv3 board to one of the GPIO pins on theRaspberry PI. In addition, if you want access to the I2Cinterface on the u-blox module, you will need to solder wires to extendthe I2C bus.
I am recommending a "high endurance" microSD purely due to the write loadrunning Linux can have. Specifically, the logging and other actions under /var.Unfortunately, most microSD cards have very low write endurance and mostdo not provide information on the endurance of a device or if the deviceincludes write wear leveling. Purchasing a microSD card that is larger thanyou need may help extend the life of the card if write wear leveling is in use.Below I will make some recommendations about ways to reduce the write loadfor this use case.
Someone was very kind by gifting me a Raspberry Pi 4 board. Thank you!I have created a update section below discussing what I have found with theRaspberry Pi 4.
Another very kind person gifted me one of the OzzMaker BerryGPS-IMUv4 boards.Thank you!
This is an update to the BerryGPS-IMUv3 which adds a Super Cap that allows theGPS module to maintain the ephemeris data for up to four hours if the moduleloses power. This means a faster time-to-first-fix if power is restored withinthe four hour window. After four hours the ephemeris data will be stale andshould be refreshed or reacquired from the satellites.
The BerryGPS-IMUv4 also has slightly different IMU sensors and QWIICconnectors.
Note
When using the QWIIC connectors, the GPS is only available over I2C.
The BerryGPS-IMUv4 is fully compatible with the BerryGPS-IMUv3 board.
- Solder the 5x2 header onto the BerryGPS-IMUv3 board. The header should beon the back of the board so that it will join with the Raspberry Pi 40 pinheader.
- Solder a wire from the "T_PULSE" pin hole on the BerryGPS-IMUv3 to a freeGPIO ping on the Raspberry Pi. I selected the GPIO 21 pin. You can use ajumper cable with a female connector for the GPIO pin if you have one, butmake sure it is a tight fit with the pin. Make note of the pin you selectedas you will need it later during the kernel configuration step.
- Optionally, connect the u-blox module I2C bus to theBerryGPS-IMUv3 I2C bus.
- Solder a wire from the SDA pin hole to the uSDA pin hole.
- Solder a wire from the SCL ping hole to the uSCL pin hole.
I chose to use Ubuntu Server on my Raspberry Pi for this project. It is acomplete Linux distribution that includes all of the packages I needed for thisproject but also the other services I want to run on the Raspberry Pi. Theyalso regularly release patches and updates which is nice.
At the time of this writing, version 19.10.1 (Eoan Ermine) of Ubuntu Server wasavailable. I plan to upgrade this device to 20.04 LTS (Focal Fossa) when it isreleased.
Download the 64-bit version of Ubuntu Server for the Raspberry Pi 3 fromtheUbuntu Raspberry Pi page.
Follow the instructions on this page to flash the microSD card with thedownloaded image.
Note
If you use the Win32Diskimager tool, it will not run if you have any RAMdisks mounted in Windows. This is listed in the release notes, but youhave to look to find it. I use a RAM disk as a temporary cache and gotblocked by this issue for a bit. Simply unmounting the RAM disk allowsthe application to start.
Make sure the BerryGPS-IMUv3 is not yet attached to the Raspberry Pi. TheNEMA codes from the GPS module UART will halt the Raspberry Pi from booting.
Install the microSD card in the Raspberry Pi and power it up.
You will see the normal Linux kernel boot sequence on the screen. On firstboot, give it some time before attempting to login. The cloud-init on thefirst run will take some time even after the login prompt is up. The defaultimage username and password of "ubuntu" will not work until cloud-init isfinished. Once you see the kernel booting, it is a good time to get abeverage.
Once you are logged in, do your updates:
sudo apt-get updatesudo apt-get dist-upgrade
You will also need some additional packages:
sudo apt-get install pps-tools rng-tools ntpsec cpufrequtils dkms python3
Configure the kernel command line:
- Edit the /boot/firmware/nobtcmd.txt
- Remove the "console=ttyAMA0,115200" section. This stops the kernel fromusing the Raspberry Pi UART as a serial console. We will be using it forthe u-blox UART.
- Add "nohz=off" to the command line. This causes the kernel to never omitscheduling clock ticks.
- Edit the /boot/firmware/nobtcmd.txt
Configure the kernel device tree:
- Edit the /boot/firmware/syscfg.txt
- Add "dtparam=i2c_arm=off". This disables the broken I2C buson the Broadcom chip used in the Raspberry Pi 3 model B. The hardwareI2C bus on the Broadcom chip does not support clockstretching used by the u-blox module.
- Add "dtparam=spi=off". This disables the SPI bus on the Raspberry Pi.We don't need it.
- Add "dtoverlay=pps-gpio,gpiopin=21". This sets the GPIO pin on theRaspberry Pi that is connected to the "T_PULSE" or PPS pin hole on theBerryGPS-IMUv3. If you used a GPIO pin other than 21 in the solderingsection above, replace the "21" on this line with the correct pinnumber.
- Add "dtoverlay=pi3-disable-bt". This disables the Bluetooth device onthe Raspberry Pi. This is optional, but I don't need it so I am going todisable it.
- Add "dtoverlay=pi3-disable-wifi". This disables the WiFi device on theRaspberry Pi. This is optional, but I don't need it so I am going todisable it.
- Add "dtoverlay=i2c-gpio,bus=3,i2c_gpio_sda=02,i2c_gpio_scl=03,i2c_gpio_delay_us=2". This enables the software I2C driver using GPIO pins onthe Raspberry Pi. This approach avoids the corruption that occurs withthe hardware Raspberry Pi I2C bus due to clock stretching.This is optional and only required if you intend to use theI2C bus on the BerryGPS-IMUv3.
- Edit the /boot/firmware/syscfg.txt
Enable the pps-gpio kernel module at boot:
echo"pps-gpio"| sudo tee -a /etc/modules-load.d/pps-gpio.conf
Shutdown getty on the ttyAMA0 device:
sudo systemctl stop serial-getty@ttyAMA0.servicesudo systemctl disable serial-getty@ttyAMA0.service
Setup udev to disable echo on the ttyAMA0 device:
sudo cp udev/09.ttyAMA0.rules /etc/udev/rules.d
If you do not disable echo on the tty device, you will see garbage in yourNMEA message stream from the ttyAMA0 device and GNTXT NMEA messages with"More than 100 frame errors, UART RX was disabled" in them.
Set the CPU frequency governor to "performance":
echo'GOVERNOR="performance"'| sudo tee -a /etc/default/cpufrequtils
Reboot and disable the uboot boot delay to stop the GPS messages fromaborting the boot process.
- Run "sudo reboot"
- When you see text, after the Raspberry Pi color gradient, start hittingthe "enter" key until you get a uboot prompt.
- Enter "setenv bootdelay -2". This disables the uboot delay so that NMEAmessages from the u-blox UART do not interrupt the boot sequence.
- Enter "saveenv". This saves the above setting so it is in effect on eachboot.
Attach the BerryGPS-IMUv3 board to the Raspberry Pi:
- Power off the Raspberry Pi.
- Install the plastic support pins included with the BerryGPS-IMUv3. Onlytwo line up for me.
- Attach the BerryGPS-IMUv3 to the Raspberry Pi by lining up the 5x2 headerwith the top GPIO pins (1 and 2) on the Raspberry Pi 3.
- Attach the antenna to the BerryGPS-IMUv3.
- Be sure to set the antenna switch to "EXT" to use the external antenna.
- Attach the PPS (T_PULSE) wire to the GPIO pin (21 in my case) if you havenot already done so.
Power up the Raspberry Pi. It should boot back to the login prompt if theprevious steps were completed correctly.
Login and run a test on the PPS source (ctrl-c to exit):
sudo ppstest /dev/pps0
This should show similar output to this example:
trying PPS source "/dev/pps0"found PPS source "/dev/pps0"ok, found 1 source(s), now start fetching data...source 0 - assert 1578164816.999990228, sequence: 966890 - clear 0.000000000, sequence: 0source 0 - assert 1578164817.999992699, sequence: 966891 - clear 0.000000000, sequence: 0
Check that the NMEA messages are streaming on the ttyAMA0 device(ctrl-c to exit):
sudo cat /dev/ttyAMA0
This should show similar output to this example:
$GNRMC,193854.00,V,0000.00000,N,00000.00000,W,0.015,,040120,,,A*71$GNZDA,193855.00,04,01,2020,00,00*7E
You should not see any non-ascii characters in this stream.Note: I have zeroed out the coordinates and marked the message as 'V',invalid, here for privacy reasons. Your RMC message will likely have an'A' and actual coordinates.
If these steps all check out ok, you have successfully completed the abovesteps and can now move on to configuring the NTP service on your RaspberryPi.
If not, go back through the initial steps and make sure you didn't miss astep. Also, double check you solder work. Adafruit has an excellentCommon Soldering Problems guide that may help.
Allow the ntpd process access to the devices:
echo'@{NTPD_DEVICE}="/dev/ttyAMA0" "/dev/pps0"'| sudo tee -a /etc/apparmor.d/tunables/ntpdsudo apparmor_parser -r /etc/apparmor.d/usr.sbin.ntpd
Configure ntpsec:
- Create the /etc/ntpsec/ntp.d/refclock.conf file.
- Add "refclock nmea flag1 1 path /dev/ttyAMA0 ppspath /dev/pps0 baud9600". This enables the NMEA driver with a PPS source.
Note
You may want to add "flag4 1" to this string if your NTP service willbe accessible from untrusted systems. This will mask the GPS antennalocation information from being avialable in the logs or via"ntpq -c clockvar <server>".
- Create the /etc/ntpsec/ntp.d/refclock.conf file.
Optionally update the network NTP pool configuration:
- Edit the /etc/ntpsec/ntp.conf file.
- Modify the "pool" configuration lines to reflect network NTP poolyou would like to use. By default, Ubuntu configures these for"ubuntu.pool.ntp.org" pools. See theNTP Pool Projectfor more information about available pools.
Note
If you don't define any additional time sources, ntpsec will not selectthe PPS source and set the system clock. This is because the defaultconfiguration file includes a "tos" "minsane" configuration that requiresmultiple servers. You can comment out this line if you will only be usingthe NMEA and PPS source from the CAM-M8C module.
- Edit the /etc/ntpsec/ntp.conf file.
Restart the ntp service to load the new configuration:
sudo systemctl restart ntpsec
Check the NTP server peer status:
sudo ntpq -np
You should see output similar to this:
remote refid st t when poll reach delay offset jitter===============================================================================oNMEA(0) .GPS. 0 l 37 64 377 0.0000 0.0129 0.0014
It will take a few minutes before the 'o' appears in front of the NMEA word.This 'o' means that the NTP service is receiving NMEA messages and hassynced to the PPS time pulses from the kernel.
The NTPsec package we are using for the NTP service on Linux has an optionalpackage called ntpsec-ntpviz. ntpviz reads the statistics files produced byntpsec and generates HTML pages with graphs of the ntp service performance.
To use ntpviz, you will need to install a few more packages:
sudo apt-get install gnuplot-nox ntpsec-ntpvizNote
I used gnuplot-nox here because if you don't specify this, installing thentpsec-ntpviz package will pull in the X windows versions of gnuplot,which installs the full X windows environment on the Raspberry Pi.
The ntpsec-ntpviz package will automatically configure ntpsec to write outthe required statistics files and will enable cron jobs to generate the HTMLpages. The default configuration will produce daily and weekly summaries.This package will also enable the /ntpviz path in Apache if it is installed.
The ntpsec package includes a cron job that will automatically rotate the statsfiles.
Flash storage devices have a limited number of program/erase (P/E), or write,cycles they can tolerate before wearing out. This is especially true of microSDcards. Unfortunately, most microSD manufactures do not provide a specificationfor the number of P/E cycles their device is expected to handle.
Some flash devices use write wear leveling to increase the overall life of aflash device by using extra un-used space on the device to write new databefore resorting to re-writing. Unfortunately, like the expected P/E cycles,most flash vendors do not disclose if their device has wear levelingcapabilities.
Due to this limitation of flash storage, and the lack of good data about theendurance of the microSD card, I have recommended getting an oversized "highendurance" microSD card.
Beyond that, we can take some steps to reduce the amount of wear we put onthe microSD card in our Raspberry Pi.
Linux based systems need to write data to storage on a regular basis. Thisincludes everything from logs, socket files, process ID files, and otherconfiguration data. Most of these writes occur under the /var file path, withthe highest write files typically writing to files under /var/log.
Normal logging does not produce a lot of regular writes, but the ntpviz packagewe installed above does. Reducing the Linux filesystem write wear is beyond thescope of this document, but I will provide some ideas to reduce the wear fromntpviz.
The ntpsec-ntpviz package enables the following statistics logging: loopstats,peerstats, and clockstats.Each of these can write hundreds of thousands of lines a data per day and willlater be re-written to disk in compressed form. Finally, they will be expiredout and deleted after a week. On top of this, ntpviz will rewrite the graphsand HTML content every hour.
Since this data is purely for monitoring, and does not impact the performanceof the ntp service, I would recommend storing these in RAM instead of onthe microSD flash. This means they will not persist across reboots, but theywill also not increase the wear on the flash storage. After each reboot, thegraphs will start over as if you just installed ntpsec-ntpviz.
To store these files in RAM, we need to setup these paths on tmpfs:
Configure the fstab to mount the directories on tmpfs:
echo"tmpfs /var/log/ntpsec tmpfs rw,size=5M,nodev,nosuid,noexec,uid=ntpsec,gid=ntpsec,mode=755 0 0"| sudo tee -a /etc/fstabecho"tmpfs /var/lib/ntpsec/ntpviz tmpfs rw,size=10M,nodev,nosuid,noexec,uid=root,gid=root,mode=755 0 0"| sudo tee -a /etc/fstab
Reboot to make sure all of the ntpviz processes are using the new filesystem:
sudo reboot
Optionally, you can clear out the already stored data in these directoriesbefore the reboot. Even if you do not, the old data will not be used.
By default, ntpviz will graph the temperature reading from the Raspberry Piprocessor as "ZONE0" using the "ntplogtemp" program. ntplogtemp has built insupport for pulling temperature readings from alternate sources, one of whichis using a command called "temper-poll".
The BerryGPS-IMUv3 includes a temperature sensor that is attached to theI2C bus and I have created a python script that is compatible withthe ntplogtemp use of "temper-poll" that can be used to capture the temperaturefrom the BerryGPS-IMUv3 called "get-imu-temp.py". This can be installed andsymbolic linked to the name "temper-poll" and ntplogtemp will automaticallystart using it to collect the "TEMPER0" temperature reading from theBerryGPS-IMUv3. I have found this temperature reading to be much closer to theambient temperature than the reading from the Raspberry Pi CPU.
To enable the BerryGPS-IMUv3 temperature reading:
Install the required python module:
sudo apt-get install python3-smbus
Copy the get-imu-temp.py application into /usr/local/bin:
sudo cp -p get-imu-temp/get-imu-temp.py /usr/local/bin
Link the "temper-poll" name to get-imu-temp.py:
sudo ln -s /usr/local/bin/get-imu-temp.py /usr/local/bin/temper-poll
Note
The get-imu-temp.py code expects the BerryGPS-IMUv3 I2C device tobe on I2C bus 3. This is how I configured the I2C busabove in thekernel device tree section.
After the next ntpviz daily graph run, you should see the "TEMPER0" labelappear on the "Local Frequency/Temp" daily graph produced by ntpviz. Bydefault, this runs once an hour.
You can also verify the "TEMPER0" temperature polling by looking at the/var/log/ntpsec/temps file. After about five minutes, you should see atemperature reading for "TERMER0" in addition to the "ZONE0" readings.
By default, all temperature values are in centigrade.
Note
Using a case around your Raspberry Pi and BerryGPS-IMUv3 may improve yourtemperature stability, which in turn may improve the stability of thecrystal oscillator in the u-blox CAM-M8C GNSS module as the CAM-M8C moduledoes not include a temperature compensated crystal oscillator.However, this will put more thermal stress on the components and, if theRaspberry Pi is under heavy load, the Raspberry Pi may throttle the CPU.See theRaspberry Pi frequency management and thermal controlfor more information on thermal throttling.
In general, the u-blox GNSS chips are highly configurable. This includessettings that can enhance the stability of your NTP service.
One of the nice things about u-blox is that they provide a graphical tool thatallows you to see how your u-blox module is performing and configure it. Thissoftware is called u-center. You can downloadu-center from the u-blox website for free.
The u-blox u-center software supports connecting to the u-blox module over anetwork.
To connect u-center to the Raspberry Pi, you will need to install the ser2netpackage and make sure it doesn't automatically start on boot:
sudo apt-get install ser2netsudo systemctl disable ser2net
Configure ser2net for u-center connection:
echo"6000:raw:600:/dev/ttyAMA0:9600 NONE 1STOPBIT 8DATABITS XONXOFF LOCAL -RTSCTS"| sudo tee -a /etc/ser2net.conf
If you have configured NTPsec to use the I2C interface, you do notneed to stop the NTP service to use u-center. However, if you are not using theI2C interface for NTPsec, you will need to stop NTPsec beforestarting the ser2net service:
sudo systemctl stop ntpsec
Now that you have ser2net prepared you can start the ser2net service:
sudo systemctl start ser2net
Connect the u-center application to the Raspberry Pi:
From the top menu, selectReceiver.
SelectConnection from theReceiver menu.
SelectNetwork Connection from theConnection menu.
SelectNew from theNetwork Connection menu.
In theAddress field, enter the URL to the Raspberry Pi:
tcp://<ip address>:6000
In the ser2net configuration we used port 6000, so I have indicated that inthis above example.
At this point you should see satellites populating in the satellite levelhistory window.
Once you are done using u-center, be sure to shut down ser2net as it does nothave any access control.
sudo systemctl stop ser2net
If you cannot run the u-center software, you can still build a customconfiguration using theu-blox protocol specification document.
To configure the u-blox module:
- Select theView menu.
- From theView menu, selectConfiguration View.
This will open the Configure window. It will show you the current configurationvalues on the CAM-M8C module. At the bottom of the window, there is a Pollbutton that allows you to query the module to load the current configuration.
Along the left side of the window is the list of possible configurationcategories. Not all of these categories apply to the CAM-M8C module.
On the right side of the window are the configuration settings in the selectedcategory. If you make a change to one of these settings, you must click theSend button at the bottom of the window for the configuration settings to beapplied to the module.
Note
The u-blox CAM-M8C module does not have persistent storage for theconfiguration. The configuration must be re-applied at power up.
I will explain how to set this up in theApplying u-blox Configuration Settings on Boot section.
In this section I will go over the u-center configuration categories and makerecommendations on settings that may improve the timing stability.
This section allows the configuration of the Global Navigation Satellite System(GNSS) the module will track and use for time synchronization.
- Confirm that GPS is enabled, with a minimum of 8 and maximum of 16.
- Disable the SBAS. This is recommended in theu-blox protocol specification document, Time Pulse section19.2.
- Enable Galileo with a minimum of 4 and maximum of 8.
- Confirm QZSS is enabled, with a minimum of 0 and maximum of 3. This is recommended in theu-blox protocol specification document, GNSS system configuration section 32.10.9.1.
- Confirm GLONAAS is enabled, with a minimum of 8 and a maximum of 14.
- All other GNSS systems should be disabled.
- Click theSend button at the bottom.
Note
Galileo satellites will not appear in u-center until we enabled NMEA version4.1 messages in the NMEA (NMEA Protocol) section below.
GLONASS satellites will be visible, but will not lock in and be used for upto thirty minutes because the GLONASS satellites only transmit the ephemerisinformation every thirty minutes.
Changing the GNSS settings requires a cold start of the GNSS subsystem asnoted in theu-blox protocol specification section 4.2.1. I willdiscuss how to do this in theApplying u-blox Configuration Settings onBoot section below.
This section configures which messages the u-blox module will send out whichcommunications port. The NTPsec NMEA driver only requires one of the followingmessages to synchronize the time: $GPRMC, $GPGLL, $GPGGA, or $GPZDA. Thedefault settings for the u-blox module send many additional messages used fornavigation.
We can reduce the latency of the required messages and reduce the processingpower that NTPsec will use by limiting the messages sent from the u-bloxdevice. This is optional configuration as NTPsec can successfully operate withthe default message settings.
Note
As you are configuring the messages you will see that the other u-bloxmodule interfaces are listed and may be enabled. This is ok. We will disablethe unused interfaces in thePRT (Ports) section.
If you are only using the UART interface (ttyAMA0) and want status andnavigation messages in addition to the timing messages:
- Leave the Messages defaults.
If you are only using the UART interface (ttyAMA0) and are only using theu-blox module for NTPsec:
- Select "F0-00 NMEA GxGGA" from the drop down, uncheck "UART1" On box,click theSend button at the bottom.
- Select "F0-01 NMEA GxGLL" from the drop down, uncheck "UART1" On box,click theSend button at the bottom.
- Select "F0-02 NMEA GxGSA" from the drop down, uncheck "UART1" On box,click theSend button at the bottom.
- Select "F0-03 NMEA GxGSV" from the drop down, uncheck "UART1" On box,click theSend button at the bottom.
- Select "F0-05 NMEA GxVTG" from the drop down, uncheck "UART1" On box,click theSend button at the bottom.
- Select "F0-05 NMEA GxZDA" from the drop down,check "UART1" On box,click theSend button at the bottom.
At this point you should only see $GNRMC and $GNZDA messages being outputover the UART (ttyAMA0) device.
If you have enabled the I2C device (ttyUBLX0) and would like touse the I2C device for NTPsec (Please see the I2CWarning):
- Leave all of the "UART1" settings using the defaults.
- Select "F0-00 NMEA GxGGA" from the drop down, uncheck "I2C" On box,click theSend button at the bottom.
- Select "F0-01 NMEA GxGLL" from the drop down, uncheck "I2C" On box,click theSend button at the bottom.
- Select "F0-02 NMEA GxGSA" from the drop down, uncheck "I2C" On box,click theSend button at the bottom.
- Select "F0-03 NMEA GxGSV" from the drop down, uncheck "I2C" On box,click theSend button at the bottom.
- Select "F0-05 NMEA GxVTG" from the drop down, uncheck "I2C" On box,click theSend button at the bottom.
- Select "F0-05 NMEA GxZDA" from the drop down,check "I2C" On box,click theSend button at the bottom.
At this point you should only see $GNRMC and $GNZDA messages being outputover the I2C device (ttyUBLX0) and multiple message types overthe UART (ttyAMA0) device.
This section configures how the u-blox module navigation engine interprets themeasurements.
- From the "Dynamic Model" drop down, select the "2 - Stationary" setting.
- Click theSend button at the bottom.
This is the recommended setting for timing applications in theu-blox protocol specificationdocument section 8.1.
This section configures the NMEA protocol output from the u-blox module.
- From the "NMEA Version" drop down, select "4.1".
- Click theSend button at the bottom.
This will enable the output of the Galileo satellites.
This section configures the u-blox module output interfaces.
If you are only using the UART interface (ttyAMA0):
- Select "0 - I2C' from the "Target" drop down.
- Select "none" in the "Protocol in" drop down.
- Select "none" in the "Protocol out" drop down.
- Click theSend button at the bottom.
- Select "3 - USB' from the "Target" drop down.
- Select "none" in the "Protocol in" drop down.
- Select "none" in the "Protocol out" drop down.
- Click theSend button at the bottom.
This will disable the I2C and USB interfaces on the u-blox module,leaving just the UART1 interface enabled.
If you are using both the UART (ttyAMA0) and the I2C (ttyUBLX0)interfaces:
- Select "0 - I2C' from the "Target" drop down.
- Select "none" in the "Protocol in" drop down.
- Select "1 - NMEA" in the "Protocol out" drop down.
- Click theSend button at the bottom.
- Select "3 - USB' from the "Target" drop down.
- Select "none" in the "Protocol in" drop down.
- Select "none" in the "Protocol out" drop down.
- Click theSend button at the bottom.
This will configure the I2C interface to only output NMEA messagesand will disable the USB interface. It will also leave the default settingfor the UART1 interface to support UBX and NMEA messages.
Note
This section also configures the baud rate of the UART1 interface. We willdiscuss changing the UART1 baud rate later in this section.
The speed of the I2C interface is defined by the Linux devicetree parameters. The default values provide more than enough bandwidthfor the NMEA RMC and ZDA messages.
This section configures the time pulse output on the Pulse Per Second (PPS)pin.
The only setting we need to configure here is the cable delay.
The formula to calculate the cable delay is:
D = \frac{L \cdot C}{V}
D: | Cable delay in nanoseconds |
---|---|
L: | Cable length in feet |
C: | Constant derived from velocity of light: 1.016 |
V: | Nominal velocity of propagation expressed as decimal, i.e. %66 = 0.66 |
You can find the nominal velocity of propagation from the cable datasheetprovided by the manufacturer.
For example, my cable is RG316 which has a nominal velocity of propagation of69.5.
The cable delay for my antenna is 15.16637681 ns.
- To configure your antenna cable delay:
- Calculate the cable delay in nanoseconds.
- Enter this value in the "Cable Delay" box. Using my value, I enter "15".
- Click theSend button at the bottom.
Once you have configured the module, you can save this configuration to a filethat can be used to configure the module on boot.
To save the configuration from u-center:
- From the top menu, selectTools.
- On theTools menu, selectReceiver Configuration.
- In theLoad/Save Receiver Configuration window, specify your configurationfile save location in theConfiguration File field.
- Click theTransfer GNSS -> File button to start the configuration saveprocess.
Note
There may be error messages while saving some configuration categories. Thisis ok. The failed categories do not apply to this u-blox module.
I have included a simple python3 application that will load a u-center savedconfiguration file into a u-blox module called u-blox-cfg-loader.py. We can usethis to configure the u-blox module when the Raspberry Pi boots.
Copy the u-blox-cfg-loader.py into /usr/local/bin on your Raspberry Pi:
sudo cp -p u-blox-cfg-loader.py /usr/local/bin
Copy your u-center configuration file into /etc on your Raspberry Pi:
sudo cp u-blox.cfg /etc/u-blox.cfgsudo chmod 644 /etc/u-blox.cfgsudo chown root.root /etc/u-blox.cfg
Configure udev to run the u-blox-cfg-loader.py on boot:
sudo cp udev/10.u-blox-cfg-loader.rules /etc/udev/rules.d
Run the u-blox-cfg-loader.py tool to load your configuration withoutrequiring a reboot:
sudo /usr/local/bin/u-blox-cfg-loader.py --port /dev/ttyAMA0 --file /etc/u-blox.cfg
On future reboots of the Raspberry Pi, the u-blox-cfg-loader.py will be run byudev automatically.
As mentioned above in theGNSS (GNSS Config) section note, u-blox recommendsa cold start after changing the GNSS settings. We can accomplish this bycreating another u-blox configuration file and setting up another udev rule:
echo"CFG-RST - 06 04 04 00 FF B9 02 00"| sudo tee -a /etc/u-blox-rst.cfgsudo cp udev/60-u-blox-cfg-loader-rst.rules /etc/udev/rules.d
You can configure the u-blox UART1 interface to run at a higher baud rate thanthe default of 9600. This will not improve the accuracy of the time but willreduce the chance of a transmit buffer overflow in the u-blox module if youenable additional messages on the UART1 (ttyAMA0) interface. To change thebaud rate of the UART1 interface on the u-blox module:
Append the configuration line to the u-center configuration file:
echo"CFG-PRT - 06 00 14 00 01 00 00 00 C0 08 00 00 00 C2 01 00 07 00 03 00 00 00 00 00"| sudo tee -a /etc/u-blox.cfg
Run the u-blox-cfg-loader.py tool to load your configuration withoutrequiring a reboot:
sudo /usr/local/bin/u-blox-cfg-loader.py --port /dev/ttyAMA0 --file /etc/u-blox.cfg
Update your NTPsec configuration to use 115200 baud:
sudo sed -i's/9600/115200/g' /etc/ntpsec/ntp.conf
Restart the NTPsec service:
sudo systemctl restart ntpsec
Update your ser2net configuration to use 115200 baud:
sudo sed -i's/ttyAMA0:9600/ttyAMA0:115200/g' /etc/ser2net.conf
Update the cold start udev rule:
sudo sed -i's/u-blox-rst.cfg/u-blox-rst.cfg --speed 115200/g' /etc/udev/rules.d/60-u-blox-cfg-loader-rst.rules
The Raspberry Pi includes a hardware watchdog device that can be used toreset the Raspberry Pi should the software freeze (such as a kernel panic).
Enable the watchdog hardware device:
- Edit the /boot/firmware/syscfg.txt
- Add "dtparam=watchdog=on". On reboot, this will enable the watchdogdevice.
- Edit the /boot/firmware/syscfg.txt
Install the watchdog system service:
sudo apt-get updatesudo apt-get install watchdog
Configure the watchdog service:
- Edit the /etc/watchdog.conf file
- Add "watchdog-device = /dev/watchdog". This will set the locationof the hardware watchdog device file.
- Add "watchdog-timeout = 15". This sets the time, in seconds, thehardware device will wait for an update before triggering a hardwarereset.
- Add "max-load-1 = 24". This is the one-minute load average thresholdat which the watchdog service will reboot the device. The one-minuteload average is the first "load average" number when you run the"uptime" command. Twenty-four is a large number, approximately six timesthe load a four core Raspberry Pi can normally process.
- Add "interface = eth0". This will cause the watchdog process to watchthe "eth0" network interface to make sure it is receiving traffic.
- Add "temperature-sensor = /sys/class/thermal/thermal_zone0/temp". Thisis the file where the Raspberry Pi core temperature is reported. Note,it is reported in thousandths of a degree Celsius.
- Add "max-temperature = 82". This sets the watchdog service temperaturethreshold to eighty-two degrees Celsius. This is the temperature theRaspberry Pi will start throttling the CPU.
- Add "min-memory = 25000". This sets a minimum available memory thresholdfor the watchdog process. This value is in memory pages, which is 4096on the Raspberry Pi (getconf PAGESIZE). A value of twenty-five thousandwill set a low memory threshold of one hundred megabytes of availablememory.
- Edit the /etc/watchdog.conf file
Enable the watchdog service:
sudo systemctlenable watchdog
Reboot the Raspberry Pi to enable the watchdog device:
sudo reboot
Verify the watchdog service started successfully:
sudo systemctl status watchdog| less
The output should show that the service is active (running).
The u-blox CAM-M8C module on the BerryGPS-IMUv3 provides multiple datainterfaces that allow access to the NMEA and UBX protocols. Above we configuredand used the UART interface over the Raspberry Pi hardware serial port (UART).In addition to the UART interface on the u-blox module, it also supports anI2C compatible Display Data Channel (DDC) interface and a SerialPeripheral Interface (SPI). On the CAM-M8C module, if the SPI is enabled, theUART and DDC/I2C interfaces cannot be used as they share pins on theu-blox module. Since I want to use the UART and I2C interfaces, Iwill not be discussing how to use SPI with the u-blox module.
By enabling the I2C interface and making it available to theRaspberry Pi we can have two, independent, interfaces on the u-blox module.This allows one interface to be configured to support only the messagesrequired for our NTP service, and the other can be used to monitor andconfigure the u-blox module.
Warning
Currently the ublox6-gps-i2c driver is not suitable as a source for NTPsec.There are occasional delays in producing the NMEA strings from the ttyUBLX0device that will cause NTPsec to label it as a falseticker. There areadjustments that can be made in the NTPsec configuration file to ignore thisissue, but this is not good for stability.I have also experienced issues attempting to configure the u-blox moduleover the I2C device. I recommend using the UART device for configurationand NTPsec until the driver can be fixed.
Copy over the ublox6-gps-i2c dkms directory:
sudo mkdir /usr/src/ublox6-gps-i2c-1.0sudo cp -a ublox6-gps-i2c/* /usr/src/ublox6-gps-i2c-1.0
Add the module to dkms so that it will be built for future kernel updates:
sudo dkms add -m ublox6-gps-i2c -v 1.0
Build and install the module for the current kernel:
sudo dkms install -m ublox6-gps-i2c -v 1.0
Enable the ublox6-gps-i2c kernel module for boot:
echo"ublox6-gps-i2c"| sudo tee -a /etc/modules-load.d/ublox6-gps-i2c.conf
Setup udev to enable the ublox_gps I2C driver:
sudo cp udev/10.ubox_i2c.rules /etc/udev/rules.d
Currently the driver doesn't support auto loading the I2C driverso, I am working around this by setting up a udev rule that detects thekernel module loading and tells the I2C bus there is a newdevice. Maybe in the future I will update the driver to auto load for thisi2c bus number and the u-blox I2C address. However, that would beunsafe as the u-blox module doesn't have any ID registers available to queryon the I2C bus to validate it is the device we want.
Enable the u-blox i2c device without the need to reboot:
sudo udevadm control --reloadsudo modprobe ublox6-gps-i2c
These steps happen automatically on reboot.
Optionally update NTPsec to use the I2C device:
Edit the /etc/ntpsec/ntp.d/refclock.conf file.
Change the /dev/ttyAMA0 to /dev/ttyUBLX0 on the "refclock" line.
sudo sed -i's/ttyAMA0/ttyUBLX0/g' /etc/ntpsec/ntp.d/refclock.confsudo sed -i's/ baud 9600//g' /etc/ntpsec/ntp.d/refclock.conf
Edit the /etc/apparmor.d/tunables/ntpd file.
Change the "/dev/ttyAMA0" to "/dev/ttyUBLX0" on the @{NTP_DEVICE} line.
sudo sed -i's/ttyAMA0/ttyUBLX0/g' /etc/apparmor.d/tunables/ntpd
Update the apparmor configuration:
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.ntpd
Restart the ntp service to load the new configuration:
sudo systemctl restart ntpsec
The very kind person that gifted me the BerryGPS-IMUv4 board inquired aboutsupporting u-blox Multi GNSS AssistNow to allow a quicker time-to-first-fix onstartup. I was more than happy to add support for AssistNow to this project.
After following these installation instructions, AssistNow will be used toload the almanac and ephemeris data into the u-blox module after the it isconfigured and the cold start is issued. In my testing, this dropped thetime-to-first-fix to about two minutes when I enabled all of the data typesand provided the receiver location settings.
Note
If you are adding AssistNow support to an existing installation, pleaseupdate the u-blox-cfg-loader.py file to the current version in thisrepository. I have added a delay after the cold start command to allowthe receiver to reset before we send it AssistNow data.
The u-blox Multi GNSS AssistNow Online is a free service, but it does requirea token to access the service. You can follow the instructions provided in theAssistNow getting started guide to get your free token.
Note
As the name implies, the AssistNow Online functionality requires yourRaspberry Pi to be able to make HTTPS connections to the u-blox servers.
Copy the u-blox-assistnow-loader.py into /usr/local/bin on your Raspberry Pi:
sudo cp -p u-blox-assistnow/u-blox-assistnow-loader.py /usr/local/bin
Copy the configuration file into /etc on your Raspberry Pi:
sudo cp -p u-blox-assistnow/u-blox-assistnow.conf /etc
Configure udev to run the u-blox-assistnow-loader.py on boot:
sudo cp -p udev/65-u-blox-assistnow.rules /etc/udev/rules.d
At a minimum you must configure thetoken in the u-blox-assistnow.conf file.If this is not set, the u-blox AssistNow loader will skip the AssistNow dataloading.
If you know the exact position of the receiver, you can enable the "pos"datatype and fill in the position information in the configuration file.An easy way to get an accurate location is to run the receiver for a while andonce is has established a stable location, connect to the receiver using theu-center application. Then, from theTools menu, selectAssistNow OnlineandAssistNow Online, GNSS. From theMultiple GNSS AssistNow Online windowsetReference Position toManual and click theUse Current button. Youcan then copy those values into the u-blox-assistnow.conf file.
Once you have completed these steps, on the next reboot, the u-blox module willget AssistNow data loaded and the time-to-first-fix should be reduced.
Someone was kind enough to gift me a Raspberry Pi 4 (Thank you again!). Here is what I have learned about the Raspberry Pi 4 so far:
U-boot on Ubuntu 19.10 (eoan) is broken. You cannot do the"setenv bootdelay -2" trick to stop the GPS serial port from aborting theboot sequence. This was caused by two issues: my USB keyboard is notdetected by u-boot and the saved environment file is corrupt.
I worked around the USB keyboard issue by using my Raspberry Pi 3 serial portto access the u-boot serial console on the Raspberry Pi 4.
The issue with the corrupt environment file was a bigger problem. Not onlydid it save out without my boot delay change, but it would not load at boot.I later found out there is an issue in this version with the size of theu-boot code and the environment data.
In the end, I resorted to building a custom version of u-boot that sets theautoboot delay and stop strings in u-boot. It would be super nice if Ubuntuset these by default in the u-boot-rpi package.
Download the source files by searching for the correct u-boot-rpi packageonhttps://packages.ubuntu.com. There are three files:u-boot_2019.07+dfsg-1ubuntu3.dsc, u-boot_2019.07+dfsg.orig.tar.xz, andu-boot_2019.07+dfsg-1ubuntu3.debian.tar.xz.
Unpack the u-boot_2019.07+dfsg.orig.tar.xz file:
tar xJf u-boot_2019.07+dfsg.orig.tar.xz
Go into the new u-boot-2019.07 directory and unpack the debian directory.
cd u-boot-2019.07tar xJf ../u-boot_2019.07+dfsg-1ubuntu3.debian.tar.xz
Make the required changes to enable the delay and stop strings:
echo"#define CONFIG_AUTOBOOT_KEYED">> include/configs/rpi.hecho"#define CONFIG_AUTOBOOT_DELAY_STR\"delay\"">> include/configs/rpi.hecho"#define CONFIG_AUTOBOOT_STOP_STR\"stop\"">> include/configs/rpi.h
Update the package to include a new patch file for the changes:
dpkg-source --commit
This will ask for a patch name, I used "rpi4-autoboot-strings". It will thenopen your favorite editor (vim right?) where you can put in a descriptionfor the patch. Update as you see fit since you will not be distributing it.
Build the new u-boot packages:
dpkg-buildpackage -us -uc
This will take a long time as it rebuilds all of the u-boot packages.
Install the newly built package:
sudo dpkg --install ../u-boot-rpi_2019.07+dfsg-1ubuntu3_arm64.deb
I am sad to report that the I2C bus clock stretching issue that the RaspberryPi 3 model B suffers from is still present on the Raspberry Pi 4. I willcontinue to use the software/GPIO I2C driver on the Raspberry Pi 4.
Unfortunately the Raspberry Pi 4 ethernet chip does not support IEEE 1588hardware timestamping. The ethtool output:
$ ethtool -T eth0Time stamping parametersfor eth0:Capabilities: software-transmit (SOF_TIMESTAMPING_TX_SOFTWARE) software-receive (SOF_TIMESTAMPING_RX_SOFTWARE) software-system-clock (SOF_TIMESTAMPING_SOFTWARE)PTP Hardware Clock: noneHardware Transmit Timestamp Modes: noneHardware Receive Filter Modes: none
For those of you that might be curious about the other offloading capabilityon the Raspberry Pi 4, here is default offload settings on Ubuntu 19.10:
$ ethtool -k eth0Featuresfor eth0:rx-checksumming: offtx-checksumming: off tx-checksum-ipv4: off tx-checksum-ip-generic: off [fixed] tx-checksum-ipv6: off tx-checksum-fcoe-crc: off [fixed] tx-checksum-sctp: off [fixed]scatter-gather: off tx-scatter-gather: off tx-scatter-gather-fraglist: off [fixed]tcp-segmentation-offload: off tx-tcp-segmentation: off [fixed] tx-tcp-ecn-segmentation: off [fixed] tx-tcp-mangleid-segmentation: off [fixed] tx-tcp6-segmentation: off [fixed]udp-fragmentation-offload: offgeneric-segmentation-offload: off [requested on]generic-receive-offload: onlarge-receive-offload: off [fixed]rx-vlan-offload: off [fixed]tx-vlan-offload: off [fixed]ntuple-filters: off [fixed]receive-hashing: off [fixed]highdma: off [fixed]rx-vlan-filter: off [fixed]vlan-challenged: off [fixed]tx-lockless: off [fixed]netns-local: off [fixed]tx-gso-robust: off [fixed]tx-fcoe-segmentation: off [fixed]tx-gre-segmentation: off [fixed]tx-gre-csum-segmentation: off [fixed]tx-ipxip4-segmentation: off [fixed]tx-ipxip6-segmentation: off [fixed]tx-udp_tnl-segmentation: off [fixed]tx-udp_tnl-csum-segmentation: off [fixed]tx-gso-partial: off [fixed]tx-sctp-segmentation: off [fixed]tx-esp-segmentation: off [fixed]tx-udp-segmentation: off [fixed]fcoe-mtu: off [fixed]tx-nocache-copy: offloopback: off [fixed]rx-fcs: off [fixed]rx-all: off [fixed]tx-vlan-stag-hw-insert: off [fixed]rx-vlan-stag-hw-parse: off [fixed]rx-vlan-stag-filter: off [fixed]l2-fwd-offload: off [fixed]hw-tc-offload: off [fixed]esp-hw-offload: off [fixed]esp-tx-csum-hw-offload: off [fixed]rx-udp_tunnel-port-offload: off [fixed]tls-hw-tx-offload: off [fixed]tls-hw-rx-offload: off [fixed]rx-gro-hw: off [fixed]tls-hw-record: off [fixed]
I would like to try setting this up on the Raspberry Pi 4 platform.Specifically, to see if I get additional stability out of the 4.
Beyond the Raspberry Pi 4 interests I would like to compare my results on theu-blox CAM-M8C with other u-blox modules.
U-blox ships the RCB-F9T timing board that should be fairly straight forward tointegrate with a Raspberry Pi. It includes the ZED-F9T "high accuracy timing"module. I am curious to see the stability improvement this module may bring.
There are also boards available with the ZED-F9P module which is considered a"high precision GNSS" module.
I am pretty sure that the antenna I am using now is limiting the channelsI am receiving from the GNSS systems. I think this antenna, like most currentlyavailable, filter for the L1 band fairly tightly. U-blox sells a multi-bandexternal antenna, the ANN-MB-00, that supports the L1 and L2 bands and istailored to this usecase. I would be curious to see if this also improves thestability by using multiple frequencies with different interference/noise.
If you would like to gift me hardware, I have anAmazon gift wish list available.
- Raspberry Pi is a trademark of the Raspberry Pi Foundation
- OzzMaker and BerryGPS-IMUv3 are likely marks owned by OzzMaker
- u-blox is a registered trademark of u-blox Holding AG
- Ubuntu is a registered trademark of Canonical Ltd.
- Broadcom is a registered trademark of Broadcom Inc.
- Adafruit is a registered trademark of Adafruit Industries.
- I did not get compensation from any of these companies for this project.
- This document comes without any warranty of any kind.
- Not intended for safety of life applications.
- The code provided in this repository is licensed under the GNU GeneralPublic License v3.0. See the included LICENSE for terms.
- This document is Copyright 2020-2022 Michael Johnson
- This document is licensed under the Creative Commons Attribution-ShareAlike4.0 International Public License
Create A Raspberry Pi 3 Model B and u-blox CAM-M8C GPS NTP server byMichael Johnson is licensed under aCreative Commons Attribution-ShareAlike 4.0 International License.