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.
Location-based recipes – hooking up GPS
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:
- GPS PCB: You can probably find cheaper versions, but we will use AdaFruit's well regarded and ubiquitous PCB (http://www.adafruit.com/product/746 at around USD $40.00).
- Antenna: Again, Adafruit's suggested SMA to the uFL adapter antenna is the simplest and cheap at USD $3.00 (https://www.adafruit.com/product/851).
- 5V power: Powering via the 5V DC in lieu of simply connecting via the mini USB is advisable. The GPS modules consume a good bit of power, a fact apparent to all of us, given how the GPS functionality is a well-known drain on our smartphones.
- Internet connectivity, either via WiFi or Ethernet
- 4x jumper wires
How to do it…
For the GPS setup, the steps are as follows:
- Insert the PCB pins into the breadboard and wire the pins according to the following fritzing diagram:
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.
- Carefully attach the antenna to the board's uFL connector.
- Now, power your BBB. Here's where it gets a bit tricky.
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.
- In order to gain access to the UART pins on the BBB, we have to enable them with a Device Tree overlay. Until recently, this was a multistep process. However, now that the BeagleBone universal I/O package comes preloaded on the current versions of the firmware, enabling the pins—in the case, UART4—is a snap. Let's begin by logging in as root with the following command:
$ sudo -i
- Then, run the relevant universal I/O command and check whether it went to the right place, as shown in the following code:
# config-pin overlay BB-UART4 # cat /sys/devices/bone_capemgr.*/slots
- Now, reboot your BBB, then check whether the device is present in the device list using the following command:
$ 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
- Finally, check whether it is loading properly with the following command:
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.
- Although the output is not pretty, the following command is a useful first step in making sure that your devices are hooked up because it will show the raw NMEA data coming out of the GPS:
$ cat /dev/ttyO4
The National Marine Electronics Association uses a GPS language protocol standard.
- Verify that your wiring is correct and that the module is generating the data properly (irrespective of a satellite fix) as follows:
$ 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,,,,,,,,
- Now quit the program using one of the the following methods:
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:
- The next set of ingredients in the recipe consists of installing and testing a common toolset to parse GPS on Linux. As always, before installing something new, it is good practice to update your repos with the following command:
$ sudo apt-get update
- Install the tools, including gpsd, a service daemon to monitor your GPS receiver. The package exposes all the data on location, course, and velocity on the TCP port 2947 of your BBB and efficiently parses the NMEA text pouring out of the GPS receiver, as shown in the following command:
$ 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.
- If the planets or communication satellites are aligned, you can run this command from the newly installed toolset and begin displaying the GPS data:
$ sudo gpsmon /dev/ttyO4
You should see a terminal GUI that looks similar to the following screenshot:
- To quit, press Ctrl + c or type q and then press return (Enter) key.
- Now, we will test the other principal tool that you just installed with the following command:
$ 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:
- We will begin by stopping all the running instances of GPS, as shown in the following code:
$ sudo killall gpsd
- Now, let's get rid of any sockets that the gpsd commands may have left behind with the following command:
$ sudo rm /var/run/gpsd.sock
There is a systemd bug that we will typically need to address. Here is how we fix it:
- Open the systemd GPSD service using the following command:
$ sudo nano /lib/systemd/system/gpsd.service
- Paste it to the window with the following script:
[Unit] Description=GPS (Global Positioning System) Daemon Requires=gpsd.socket [Service] ExecStart=/usr/sbin/gpsd -n -N /dev/ttyO4 [Install] Also=gpsd.socket
- Then, restart the systemd service as follows:
$ sudo service gpsd start
- You should now be able to run either of the following service again:
$ 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:
- Set up a control socket for GPS with the following command:
$ 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.
- We may also need to install a package that lets us examine any port conflict that could be occurring, a shown in the following code:
$ sudo apt-get install lsof
- This installed utility will open and display the system files, including disk files, named pipes, network sockets, and devices opened by all the processes. There are multiple uses for the tool. However, we only want to determine whether the GPS module is speaking correctly to port 2947 and if there are any conflicts. So, we will run the following command:
$ 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)
- You may also want to check whether any instances of the GPS are running and then kill them with the following code:
$ 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.
- Go, get it using the following command:
$ git clone https://github.com/HudsonWerks/gps-tests.git
- Now, browse to the new directory that we just created and take a look at the file that we will use with the following command:
$ cd gps-tests $ sudo nano GPStest1.py
- Then, open a new Python file and paste the following code to the window:
$ 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)
- Now, close the script and run the following command:
$ python GPStest1.py
In a few seconds, nicely formatted GPS data should be spitting out in your terminal window.
- Sparkfun's tutorial on GPS is definitely worth the read at https://learn.sparkfun.com/tutorials/gps-basics/all
- For further GPSD troubleshooting, refer to http://www.catb.org/gpsd/troubleshooting.html
In this article we discussed how to hook up GPS in detail as one of the major features of IoT.
Resources for Article:
- Learning BeagleBone Python Programming [Article]
- Learning BeagleBone [Article]
- Protecting GPG Keys in BeagleBone [Article]