gps – intro

Programming

gps – intro

For very little reason, I decided to try out some basic gps programing.

Another user over on the Pyra handheld forums asked about using latitude and longitude data from the Pyra’s built in gps to fetch the weather using wego (a project written in Go).

Knowing nothing about the Pyra’s gps (in fact, very little about gps in general), I decided to have a crack at responding. Some cursory research indicated that most gps units communicated using a standard called NMEA 0183. The Pyra’s gps is (very likely) no different.

Lets first have a look at what the nmea sentences look like. Lacking real hardware to test, the below was created using an online nmea sentence generator. I’ve saved it as a plain text file called somewhere.nmea

$ less somewhere.nmea
$GPGSV,3,1,12,02,05,320,17,03,52,091,20,06,45,299,18,09,58,230,22*7F
$GPGSV,3,2,12,17,17,237,26,19,25,262,20,22,30,102,17,23,84,094,18*7D
$GPGSV,3,3,12,31,09,033,19,01,14,156,,07,05,181,,26,02,070,*74
$GLGSV,3,1,09,86,46,240,28,87,31,320,25,71,66,323,23,72,23,272,17*65
$GLGSV,3,2,09,70,40,059,,73,15,130,,80,32,071,,79,08,011,*69
$GLGSV,3,3,09,85,10,191,*59
$GPGGA,174045.0,4800.870320,N,01135.288585,E,1,06,1.2,595.8,M,47.0,M,,*56
$GNGNS,174045.0,4800.870320,N,01135.288585,E,AA,10,1.2,595.8,47.0,,*65
$GPVTG,165.1,T,165.1,M,0.0,N,0.0,K,A*23
$GPRMC,174045.0,A,4800.870320,N,01135.288585,E,0.0,165.1,240818,0.0,E,A*0C
$GPGSA,A,2,03,06,09,17,19,31,,,,,,,1.4,1.2,0.8*3D
$GNGSA,A,2,03,06,09,17,19,31,,,,,,,1.4,1.2,0.8*23
$GNGSA,A,2,71,72,86,87,,,,,,,,,1.4,1.2,0.8*21
$GPGGA,174045.0,4800.870320,N,01135.288585,E,1,06,1.2,595.8,M,47.0,M,,*56

Each sentence starts with a $ and ends with a * followed by a hexadecimal checksum. Each sentence contains a list of comma separated values. Check out this for a description of the different types of nmea sentences.

The first value of every sentence is the sentence ‘type’. For our use case (finding our latitude and longitude), we are going to use the GGA sentence type (although there are others we could use)

We could use grep witht the -m1 option to find the first sentence which contains $GPGGA. Alternatively, we could just use awk, the second command prints the first sentence which contains $GPGGA. I’ll stick with awk because to keep everything in one script. The third command takes it further, specifying a field delimiter of , and printing the third and fifth values in the sentence (the latitude and longitude)

$ grep -m1 '$GPGGA' somewhere.nmea
$GPGGA,174045.0,4800.870320,N,01135.288585,E,1,06,1.2,595.8,M,47.0,M,,*56

$ awk '/$GPGGA/ {print; exit;}' somewhere.nmea
$GPGGA,174045.0,4800.870320,N,01135.288585,E,1,06,1.2,595.8,M,47.0,M,,*56

$ awk -F, '/$GPGGA/ {print $3 $5; exit;}' somewhere.nmea
4800.870320 1135.288585

Great, we have our latitude and longitude. But there’s a problem. Review the sentence definition for GGA. The latitude and longitude we extracted are in the format ddmm.mmmm, we have to do some additional processing. To stop this turning into an unreadable one liner, lets create an awk script named latlon.awk.

$ which awk
/usr/bin/awk
$ vim latlon.awk #!/usr/bin/awk -f BEGIN { FS="," } { if($1 == "$GPGGA"){ lat=($4 == "S" ? -1 : 1) * (int($3 / 100) + ($3 % 100) / 60); lon=($6 == "W" ? -1 : 1) * (int($5 / 100) + ($5 % 100) / 60); print lat "," lon; exit; //Only match the first GGA sentence, then exit } }

$ chmod +x latlon.awk

$ ./latlon.awk somewhere.nmea
48.0232,11.94

$ ./latlon.awk | wego

Consider our latitude of 4800.870320 in the format ddmm.mmmm. The degrees part is extracted by dividing by 100 and truncating the results as an integer; (int(4800.870320 / 100)) = 48. The minutes are then calculated by taking the modulo division by 100 and dividing by 60; (4800.870320 % 100) / 60 = 0.0232. The final result is the addition of these two numbers. If the northing/southing is equal to south, we multiply by -1.

Our complete awk script can extract the latitude and longitude from a file containing the $GPGGA nmea sentence.

If you installed and configured wego according to the instructions on its github page, the last command should tell you the current weather at our fake latitude and longitude.

Nice one.

Next time, we’ll use an Arduino and a ublox gps module to code with real gps hardware.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.