STFN

Set up GPSD with U-blox7 GPS Dongle on Linux

10 minutes

If you are in hurry and want to skip my ponderings and jump straight to the solution, le click here.

The fix was tested on a Raspberry Pi running astrobbery.io, a Linux Mint PC and a Manjaro laptop. Worked fine in all cases.

Background

I bought a small and cheap GPS/GLONASS USB dongle called U-blox7. I got it mostly to tinker with GPS data, but also to use in my astrophotography rig as a way to get location, and most of all, time from GPS satellites.

Why time? Because one of my astroberry devices, Astrolink 4 Pi does not have a RTC clock, and so “forgets” the time everytime it’s turned off. And when I am using it out in the open field without internet access getting the time from ntp is not possible. Knowing the current time is needed to provide correct FITS header data to astrophotography images, which in turn allows easier plate solving, not to mention simplifing going throught the history of captures.

Happy that it finally arrived in the mail, I jumped in front of my PC, went throught the GPS for Linux docs, and installed gpsd, the GPS managing Linux daemon, and gpsd-clients, a set of clients taking data from gpsd and presenting it in a useful manner:

sudo apt install gpsd
sudo apt install gpsd-clients

…and it did not work.

Problem

My GPS device was not found by gpsd. gpsd was reporting no devices when monitored by cgps:

When running cgps I got an empty table, and among the logs there was an ominous

{"class":"DEVICES","devices":[]}

Cause

A quick browse of the intertubes suggested checking if the device is actually registered by the OS. By using dmesg I found out that the usb dongle was registered by the system as /dev/ttyACM0, while all gpsd docs mention dev/ttyUSB0 as the default device. That seemed to be the cause of the issue.

dmesg output:

[ 7225.765450] usb 1-3: new full-speed USB device number 2 using xhci_hcd
[ 7226.007961] usb 1-3: New USB device found, idVendor=1546, idProduct=01a7, bcdDevice= 1.00
[ 7226.007968] usb 1-3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 7226.007970] usb 1-3: Product: u-blox 7 - GPS/GNSS Receiver
[ 7226.007971] usb 1-3: Manufacturer: u-blox AG - www.u-blox.com
[ 7226.031755] cdc_acm 1-3:1.0: ttyACM0: USB ACM device

Solution: configuring gpsd for the right device

One way to fix it is to stop the gpsd instance that started with the boot of system, and run a new one with the correct device.

Killing all gpsd processes:

sudo systemctl stop gpsd
sudo systemctl stop gpsd.socket
sudo rm /var/run/gpsd.sock 

Starting gpsd manually, in the foreground and with debug ON:

sudo gpsd -D 5 -N /dev/ttyACM0

gpsd should now run fine and healthy. Open cgps in a different tab, and it should report a device and start collecting data from it. If not, continue to the next step:

Solving the permissions problem

It is possible that even after selecting the correct device, gpsd will still not be able to use it. This is caused by the service not having the permissions to access the /dev/ttyACM0 device. The solution is to add yourself, meaning your user, to the dialout group, which has access rights to tty devices:

sudo usermod -a -G dialout $USER

After running the command above, try again with running gpsd in the foreground. gpsd should now use the correct device and be able to access it. Once you know it works fine, ctrl+c out of the gpsd running in the foreground and run gpsd as a deamon in the background:

sudo gpsd /dev/ttyACM0

Fixing the service

Once gpsd is running fine, the next step is fix the daemon config file, so that is starts on boot already with the correct device.

To see how the service is started, I checked /lib/systemd/system/gpsd.service.

In my case, it looked like this:

[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
ExecStart=/usr/sbin/gpsd $GPSD_OPTIONS $DEVICES

[Install]
WantedBy=multi-user.target
Also=gpsd.socket

The ExecStart line shows that the service is started with the devices taken from an environmental variable. That variable is taken from the EnvironmentFile line above.

Opening that file, I saw

# Devices gpsd should collect to at boot time.
# They need to be read/writeable, either by user gpsd or the group dialout.
DEVICES=""

# Other options you want to pass to gpsd
GPSD_OPTIONS=""

I changed it to

# Devices gpsd should collect to at boot time.
# They need to be read/writeable, either by user gpsd or the group dialout.
DEVICES=/dev/ttyACM0

# Other options you want to pass to gpsd
GPSD_OPTIONS=""

Now it was only a matter of restarting the services

sudo systemctl restart gpsd
sudo systemctl restart gpsd.socket

And it works! cgps reports the correct device, even after restarting the whole system.

Using GPSD in KStars and EKOS

To use gpsd in EKOS, fist you need to install the indi_gpsd driver. I used the instructions from indilib.org, here’s a tl;dr version:

sudo add-apt-repository ppa:mutlaqja/ppa
sudo apt-get update
sudo apt-get install indi-gpsd

Now in EKOS gear configuration view you can select GPSD under the Aux dropdown. When you start the profile for the first time, you will be asked if you want to get the system time from the GPS service. Click yes and you are done!

If you would like to help fund my future projects, please consider to