I’ve been experimenting with a Raspberry Pi B v3, which has an onboard bluetooth radio. I’ve been interested in using GPS (or more correctly, GNSS) radio receivers with the Raspberry Pi for a while now, but the price of development platforms for the Raspberry Pi is quite high. I dug out a bluetooth GPS receiver from a box of old electronics, and found it surprisingly easy to connect to. I think I’m still going to have to invest in a proper development board at some point because the bluetooth GPS lacks a pulse-per-second (PPS) output with I’d like to use to build a stratum-1 NTP server, but for now, here’s how I got the GPS working:
Connecting to the Bluetooth Device
The program bluetoothctl can be used to control the bluetooth radio on the Pi. To connect to a bluetooth device, follow these steps:
- use the command bluetoothctl at the CLI. This opens the program. Try the command help to see a list of possible commands.
- power on
- scan on – find and note the target mac address from the list
- agent on
- error message? Try:
- select YO:UR:MA:CA:DD:RE:SS:00
- agent on
- error message? Try:
- pair DE:VI:CE:MA:CA:DD:RE:SS & enter code if required
- trust DE:VI:CE:MA:CA:DD:RE:SS (if you want to skip confirming trust in future)
- exit (to exit)
Connecting to the Bluetooth Serial Interface
We use the program RFCOMM to connect to the bluetooth serial interface. First, load it with the command “sudo modprobe rfcomm”. Now connect (or “bind”) the GPS receiver to the RFCOMM “device” using “rfcomm bind rfcomm0 DE:VI:CE:MA:CA:DD:RE:SS”. Note that the connection will only be initialised when a program attempts to open the RFCOMM device.
Checking the State of the NMEA Messages
Most GPS units will communicate using messages sent in ASCII over a serial data connection. The format is standardised with the NMEA0183 specification, with compliance highly variable! Most receivers have the same serial communications settings – 4800 baud 8N1 (that is, data bits=8, parity=none, stop bits=1, handshake=none). You can use Minicom in Unix-like system (or PuTTY in Windows) to view the messages as they arrive. On the Raspberry Pi, you could use minicom – or you could skip directly to GPSD to probe the messages sent by the GPS.
To use minicom, you need to install it (sudo apt-get install minicom) and then open the configuration menu (minicom -s). Select “configure serial port” and give it the NMEA standard settings above. Set the serial device to “/dev/rfcomm0”. Save the setup as the default, exit, and start the program (minicom). You should see the messages as they come in! Remember to exit it’s the intuitive (!) CTRL+A then X.
You might also use GPSD, a program designed to utilise GPS devices in a number of ways. One of the best things about GPSD is that it automatically detects and configures the connections, so you don’t have to tell it what kind of serial connection you need or what messages to expect. It does need to know to look for the bluetooth connection though, so…
- Install using “sudo apt-get install gpsd gpsd-clients python-gps” (ok, there’s some extra bits there for later…)
- a bit of housekeeping to avoid some conflicts in manually run instances (sudo systemctl stop gpsd.socket, then sudo systemctl disable gpsd.socket)
- sudo gpsd /dev/rfcomm0 -F /var/run/gpsd.sock to connect the rfcomm0 device to the GPSD socket, and
- gpsmon to open the program that both parses the position data and displays the messages as they arrive.
What do these messages mean? I won’t go through them all, not least because the specification is not freely available, but also because there are all sorts of different messages. A bit of Google-fu might be required if you see something unusual, although the document IEC 61162-1 is very closely derived from NMEA0183 and you may have easier access to this document. A GPS unit will output a number of lines, cycling through them; for example, mine outputs a RMC, VTG, GGA, GSA x5 times over, then GSV spread over four lines then repeat.
- RMC contains the “minimum recommended data for GPS”
- VTG contains “velocity made good” speed and heading information,
- GGA contains essential fix data including quality indicators
- GSA contains GPS dilution of precision and information on satellites in use
- GSV contains information on the satellites that could be in use based on available data – this is often spread over multiple lines
$GPGGA,161229.487,3723.2475,N,12158.3416,W,1,07,1.0,9.0,M, , , ,0000*18
- $ defines the beginning of the message
- GP is the “talker ID” and identifies the type of unit that is sending the message. This is sometimes programmable, but is always two letters, most commonly GP for generic GPS
- GGA defines the type of message the follows – this is always three letters. Here, GGA means the message is a “Global Positioning System Fix Data” message. This defines what the following commas separated values are:
- 161229.487 is the UTC time in hhmmss.sss format
- 3723.2475 is the latitude in decimal degrees, in the format ddmm.mmmm
- N refers the hemisphere of the latitude, north or south
- 12158.3416 is the longitude in the same format as the latitude
- W is the hemisphere of the longitiude, east or west
- 1 defines whether the signal is valid and whether it is from a standard or differential fix
- 07 is the number of satellites used to calculate the fix
- 1.0 is the horizontal dilution of precision – or the accuracy in the x and y plane
- 9.0 is the altitude above mean sea level
- M is the units (here, meters) of the altitude above mean sea level
- the next three fields are blank, as they refer to parameters for differential fixes
- 0000 is a null value as it refers to a parameter for differential fixes
- * defines the end of the message
- 18 is a checksum for error-checking the previous message, and may or may not be present
There are messages that give detail of the number of satellites present and their status, on timing signals, or the various dilution of precision in all planes. The protocol defines messages for all kinds of other equipment, like depth sondes, radar and inertial motion units.