Kenneth M. Cruikshank
Decode NMEA GPS Sentences

Kenneth M. Cruikshank
Decode NMEA GPS Sentences

Many sensor packages send information out as a serial stream. This stream makes up text sentences that may need to be decoded. Perhaps the most ubiquitous is the NMEA Sentence from a GPS unit. This code shows some techniques for dealing with these sentences, using standard C-functions (not all Arduino platforms support all the std::String object functions).

Introduction

Many devices we connect to an Arduino send data via the serial lines. These can be read using the Serial.Read() function. The result is a string which we may then have to parse (i.e., split up into subsets), and convert these subsets from a string representations of numbers to actual binary number types (int, float, etc.). After that we can use them in whatever computations we need.

C/C++ have both null-terminated character arrays for strings, and C++ has the String object, although the Arduino C++ String objects do not appear to support all the member functions on all Arduino platforms. For this reason I have chosen to work with the C-style character arrays, and use the regular C-string functions in <string.h>. Many of these functions are possible security loopholes, so if you can use the String objects on your platform, you should probably use them.

There are three main functions we use, The first is the string copy, or strcpy() function. This is needed because some of the functions we use "destroy" the original string, so we work with a copy so that each time through the loop() function everything will work. The second function is strtok(). This splits the string up into tokens (or substrings) based on one or more delimiters (e.g., a "," or tab). The third set of functions converts a string to a number: atoi() for integers and atof() for floating-point.

The final aspect of the decoding process is converting the number to a more useful form. In the case of the GPS strings, the geographic position is given in dddmm.mmm, so once we have it as a floating-point number, we may want to break it into two numbers, one for integer degrees (ddd) and the other for decimal minutes (mm.mmm). For this we make use of computer rounding with the floor() function which forces rounding-down. From these two numbers we can calculate the position in decimal degrees (1 degree = 60 minutes, and 1 minute = 60 seconds).

Sample Code

This sample code decodes GPS NMEA strings for position. Details on NMEA strings can be found at: https://en.wikipedia.org/wiki/NMEA_0183. The position function then passes the position to a function that determines the magnetic declination at that location. The magnetic declination routine is very crude, and only designed to work in the western US (and even then it is not going to be very accurate). It is essentially a lookup-table based on position -- it is here to show a simple technique for table lookups with 2D data (a teaching moment rather than producing production code). This function can (should) be replaced with a more sophisticated function. A more complete discussion of calculating the magnetic declination can be found at http://www.ngdc.noaa.gov/IAGA/vmod/igrf.html

 

Geology Department
http://www.pdx.edu/geology

Copyright © 1994-2015 · K.M. Cruikshank ·
http://geomechanics.research.pdx.edu