Lefebure.com / Articles / NMEA 0183 Sentences


Introduction: I've written a handful of applications that deal with GPS position data. The world standard for this data is the NMEA sentence. Here is an example of a NMEA GGA sentence:

$GPGGA,115739.00,4158.8441367,N,09147.4416929,W,4,13,0.9,255.747,M,-32.00,M,01,0000*6E

If you've never seen this before, it will look a little cryptic. However, the above characters contain a lot of useful info, and are actually somewhat human-readable if you know what you're looking at. This page is intended to help you understand the various parts of the message so that you can quickly write software to read or create NMEA sentences, and hopefully overcome problems such as corrupted or invalid data.


NEMA Sentence Structure: The first thing you need to know is that each NMEA sentence is on its own line, separated by two characters, a carriage return (ASCII 13) and a line feed (ASCII 10). If you're looking at the data stream in a terminal program such a PuTTy, you'll see this as a new line. Here is an example of multiple messages from a GPS receiver:

$GPGGA,115739.00,4158.8441367,N,09147.4416929,W,4,13,0.9,255.747,M,-32.00,M,01,0000*6E
$GPGGA,115740.00,4158.8441367,N,09147.4416924,W,4,13,0.9,255.739,M,-32.00,M,01,0000*64
$GPGGA,115741.00,4158.8441360,N,09147.4416934,W,4,13,0.9,255.738,M,-32.00,M,01,0000*62
$GPGGA,115742.00,4158.8441378,N,09147.4416932,W,4,13,0.9,255.740,M,-32.00,M,01,0000*61
$GPGGA,115743.00,4158.8441389,N,09147.4416944,W,4,13,0.9,255.739,M,-32.00,M,01,0000*61
$GPGGA,115744.00,4158.8441396,N,09147.4416939,W,4,13,0.9,255.741,M,-32.00,M,01,0000*6D
$GPGGA,115745.00,4158.8441395,N,09147.4416936,W,4,13,0.9,255.744,M,-32.00,M,01,0000*65

Any well-behaved GPS receiver will output both the carriage return and line feed characters immediately following each line. For this reason, you can usually separate lines by looking for these two characters. Below is a VB.Net code sample used to read data coming in from a serial port:

ReceiveBuffer += COMPort.ReadExisting
If InStr(ReceiveBuffer, vbCrLf) Then
    Dim lines() As String = Split(ReceiveBuffer, vbCrLf)
    For i = 0 To UBound(lines) - 1
        If lines(i).Length > 5 Then
            ParseLine(lines(i))
        End If
    Next
    ReceiveBuffer = lines(UBound(lines))
Else
    If ReceiveBuffer.Length > 4000 Then
        ReceiveBuffer = ""
    End If
End If

Data coming in from the serial port is appended to a buffer. That buffer is then checked to see if it contains any carriage return and line feed character sequences (vbCrLf). If any are found, the buffer is split into individual lines. One by one, those lines are checked to see if they are at least 5 characters long, and then sent to the ParseLines() subroutine for further processing. If any data remains after the last CrLf, it is placed back into the buffer so that future incoming data can be appended to it. The buffer is also checked to see if it is over 4000 characters long, and if so, it is cleared. NMEA messages should never be anywhere near this long, so hitting this limit means that you aren’t receiving NMEA data.


The Checksum: The next thing you'll notice is that all NMEA sentences start with a dollar sign ($) indicating the start of a message. Sentences also end with an asterisk (*) followed by two characters. Those two characters are the checksum for the message. The checksum allows you to confirm that the message is the same as when it was created, and no data corruption along the way. It is a simple method of error checking.

$GPGGA,115739.00,4158.8441367,N,09147.4416929,W,4,13,0.9,255.747,M,-32.00,M,01,0000*6E

The checksum is actually computed as a single byte of data (8 bits), but is formatted as a two-character hexadecimal so that it is valid in ASCII. If you are reading NMEA data, you will need to separate the line to get everything between the dollar sign ($) and the asterisk (*), highlighted above in green. That data needs to have the checksum calculated for it. At that point, if you’re reading the data, you can compare your computed checksum with the one at the end of the sentence. Below is a VB.Net code sample used to calculate the checksum:

Public Function CalculateChecksum(ByVal sentence As String) As String
    ' Calculates the checksum for a sentence
    ' Loop through all chars to get a checksum
    Dim Character As Char
    Dim Checksum As Integer
    For Each Character In sentence
        Select Case Character
            Case "$"
                ' Ignore the dollar sign
            Case "*"
                ' Stop processing before the asterisk
            Case Else
                ' Is this the first value for the checksum?
                If Checksum = 0 Then
                    ' Yes. Set the checksum to the value
                    Checksum = Convert.ToByte(Character)
                Else
                    ' No. XOR the checksum with this character's value
                    Checksum = Checksum Xor Convert.ToByte(Character)
                End If
        End Select
    Next
    ' Return the checksum formatted as a two-character hexadecimal
    Return Checksum.ToString("X2")
End Function
End If



The Header: As mentioned above, all messages start with a $. The next five characters indicate the type of message that follows. Of these, the first character is always the letter ‘G’.

The second character is used to describe the primary positioning system used to create the data. This will almost always be the letter ‘P’ for GPS, but I have also seen ‘L’ for GLONASS.

$GPGGA,

The next three characters define the type of sentence that follows.

$GPGGA,

Some common sentence types are:
GGA = Position, elevation, time, number of satellites used, fix type, correction age.
RMC = Position, date, time, speed, heading.
VTG = Heading, speed.
GSV = Satellites in view, their PRN number, elevation, azimuth, and signal strength.
GSA = PRNs of satellites used, Dilution of precision.


Last updated: December 10, 2013

© 2024 Lefebure.com