In this article by Charles Hamilton, author of the book BeagleBone Black Cookbook, we will cover location-based recipes and how to hook up GPS.
(For more resources related to this topic, see here.)
The Internet of Things is a large basketful of things. In fact, it is so large that no one can see the edges of it yet. It is an evolving and quickly expanding repo of products, concepts, fledgling business ventures, prototypes, middleware, ersatz systems, and hardware.
Some define IoT as connecting things that are not normally connected, thus making them a bit more useful than they were as unconnected devices.
We will not show you how to turn off the lights in your house using the BBB, or how to auto raise the garage door when you turn onto your street while driving. There are a bunch of tutorials that do that already. Instead, we will take a look at some of the recipes that provide some fundamental elements to build IoT-centric prototypes or use cases.
A common question in the IoT realm is where is that darn thing? That Internet of Things thing? Being able to track and pinpoint the location of a device is one of the more typical features of many IoT use cases. So, we will first take a look at a recipe on how to for use everyone's favorite location tech: GPS. Then, we will explore one of the newer innovations spun out of Bluetooth 4.0, a way to capture more precise location-based data rather than GPS using beacons.
The UART background
In the galaxy of embedded systems, developers use dozens of different serial protocols. On the more common side, consumers are familiar with things such as USB and Ethernet. Then, there are protocols familiar to engineers, such as SPI and I2C, which we have already explored in this book. For this recipe, we will use yet another flavor of serial, UART, an asynchronous or clock-less protocol. This comes in handy in a variety of scenarios to connect IoT-centric devices.
Universal asynchronous receiver/transmitter (UART) is a common circuit block used to manage serial data and hardware. As UART does not require a clock signal, it uses fewer wires and pins. In fact, UART uses only two serial wires: RX to receive packets and TX to transmit them.
The framework for this recipe comes from AdaFruit's tutorial for the RPi. However, the differences between these two boards are nontrivial, so this recipe needs quite a few more ingredients than the RPi version.
You will need the following components for this recipe:
For the GPS setup, the steps are as follows:
P9_11 (blue wire): This denotes RX on BBB and TX on GPS PCB. At first, it may seem confusing to not wire TX to TX, and so on. However, once you understand the pin's function, the logic is clear: a transmit (TX) pin pairs with a pin that can receive data (RX); a receive pin pairs with a pin that transmits data.
P9_13 (green wire): This specifies TX on BBB and RX on GPS PCB.
P9_1: This indicates GND.
P9_3: This denotes 3.3V.
When your BBB starts up, you will immediately see the Fix button on the GPS board that will begin to flash quickly, around 1x per second. We will come back to check the integrity of the module's satellite connection in a later step.
$ sudo -i
# config-pin overlay BB-UART4
# cat /sys/devices/bone_capemgr.*/slots
$ ls -l /dev/ttyO*
crw-rw---- 1 root tty 247, 0 Mar 1 20:46 /dev/ttyO0
crw-rw---T 1 root dialout 247, 4 Jul 13 02:12 /dev/ttyO4
$ dmesg
This is how the output looks:
[ 188.335168] bone-capemgr bone_capemgr.9: part_number 'BB-UART4', version 'N/A'
[ 188.335235] bone-capemgr bone_capemgr.9: slot #7: generic override
[ 188.335250] bone-capemgr bone_capemgr.9: bone: Using override eeprom data at slot 7
[ 188.335266] bone-capemgr bone_capemgr.9: slot #7: 'Override Board Name,00A0,Override Manuf,BB-UART4'
[ 188.335355] bone-capemgr bone_capemgr.9: slot #7: Requesting part number/version based 'BB-UART4-00A0.dtbo
[ 188.335370] bone-capemgr bone_capemgr.9: slot #7: Requesting firmware 'BB-UART4-00A0.dtbo' for board-name 'Override Board Name', version '00A0'
[ 188.335400] bone-capemgr bone_capemgr.9: slot #7: dtbo 'BB-UART4-00A0.dtbo' loaded; converting to live tree
[ 188.335673] bone-capemgr bone_capemgr.9: slot #7: #2 overlays
[ 188.343353] 481a8000.serial: ttyO4 at MMIO 0x481a8000 (irq = 45) is a OMAP UART4
[ 188.343792] bone-capemgr bone_capemgr.9: slot #7: Applied #2 overlays.
Tips to get a GPS fix
Your best method to get the GPS module connected is to take it outdoors. However, as that's not a likely option when you are developing a project, putting it against or even just outside a window will often suffice. If it is cloudy, and if you don't have a reasonably clear sky view from your module's antenna, do not expect a quick connection. Be patient. When a fix is made, the flashing LED will cycle very slowly at about 15-second intervals.
Even if the GPS modules do not have a fix, be aware that they will still send data. This can be confusing because you may run some of the following commands and think that your connection is fine, but you just keep getting junk (blank) data. However, to reiterate that the flashing LED has to have slowed down to 15-second intervals to confirm that you have a fix.
$ cat /dev/ttyO4
The National Marine Electronics Association uses a GPS language protocol standard.
$ sudo screen /dev/ttyO4 9600
The output should immediately begin and look something similar to this:
$GPGGA,163356.000,4044.0318,N,07400.1854,W,1,5,2.65,4.0,M,-34.2,M,,*67
$GPGSA,A,3,13,06,10,26,02,,,,,,,,2.82,2.65,0.95*04
$GPRMC,163356.000,A,4044.0318,N,07400.1854,W,2.05,68.70,031214,,,A*46
$GPVTG,68.70,T,,M,2.05,N,3.81,K,A*09
$GPGGA,163357.000,4044.0322,N,07400.1853,W,1,5,2.65,3.7,M,-34.2,M,,*68
$GPGSA,A,3,13,06,10,26,02,,,,,,,,
Press Ctrl + a, enter or copy and paste :quit with the colon to the highlighted box at the bottom, or press Ctrl + a, k, y.
Installing the GPS toolset
Perform the following steps to install the GPS toolset:
$ sudo apt-get update
$ sudo apt-get install gpsd gpsd-clients python-gps
For the preceding command, gpsd-clients installs some test clients, and python-gps installs the required Python library so that it can communicate with gpsd via Python scripts.
After the installation, you may find it useful to run gpsd and review the package's well-written and informative manual. It provides not only the details around what you just installed, but also the general GPS-related context as well.
$ sudo gpsmon /dev/ttyO4
You should see a terminal GUI that looks similar to the following screenshot:
$ sudo cgps -s
The output includes the current date and time in UTC, the latitude and longitude, and the approximate altitude.
Troubleshooting: Part 1
You may run into problems here. Commonly, on a first time set up and running, cgps may time out, close by itself, and lead you to believe that there is a problem with your setup. If so, the next steps can lead you back on the path to GPS nirvana:
$ sudo killall gpsd
$ sudo rm /var/run/gpsd.sock
There is a systemd bug that we will typically need to address. Here is how we fix it:
$ sudo nano /lib/systemd/system/gpsd.service
[Unit]
Description=GPS (Global Positioning System) Daemon
Requires=gpsd.socket
[Service]
ExecStart=/usr/sbin/gpsd -n -N /dev/ttyO4
[Install]
Also=gpsd.socket
$ sudo service gpsd start
$ sudo gpsmon /dev/ttyO4
Alternatively, you can also run the following command:
$ sudo cgps -s
Troubleshooting: Part 2
Sometimes, the preceding fixes don't fix it. Here are several more suggestions for troubleshooting purposes:
$ sudo gpsd -N -D3 -F /var/run/gpsd.sock
The explanation of the command-line flags or options are as follows:
-N: This tells gpsd to immediately post the GPS data. Although, this is useful for testing purposes, it can also be a power consumption, so leave it off if your use case is battery-powered.
-F: This creates a control socket for device addition and removal. The option requires a valid pathname on your local filesystem, which is why our command is appended with /var/run/gpsd.sock.
$ sudo apt-get install lsof
$ sudo lsof -i :2947
This is how the output should look:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
systemd 1 root 24u IPv4 6907 0t0 TCP localhost:gpsd (LISTEN)
gpsd 5960 nobody 4u IPv4 6907 0t0 TCP localhost:gpsd (LISTEN)
$ ps aux |grep gps
$ sudo killall gpsd
For a final bit of cooking with the GPS board, we want to run a Python script and display the data in tidy, parsed output. The code was originally written for the RPi, but it is useable on the BBB as well.
$ git clone https://github.com/HudsonWerks/gps-tests.git
$ cd gps-tests
$ sudo nano GPStest1.py
$ sudo nano GPStest1.py
The script requires a number of Python libraries, as shown in the following code:
import os
from gps import *
from time import *
import time
import threading
Keep in mind that getting a fix and then obtaining a good GPS data can take several moments before the system settles into a comfortable flow, as shown in the following code:
#It may take a second or two to get good data
#print gpsd.fix.latitude,', ',gpsd.fix.longitude,'
Time: ',gpsd.utc
If you find the output overwhelming, you can always modify the print commands to simplify the display as follows:
print
print ' GPS reading'
print '----------------------------------------'
print 'latitude ' , gpsd.fix.latitude
print 'longitude ' , gpsd.fix.longitude
print 'time utc ' , gpsd.utc,' + ', gpsd.fix.time
print 'altitude (m)' , gpsd.fix.altitude
print 'eps ' , gpsd.fix.eps
print 'epx ' , gpsd.fix.epx
print 'epv ' , gpsd.fix.epv
print 'ept ' , gpsd.fix.ept
print 'speed (m/s) ' , gpsd.fix.speed
print 'climb ' , gpsd.fix.climb
print 'track ' , gpsd.fix.track
print 'mode ' , gpsd.fix.mode
print
print 'sats ' , gpsd.satellites
time.sleep(5)
$ python GPStest1.py
In a few seconds, nicely formatted GPS data should be spitting out in your terminal window.
In this article we discussed how to hook up GPS in detail as one of the major features of IoT.
Further resources on this subject: