circuitcellar.com
Magazine Support   Digital Library   Products & Services   Suppliers Directory 
 
 





 

October 2000, Issue 123

Navigating With GPS


by Jeff Stefan

GETTING THE DATA

Most GPS receivers output data in NMEA-0183 format. NMEA stands for the National Marine Electronics Association. The data is sent via RS-232 at 4800 bps, with most GPS receivers providing a serial port that outputs NMEA GPS messages at 1-s intervals. NMEA messages are sent by talkers (identified by a two-character ID string with a "GP" prefix) and received by listeners. The messages are one-way: from talker to listener. Thus, an application program’s control of the receiver’s output is limited. Data enters your application program at 4800 bps at 1-s intervals, period. The data rate and burst time can’t be changed. This is OK for most land- and sea-based applications.

An NMEA sentence contains an address field, data field, and checksum. The address field is composed of a sentence formatter and talker identifier. The latter indicates where the data comes from. For GPS, the talker identifier is GP. Two useful GPS talker identifiers are RMC and GGA. The sentence formatter indicates the content of the data field.

NMEA messages are easy for a program to parse because they are consistent and well defined. The general NMEA message format is:

$<Address>,<Data>*<Checksum><CR><LF>

The address field, <Address>, is broken down as <talker><sentence_ formatter>. All fields are comma delimited except <Checksum>, which is delimited by a star (see Figure 2).

$<Address>,<Data>*<Checksum><CR><LF>
<Address> = <Talker><Sentence_formatter>
<Talker> = GP
<Sentence_formatter> = one of RMC GGA GSV…ZDA
Figure 2—This is the NMEA sentence format.

Table 1 lists eight examples of NMEA GPS messages. The most useful one is the RMC message, which contains all of the basic information required to build a navigation system. RMC is listed as recommended minimum specific GPS/transit data (see Figure 3). Although I don’t know what the "C" stands for in RMC, I know I like the utilitarian nature of this message. It contains time, status, position, speed, course, and date.

RMC Contains recommended minimum specific GPS/transit data
ALM Provides GPS almanac information
GLL Provides latitude, longitude, and UTC (Universal Time Coodinated) data
ZDA Contains UTC along with day, month, year, and local time
GGA Contains UTC, fix, and position data
GSA Provides GPS DOP and active satellite information
VTG Provides "track made good" and ground speed
ZDA Provides the current time and data
Table 1—These are useful GPS NMEA messages used for navigation applications.

 

                                            RMC message
$GPRMC,nnmmss.ss,A,IIII.II,a,yyyy.yy,a,x.x,x.x,xxxxxx,x.x,a*hh<CR><LF>
$GPRMC Address field
hhmmss.ss UTC of position fix (hours, minutes, seconds, decimal seconds)
A GPS status: A means data is valid, V means data is invalid
Llll.ll Latitude
a North/south
yyyy.yy Longitude
a East/west
x.x Speed over ground in knots
x.x Course over ground, degrees true
xxxxxx Date: ddmmyy (day, month, year)
x.x Magnetic variation
a East/west
*hh<CR><LF> Checksum
Figure 3—Here’s the NMEA RMC message format, followed by definitions.


Looking at the RMC message, the first chunk of data encountered is $GPRMC. As the NMEA sentence describes, this is the talker and sentence formatter. Universal Time Coordinated UTC data follows the sentence formatter; the time is given in hours, minutes, seconds, and decimal seconds. Next is the GPS status indicator (A), which indicates whether or not the incoming GPS data is valid. The V in this field seems to indicate that the data is valid, however, it means the opposite. An A in this field means that the data is indeed valid.

There are many reasons why a GPS receiver would output invalid data. For example, the receiver might not have acquired enough satellites for a position fix yet, foliage or buildings might block the GPS signals, or the GPS almanac or ephemeris data could be out of date. Invalid data output from a receiver is almost always temporary, and a V usually will become an A within seconds or minutes.

The next two fields cover latitude and determine whether the latitude is in the Northern or Southern Hemisphere. Following the latitude fields are the corresponding longitude and east/west indicators. The two fields after that, speed (knots) over ground and course (degrees) over ground, are handy. Next is the date, and then the magnetic variation (east or west).

The RMC message is available on almost all receivers that output NMEA messages. As stated, GPS receivers supporting NMEA messages output data at 1-s intervals at 4800 bps, so processing data at 1200- to 1800-ms intervals ensures enough time to fill up a receiver buffer and transfer the data to a holding buffer. The data in the holding buffer can be parsed and processed while new information enters the receive buffer.

Listing 1 shows a C structure into which you can deposit the parsed RMC message data. The [#defines] identify character array lengths and are optional. The structure contains the proper data types to contain the RMC data fields. You can create similar structures for additional NMEA messages that an application needs.

#define STRING10 10
#define STRING7  7

struct rmc
{
	char UTC[STRING10];
	char Status;
	double Lat; 
	char NS;
	double Lon;
	char EW;
	double Speed;
	int Course; 
	char Date[STRING7];
	char Var[STRING10];
};
Listing 1—Here’s the structure that holds parsed RMC messages.

After the GPS receiver deposits data in a buffer named InputQueue[], the data is transferred to another buffer called InputMsgBuff[]. The latter is used to extract the RMC or other NMEA messages of interest. To extract the data, create a pointer and have it point to InputQueue[]. For transferring data, you need to de-reference the pointer to Input- MsgBuff[]. This is illustrated in the C code fragment in Listing 2.

unsigned char *locptr;  	// local buffer pointer
int i = 0;                 // array index 
/***************************************
* Transfer InputQueue data to InputMsgBuff[]
***************************************/
locptr = InputQueue;
/***************************************
* Check for NMEA message start character ‘$’.
* If ‘$’ is found, transfer message to InputMsgBuf.
****************************************/
if (*locptr == ‘$’)
{
   while (*locptr != ‘\0’)
    {
        InputMsgBuff[i++] = *locptr;
     }
  InputMsgBuff[i] = ‘\0’;
}
Listing 2—This code transfers an NMEA message from a raw input queue to a message processing buffer.

When a message is in a buffer, the talker and sentence formatter can be identified and processed. This bit of code collects a sequence of messages so multiple messages can be processed. This allows you to create custom structures, spanning the data from multiple messages. For example, a structure can be created that holds speed, course, latitude, longitude, the number of satellites in view, and dilution of precision values.