Updating GPSD
Home Page Up ACARS decoder ADS-B dump1090 AIS receiver Cross-compiling Kernel compile Monitoring NTP Wall Clock Updating GPSD

 

Updating GPSD for Galileo

Background

Having recently purchased a couple of GPS modules from Uputronics which were capable of Galileo operation, I wanted to use these modules to see how they worked in a domestic environment using Raspberry Pi cards.  This needs version 3.20 of the gpsd package, but at the time of writing (May-2020) the current release of Raspbian only provides 3.17.  3.20 includes an improved cgps program which includes a better indication of the satellites in use making it easier to see whether the hardware has actually found the satellites!  By default, the units I have are activated for just GPS and GLONASS, and require the Galileo to be activated after each power-cycle (although a few hours large capacitor backup is provided).

I've provided notes on using the Raspberry Pi 4B, a Raspberry Pi 1B, running as a service, some Linux commands, and the hardware I've used.

Hardware

My interest in this dates back some time to the first operational availability of Galileo data.  I've long been a fan of the professionally made Uputronics GPS modules, so I was delighted to find that a ready-made general purpose unit was available in addition to the HAT device already offered for the full-size Raspberry Pi.  This unit is applicable to a wider range of devices that just the Raspberry Pi.  Here it is, together with the HAT version.  For Galileo operation you need the breakout as that us supplied with the MAX-M8Q-0-10 module.

uBLOX MAX-M8Q-0-10 Breakout for Active Antennas

uBLOX MAX-M8Q Raspberry Pi+ GPS Expansion Board

 

The only issue I found with these devices to use Galileo was that as supplied by U-Blox they come with GPS and GLONASS configured, so you're using just two of the three available satellite constellations.  So each time the devices are powered up you need to send a command to enable the Galileo mode should you want the extra satellites.  It's easy with gpsd 3.20 as it includes a "ubxtool" command, and I'll mention that later.  Yes, you can also send that command with gpsd 3.17, but you have to work out the u-blox command yourself, and code it in hex.  "ubxtool -e GALILEO" is somewhat easier and less error-prone!

I also had the chance to try the Pico module, which swaps the capacitor backup and SMA socket for a built-in chip antenna.  Here it is, together with my test lash-up.

         

This uses the u-blox MAX-M8C-0-10 device, which basically offers the same facilities in a more compact unit, although there is no 1 PPS timepulse output.  Having the unamplified chip antenna means that the device is much less sensitive indoors.  I tried to improve the signal level by clamping the unit to an insulated copper-clad board with the black band you can see in the photo, but that didn't seem to improve things.  Eventually I go the unit just poking out of the window on an extension lead but this made testing rather awkward.  As with the breakout, you need you need to send a command to enable Galileo. 

  

Raspberry Pi 4 B

The Buster OS includes gpsd 3.17, and back ports are available of 3.20, so the steps required are to tell APT that an update is available in the backports resource, and install that version.  These steps are detailed in http://marksrpicluster.blogspot.com/2019/12/add-buster-backports-to-raspberry-pi.html

  • sudo nano /etc/apt/sources.list
  • Add at the end
  • deb http://deb.debian.org/debian buster-backports main

A couple of keys are required:

  • sudo wget -qO - 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x04EE7237B7D453EC' | sudo apt-key add -
  • sudo wget -qO - 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x648ACFD622F3D138' | sudo apt-key add -

Now simply update the software, but tell the install to use the backports:

  • sudo apt update
  • sudo apt-get install -t buster-backports gpsd gpsd-clients python-gps

You can use "cgps -s" to check what satellite constellations are in use - this shot from a unit indoors upstairs nearer to the centre of the room:

You should then be able to tell the gps hardware to enable Galileo with the ubxtool (included in gpsd), using -d for disable or -e for enable and see the difference almost immediately in the cgps display.

  • ubxtool -e GALILEO

Another screen-shot, this time from a downstairs unit with the antenna on the floor right in the corner of the room.  This is the version I built from the source and it shows greater precision in the QTH locator grid square, and although a similar number of satellites is visible there are fewer used.  I don't know why, but perhaps lower SNR reduces the number used?  This might also account for the greater errors in lat/lon etc.  I don't know what the (18) after the time means!

Still to be resolved, getting gpsd to start automatically.
  


Raspberry Pi 1 B

