NMEA 0183 and GPS: Decoding the NMEA 0183 standard in your GPS Software Project
As GPS units become more common and less expensive, a whole new set of location-aware applications and services are popping up to take advantage of its capabilities. If you are one of the thousands of software developers tasked with adding GPS capability to an application, you have probably come across the NMEA 0183 standard, the protocol by which GPS units communicate with other devices. Since decoding the NMEA 0183 standard is the key to integrating GPS data in your VB, C# or C++ project, let's examine some strategies for handling NMEA 0183 output.
The Big Picture
Before we dive into the guts of the NMEA 0183 standard, let's take a step back and examine how the NMEA 0183 data stream fits into the larger structure of our application. There are three hurdles that we must first overcome before we can begin decoding the NMEA 0183 stream and using the data in our application:
1) Getting the hardware connection right
GPS hardware connections come in three common varieties: serial port, USB, or Bluetooth. To read NMEA 0183 data from a GPS, we must make these connections look like COM ports to the PC. If the GPS connects to the PC through a serial port, we're in luck since this is already done. If we have a USB GPS, we must either install the USB drivers that came with the GPS, or purchase a USB to serial port converter. If using a Bluetooth GPS, we must install the manufacturer's driver software.
2) Reading from the COM port in your application
Now that we have the COM port set up, how can we read from it in our application? This is, without a doubt, the most challenging part of reading NMEA 0183 data. In fact, reading from a COM port in a Windows application can be so difficult that a whole cottage industry has been created around it. There are dozens of ActiveX controls and a few .NET components (including our own PortController.NET) devoted to making reading from and writing to a COM port easier. If you have some time on your hands, you can learn to read from the COM port yourself, otherwise it might be worth looking into a good, multithreaded 3rd party control.
3) GPS portability
Unfortunately, GPS manufacturers often pick and choose which parts of the NMEA 0183 standard they support. If your application only needs to read from one model of GPS, then it's not a problem, but if it must handle many different GPS types, it can complicate matters. To cope, decide which NMEA 0183 sentences you will use as your primary sources of position, speed, course, navigation, and satellite data. Then identify other sentences which contain pieces of this information and designate them as secondary sources. If the GPS you are reading from is not reporting the primary sentence, start looking for secondary sentences to get the necessary data.
Parsing the NMEA 0183 Stream
The NMEA 0183 data stream consists of a series of "sentences" delimited by a newline character. Each sentence begins with a six character identifier, the first character of which is always "$". The NMEA 0183 standard defines dozens of sentences, but only a fraction apply directly to GPS devices. The most useful sentences include:
- $GPAAM - Waypoint Arrival Alarm
- $GPBOD - Bearing, Origin to Destination
- $GPBWW - Bearing, Waypoint to Waypoint
- $GPGGA - Global Positioning System Fix Data
- $GPGLL - Geographic Position, Latitude/Longitude
- $GPGSA - GPS DOP and Active Satellites
- $GPGST - GPS Pseudorange Noise Statistics
- $GPGSV - GPS Satellites in View
- $GPHDG - Heading, Deviation & Variation
- $GPHDT - Heading, True
- $GPRMB - Recommended Minimum Navigation Information
- $GPRMC - Recommended Minimum Specific GPS/TRANSIT Data
- $GPRTE - Routes
- $GPVTG - Track Made Good and Ground Speed
- $GPWCV - Waypoint Closure Velocity
- $GPWNC - Distance, Waypoint to Waypoint
- $GPWPL - Waypoint Location
- $GPXTE - Cross-Track Error, Measured
- $GPXTR - Cross-Track Error, Dead Reckoning
- $GPZDA - UTC Date/Time and Local Time Zone Offset
- $GPZFO - UTC and Time from Origin Waypoint
- $GPZTG - UTC and Time to Destination Waypoint
(A complete reference with detailed examples can be found at Glenn Baddeley NMEA sentence information page and at Peter Bennett's GPS and NMEA site)
For the sake of simplicity, let's will assume that we are only interested in position, speed, and course data. Looking at the available NMEA 0183 sentences, we see that the $GPRMC sentence contains all the information we need. The format of the $GPRMC sentence is
$GPRMC,aaaaaa,b,cccc.cc,d,eeeee.ee,f,ggg.g,hhh.h,jjjjjj,kkk.k,l*mm
Where:
- aaaaaa is the time of the fix UTC in hhmmss format
- b is the validity of the fix ("A" = valid, "V" = invalid)
- cccc.cc is the current latitude in ddmm.mm format
- d is the latitude hemisphere ("N" = northern, "S" = southern)
- eeeee.ee is the current longitude in dddmm.mm format
- f is the longitude hemisphere ("E" = eastern, "W" = western)
- ggg.g is the speed in knots
- hhh.h is the true course in degrees
- jjjjjj is the date in DDMMYY format
- kkk.k is the magnetic variation in degrees
- l is the direction of magnetic variation ("E" = east, "W" = west)
- mm is the checksum
Getting the position, speed, and course data in which we are interested now just becomes a matter of reading the $GPRMC sentence into a string, parsing the string to extract the pertinent data, and converting the data into the proper units. But what if one particular model of GPS that we have to support does not output the $GPRMC sentence, or contains only a subset of $GPRMC data?
When reading NMEA 0183 data, it is important that the code be flexible enough to gather similar data from multiple sources. We will then examine our "secondary" sentences to piece our data together. In this case, we can find this information in the $GPGLL sentence (positional data), and the $GPVTG sentence (course and speed). You can find a full description of these sentences at the sites linked above.
Devil in the Details
So as we can see, the NMEA 0183 standard is simple and straightforward, but, as with all things, it's the details that cause the headaches. Developing an architecture to read from the COM port (without locking up the GUI, preferably), handling redundant and/or missing data, and converting between commonly used units are important elements in the design and implementation of a NMEA 0183 reader. It is far better to consider these elements early in the design process instead of trying to adapt a flawed design to handle them later.
Luckily, if you're not inclined to wrestle with these issues, GPS ToolKit.NET and GPS ToolKit ActiveX can handle all these details for you, and allow you to access position, speed, course, navigation, and satellite data through simple, straightforward properties. You can download a free 30 day trial for .NET here, or for Visual Basic 6 and Visual C++ 6 here.
Learn more about GPS ToolKit.NET
Download GPS ToolKit.NET Trial
Learn more about GPS ToolKit ActiveX
Download GPS ToolKit ActiveX Trial
评论