I am presently working on something that requires geolocation. Not knowing much about GPSes and related topics, I decided to get a USB GPS. This week, let’s have a look at how we can extract information from the USB GPS using Bash.
The first step is to locate your USB GPS as a device. If it’s NMEA compliant, it should mount automagically as a USB serial port. You would think that lsusb -v would show you the device, but it does not always. Sometimes it shows as “Brand X GPS”, sometimes it only shows as a generic device, say “MediaTek Inc.”, or even as a modem. It will typically show up as /dev/ttyUSB0 or /dev/ttyACM0.
Once you’ve ascertained the device name, you must add your user to the dialout group (on Linux, anyway) to access the devices. You do so with
sudo adduser $USER dialout
and by login-out and in again (to make the group addition propagate correctly to your environment).
The next step (now that you know the device name and that you’ve added yourself to group dialup), is to configure the baud-rate and other port parameters. To do that, we’ll use stty
stty \ -F $gps_device \ raw \ 38400 \ cs8 \ clocal \ cs8 \ -parenb \ crtscts \ -cstopb
This commands sets the device pointed by the variable $gps_device to 38400 bauds, no-handshake and 8n1 data (8 bits, no parity, one stop bit).
We can now open the device as files for reading and writing:
exec 4<$gps_device # gps read-stream exec 5>$gps_device # gps write-stream
…creating stream #4 for reading and stream #5 for writing. While one may not think of a GPS as a read/write device, it does accept configuration commands such as the frequency at which you desire the updates and what NMEA information you want. The simplest command is probably the update frequency that lets you specify the interval, in ms, at which the GPS spews out its data. It would look very much like:
# configure GPS options # # with the help of : http://www.hhhh.org/wiml/proj/nmeaxor.html # # 2000 ms = $PMTK220,2000*1C # 1500 ms = $PMTK220,1500*1A # 1000 ms = $PMTK220,1000*1F # 750 ms = $PMTK220,750*2C # 500 ms = $PMTK220,500*2B # 250 ms = $PMTK220,250*29 # 200 ms = $PMTK220,200*2C # 100 ms = $PMTK220,100*2F echo \$PMTK220,1000\*1F$'\r' >&5
The PMTK commands are reminiscent of the old AT modem commands, but with the addition of a (rather crude) check-sum at the end of each command, separated by *. The GPS will answer with a possibly negative acknowledge message to let you know if the command succeeded. The above would result in something like:
Were 001 is the type of the message, here an acknowledge message, 220 is the type of the message it answers to, and 2 or 3 before the check sum tells whether it failed or succeeded.
Pumping the data out of the GPS is rather straightforward:
while [ 1 ] do read this_line ...do more stuff... done <&4
The output should look something like
$GPGSV,3,1,12,15,69,197,26,26,63,068,25,21,46,300,23,05,38,085,23*71 $GPGSV,3,2,12,09,34,119,23,29,26,224,18,51,23,226,,18,21,275,20*74 $GPGSV,3,3,12,08,20,043,16,06,08,329,17,24,06,168,,07,02,021,*79 $GPRMC,132822.000,A,4932.1147,N,06723.2320,W,0.00,181.2,230313,,*26 $GPVTG,181.2,T,,M,0.00,N,0.0,K*5A
where the $GPGSV data tells you what satellites you are receiving signals from, and the $GPRMC is the minimal positioning data the GPS is supposed to give you to be NMEA-compliant.
In the next entry, we’ll have a look at how to parse this data with Bash