Unfortunately the same approach cannot be used for the Raspberry Pi model 1 B.  Why would you want to use such an old RasPi?  Well, if it works and has all the hardware connections in place - why not!  This particular RasPi has environmental sensors in place (well, pressure temperature and humidity, (enviromental is the more modern term!) so "if it works, leave it".

Building from source

When I tried the backports approach it became clear that there were incompatibilities, possibly due to the backport not being tested (or even designed) for the ARMv6 instruction set.  Gary E Miller suggested compiling from the master source instead.  This turned into a very long saga, so let's just post what actually worked, what snags and work-rounds I used, and a few new-to-me Linux commands I needed.

I used the information here: https://gpsd.gitlab.io/gpsd/installation.html

For Buster, it was necessary to install some required software, and I installed the minimum as I don't need X capability nor the documentation on that particular RasPi.  What is critical is to remove any existing gpsd:

  • sudo apt remove gpsd
  • sudo apt purge gpsd

Having done that I did still find some lurking gps files in /local/bin (or elsewhere) so I zapped them as well.

  • sudo rm /local/bin/*gps*

Doubtless there would be a cleaner way to do this but after many days of struggling it seems to be not unwise.  The next step would have been a complete re-install anyway!  Having done that, install the minimum required tools:

  • sudo apt-get update
  • sudo apt-get dist-upgrade
  • sudo reboot
  • sudo apt-get install scons libncurses-dev python-dev pps-tools
  • sudo apt-get install git-core
  • sudo apt-get install build-essential manpages-dev pkg-config

Then find a directory to place the downloaded source files - I chose /Home/pi/gpsd, so I ran the command:

Now I deviated from the documented procedure here as it implied running two steps as sudo.  When I did this, one of the steps gave a privilege error.  So instead I ran the first step as a normal user (compiling the programs) and the install step with priviilege:

  • scons --config=force
  • sudo scons install

After that a test program (in /home/pi/) would not compile, as the required shared object wasn't available.  The install procedure hadn't copied it to the required system location.  Moving my program into the pi/gpsd directory fixed that one I discovered the -L (upper case) link option in gcc.  So something like:

  • gcc myprog.c -L/home/pi/gpsd -lgps -o myprog

I was disappointed that the "install" hadn't already done this.  On trying to run the program, it couldn't find the libgps.so which it needed, so I had to copy the .so file from my gpsd directory into /usr/local/lib and create some llinks:

pi@raspi-3:~ $ ls -l /usr/local/lib/libgps.so*
lrwxrwxrwx 1 root root 16 May 27 13:27 /usr/local/lib/libgps.so.27 -> libgps.so.27.0.0
-rwxr-xr-x 1 root root 116856 May 27 12:00 /usr/local/lib/libgps.so.27.0.0

Likely an "apt-get install" would have made a better job!

At this point, my program worked, so I stopped [for the time being].

 

Raspberry Pi 4 B - 64-bit OS

At the end of May-2020, a beta of the 64-bit Raspberry Pi OS was released.  This basically works just the same way as the 32-bit version, so here are some very condensed notes:

  • Test first with Uputronics HAT
    • install NTP and configure for PPS (22) clock driver (127.127.22.0)
    • raspi-config: for access to the serial ports
    • sudo apt-get install minicom
    • minicom -b 9600 -o -D /dev/ttyS0 (note different device)
    • sudo apt-get install pps-tools libcap-dev libssl-dev
    • sudo nano /boot/config.txt
      • add dtoverlay=pps-gpio,gpiopin=18
      • add dtoverlay=pi3-miniuart-bt (makes the Primary UART available as AMA0 instead)
    • sudo nano /etc/modules Add pps-gpio
    • sudo reboot
    • check: lsmod | grep pps; dmesg | grep pps; sudo ppstest /dev/pps0
    • ntpq -pn shows kPPS working and running
  • Now that works, do NOT install gpsd, but build from source
    • sudo su (enter superuser mode)
    • apt-get install scons libncurses-dev python-dev pps-tools
    • apt-get install git-core
    • apt-get install build-essential manpages-dev pkg-config - (many already installed)
    • git clone https://gitlab.com/gpsd/gpsd.git
    • cd gpsd
    • scons --config=force && scons install
    • exit (out of superuser mode)
    • sudo sudo gpsd /dev/ttyAMA0 -n -F /var/run/gpsd.sock
    • cgps and ubxtool work OK
  • Compile the program:
    • use user-compiled gps header in gpsd directory
    • gcc gpsGetSatellites.c -o gpsGetSatellites -Lgpsd -lgps
  • Run program cannot find libgps.so.27
    • sudo cp gpsd/libgps.so.27.0.0 /usr/local/lib
    • sudo ldconfig /usr/local/lib/libgps.so.27.0.0
    • all now OK!
       
       

MODEM changes

Note that the Raspberry Pi 3 and 4 have changes so that the PL011 UART0 is set for Bluetooth, and the miniUART is set for the "primary" GPIO pins 14/15.  This is undesirable as the mini UART has a variable baud rate according to the CPU speed!  You can change this by adding a line to /boot/config.txt which allocated the miniUART to the Bluetooth and the better PL011 UART to the GPIO pins.  In devices:

/dev/serial0  is the primary UART - GPIO pins
/dev/serial1  is the secondary UART (Bluetooth)

/dev/ttyS0  is the miniUART
/dev/AMA0  is the first PL011 (UART0)

The connection is by symbolic links:

As supplied, by default:

pi@RasPi-23:~ $ ls -l /dev/ser*
lrwxrwxrwx 1 root root 5 May 31 11:21 /dev/serial0 -> ttyS0
lrwxrwxrwx 1 root root 7 May 31 11:21 /dev/serial1 -> ttyAMA0
Edit: sudo nano /boot/config.txt, add: dtoverlay=pi3-miniuart-bt

and then:

pi@RasPi-23:~ $ ls -l /dev/ser*
lrwxrwxrwx 1 root root 7 Jun 1 08:56 /dev/serial0 -> ttyAMA0
lrwxrwxrwx 1 root root 5 Jun 1 08:56 /dev/serial1 -> ttyS0

Be aware of this in the notes above.  This is better explained here: https://www.raspberrypi.org/documentation/configuration/uart.md
 

Running as a service

Base on notes from Charles Curley, many thanks!  Paul Theodoropoulos commented that he prefer to have the option variables left in the gpsd.service file and set the values in /etc/default/gpsd file instead, as per the normal practice.

Check if there is already a service running:

pi@RasPi-23:~ $ sudo systemctl status gpsd.service

If it reports "Unit gpsd.service could not be found" then check in /etc/systemd/system for a gpsd.service file. if there's not one there, there is an example one in the download from GIT at ~/gpsd/systemd/gpsd.service (if you're using the directory structure from the previous paragraphs).  This is a somewhat generic file, with the options and device for gpsd not complete.

Charles Curley comments: Using /etc/default/gpsd (debian) or /etc/sysconfig/gpsd (redhat) to set options lets folks who are accustomed to the SysV init on those two environments retain their old habit.  I have no problem with moving the environmental variables into service.gpsd.
Having done that, you can probably get rid of the two EnvironmentFile=- lines in [Service]. That's one less file to parse during startup.

The gpsd.service file, along with the other two, must be copied to /etc/systemd/system, and you can check with the "ls -l" command:

pi@RasPi-23:~/gpsd/systemd $ sudo cp gpsd* /etc/systemd/system
pi@RasPi-23:~ $ ls -l /etc/systemd/system/gps*
-rw-r--r-- 1 root root 452 Jun  6 18:37 /etc/systemd/system/gpsdctl@.service
-rw-r--r-- 1 root root 356 Jun  6 18:52 /etc/systemd/system/gpsd.service
-rw-r--r-- 1 root root 362 Jun  6 18:37 /etc/systemd/system/gpsd.socket

I'm unsure about the times here, but I think that 18:37 may be the time I ran the commands below, and 18:52 may be when I rebooted the RPi just to ensure that the service started at boot time.  Once you've copied the file, you may need to edit the line in /etc/systemd/system/gpsd.service to point to your choice of options and device.  I changed:

[Service]
Type=forking
EnvironmentFile=-/etc/default/gpsd
EnvironmentFile=-/etc/sysconfig/gpsd
ExecStart=/usr/local/sbin/gpsd $GPSD_OPTIONS $OPTIONS $DEVICES

to:

[Service]
Type=forking
ExecStart=/usr/local/sbin/gpsd /dev/ttyAMA0 -n -F /var/run/gpsd.sock

You then need to run commands to enable and run the gpsd service, and to check the service status:

sudo systemctl enable gpsd
sudo systemctl start gpsd
sudo systemctl status gpsd

I got:

* gpsd.service - GPS (Global Positioning System) Daemon
Loaded: loaded (/etc/systemd/system/gpsd.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2020-06-06 18:54:08 BST; 15h ago
Process: 358 ExecStart=/usr/local/sbin/gpsd /dev/ttyAMA0 -n -F /var/run/gpsd.sock (code=exited, status=0/SUCCESS)
Main PID: 383 (gpsd)
Tasks: 2 (limit: 4249)
CGroup: /system.slice/gpsd.service
`-383 /usr/local/sbin/gpsd /dev/ttyAMA0 -n -F /var/run/gpsd.sock

Jun 06 18:54:08 RasPi-23 systemd[1]: Starting GPS (Global Positioning System) Daemon...
Jun 06 18:54:08 RasPi-23 systemd[1]: Started GPS (Global Positioning System) Daemon.

You can also use the usual "sudo service gpsd stop"  and "sudo service gpsd start" commands to control the service.

Here are some sample files.  When using a different version (3.17) I found that the executable daemon was in /usr/local/sbin/ rather than /usr/local/sbin/ so I simply copied the file (with sudo, of course).  Note that you would also need sudo to edit or create the examples below.

Sample files from /etc/systemd/system/
gpsd.service
[Unit]
Description=GPS (Global Positioning System) Daemon
Requires=gpsd.socket
# Needed with chrony SOCK refclock
After=chronyd.service

[Service]
Type=forking
EnvironmentFile=-/etc/default/gpsd
EnvironmentFile=-/etc/sysconfig/gpsd
ExecStart=/usr/local/sbin/gpsd /dev/ttyAMA0 -n -F /var/run/gpsd.sock

[Install]
WantedBy=multi-user.target
Also=gpsd.socket
gpsd.socket
[Unit]
Description=GPS (Global Positioning System) Daemon Sockets

[Socket]
ListenStream=/var/run/gpsd.sock
ListenStream=[::1]:2947
ListenStream=127.0.0.1:2947
# To allow gpsd remote access, start gpsd with the -G option and
# uncomment the next two lines:
# ListenStream=[::1]:2947
# ListenStream=0.0.0.0:2947
SocketMode=0600

[Install]
WantedBy=sockets.target
gpsd@.service
[Unit]
Description=Manage %I for GPS daemon
Requires=gpsd.socket
BindsTo=dev-%i.device
After=dev-%i.device

[Service]
Type=oneshot
Environment="GPSD_SOCKET=/var/run/gpsd.sock"
EnvironmentFile=-/etc/default/gpsd
EnvironmentFile=-/etc/sysconfig/gpsd
RemainAfterExit=yes
ExecStart=/bin/sh -c "[ \"$USBAUTO\" = true ] && /usr/local/sbin/gpsdctl add /dev/%I || :"
ExecStop=/bin/sh -c "[ \"$USBAUTO\" = true ] && /usr/local/sbin/gpsdctl remove /dev/%I || :"

 

Some Linux commands that likely you already know!

Finding files, starting at "/" with a 
given name including wildcards

pi@raspi-3:~ $ sudo find / -name "libgps*so*"
/usr/local/lib/libgps.so.27.0.0
/usr/local/lib/libgpsdpacket.so.27.0.0
/usr/local/lib/libgpsdpacket.so.27
/usr/local/lib/libgps.so.27
/usr/local/lib/libgpsdpacket.so
/home/pi/gpsd/libgps.so.27.0.0
/home/pi/gpsd/libgpsdpacket.so.27.0.0
/home/pi/gpsd/libgps_sock.o
/home/pi/gpsd/libgpsdpacket.so.27
/home/pi/gpsd/libgps.so.27
/home/pi/gpsd/libgps_json.c
/home/pi/gpsd/libgps_sock.c
/home/pi/gpsd/libgps_json.os
/home/pi/gpsd/libgps_json.o
/home/pi/gpsd/libgps_sock.os
/home/pi/gpsd/libgpsdpacket.so
/home/pi/gpsd/libgps.so

Checking a file type  
Are these two compatible?  

pi@raspi-3:~/gpsd $ sudo file /bin/tar
/bin/tar: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV),
dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux
3.2.0, BuildID[sha1]=53533d506171c559ad7c50eecf27e585e511040f, stripped

pi@raspi-3:~/gpsd $ file /usr/local/lib/libgps.so.27.0.0
/usr/local/lib/libgps.so.27.0.0: ELF 32-bit LSB pie executable, ARM, EABI5
version 1 (SYSV), dynamically linked,
BuildID[sha1]=758c80d49b842ca7a3581ba7f47b5fc16674ed90, stripped

Finding what packages are 
installed, e.g. GPIO  

pi@raspi-3:~ $ dpkg -l | grep gpio
ii python-rpi.gpio 0.7.0~buster-1 armhf Python GPIO module for Raspberry Pi

Find the Raspberry Pi clock rate in
two different ways.

 

pi@raspi-3:~ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
600000   (result in kHz)

pi@raspi-3:~ vcgencmd measure_clock arm
frequency(48)=600169920  (result in Hz)
  

To check if systemd is holding the port
required for gpsd.  Look for 1/init.

pi@raspi-3:~ sudo netstat -apn | fgrep 2947
tcp      0    0 127.0.0.1:2947      0.0.0.0:*    LISTEN      1/init
tcp6     0    0 ::1:2947            :::*         LISTEN      1/init

 

Thanks to ......

  • Anthony Stirk
  • Martin Burnicki
  • Gary E. Miller
  • Paul Theodoropoulos
  • Bryan Christianson
  • Per Westermark
  • Charles Curley
  • A. Dumas

and others I've forgotten!

 
Copyright © David Taylor, Edinburgh   Last modified: 2020 Jun 18 at 15:24