NMEA 0183 Decoder
Parse NMEA 0183 sentences into labeled fields with checksum check.
| # | Field | Value |
|---|---|---|
| 1 | UTC time | 123519 |
| 2 | Latitude | 4807.038 |
| 3 | N/S | N |
| 4 | Longitude | 01131.000 |
| 5 | E/W | E |
| 6 | Fix quality (0=invalid, 1=GPS, 2=DGPS) | 1 |
| 7 | Satellites in use | 08 |
| 8 | HDOP | 0.9 |
| 9 | Altitude | 545.4 |
| 10 | Altitude unit | M |
| 11 | Geoid separation | 46.9 |
| 12 | Separation unit | M |
| 13 | DGPS age | — |
| 14 | DGPS station id | — |
This tool decodes an NMEA 0183 sentence into a labeled field table: talker and type up top, checksum verdict, then every field with its meaning for the common types (GGA, RMC, GLL, VTG, GSA) or numbered fields for anything else. Paste a line straight from your serial capture and see what the receiver is actually saying.
How it works
NMEA 0183 sentences are printable ASCII: $TTSSS,field1,field2,…*HH, where TT is the talker (GP = GPS, GN = multi-constellation), SSS the sentence type, and HH an XOR checksum over everything between $ and *. Field positions are fixed per sentence type, so decoding is a split on commas plus a lookup table of meanings — which is exactly what this tool applies, after verifying the checksum so you know the line survived the serial link intact.
Worked example
→ GP / GGA · checksum VALID (0x47)
→ UTC 12:35:19 · lat 48°07.038′N · lon 011°31.000′E
→ fix quality 1 (GPS) · 8 satellites · HDOP 0.9 · alt 545.4 M
Writing a parser that survives real receivers
The format is simple; the failure modes are all in the assumptions. Four rules cover most of what breaks hand-written NMEA parsers.
Match the type, not the talker. The first two letters of the address are the constellation — GP for GPS, GL for GLONASS, GA for Galileo, GN for a combined fix. A parser that hard-matches $GPGGA stops working the day a multi-constellation module starts emitting $GNGGA, which is the default on modern receivers. Match the last three letters and keep the talker as data.
Empty fields are normal, not errors. Before a fix, a receiver sends the sentence anyway with the position fields blank: $GPGGA,,,,,,0,00,,,M,,M,,*66 is a valid sentence that means "no fix yet". Code that doesparseFloat on every field without checking for empty strings turns start-up into NaN.
The coordinate field is not a decimal number.ddmm.mmmm has to be split at the minutes boundary — degrees are the digits before the last two integer digits, the rest is minutes to divide by 60. Reading 3733.9900 as 37.339900° puts the fix in the wrong place by about 25 km, and nothing warns you.
Field counts vary by revision. Later NMEA revisions appended fields — RMC grew a mode indicator, then a navigation status. Parse positionally from the front and tolerate extra fields at the end rather than requiring an exact count.
Feeding NMEA into LabVIEW or a PLC
NMEA is plain ASCII on a serial port, so any environment that can read lines can consume it — the work is always the same three steps: frame on $…CR/LF, verify the checksum, split on commas. In LabVIEW that is a serial read wired to a string subset/scan pattern; on a PLC it is a string instruction block. The two places implementations go wrong are the coordinate conversion above and dropped partial lines at start-up — always resynchronise on the next $ rather than assuming the buffer starts at a sentence boundary.
To test a consumer without a live receiver, the companion generator on this site builds valid sentences — including the no-fix and southern-hemisphere cases a bench receiver rarely produces on demand.
Parameters
| Parameter | Value | Notes |
|---|---|---|
| Structure | $address,fields*HH | ASCII, CR LF terminated |
| Talker | GP · GN · GL · P (proprietary)… | |
| Labeled types | GGA · RMC · GLL · VTG · GSA | |
| Checksum | XOR between $ and * | |
| Coordinates | ddmm.mmmm + hemisphere | degrees·minutes packed |
Python implementation
# Minimal NMEA field split with checksum verification
def parse_nmea(line: str):
body, _, cs = line.strip().lstrip("$").rpartition("*")
computed = 0
for ch in body:
computed ^= ord(ch)
fields = body.split(",")
return fields[0], fields[1:], computed == int(cs, 16)
addr, fields, ok = parse_nmea(
"$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47")
assert addr == "GPGGA" and ok and fields[0] == "123519"FAQ
▸Which sentence types get labeled fields?
GGA (fix data), RMC (recommended minimum), GLL (position), VTG (course/speed) and GSA (DOP and satellites) — the types that carry most of the information engineers actually read. Anything else, including proprietary $P… sentences, decodes generically with numbered fields.
▸How do I read the latitude field 4807.038?
NMEA packs degrees and minutes together: ddmm.mmmm. 4807.038 means 48° 07.038′ — to get decimal degrees, 48 + 7.038/60 = 48.1173°. The hemisphere letter in the following field (N/S) sets the sign.
▸What does fix quality 0/1/2 mean in a GGA sentence?
0 = no valid fix, 1 = standard GNSS fix, 2 = differential (DGPS) fix. Higher values exist for RTK modes on capable receivers. Combined with the satellites-in-use and HDOP fields, this is the quick health check of a receiver.
▸Why are some fields empty?
NMEA leaves a field's position in place but empty when the receiver has no value — two adjacent commas. Empty DGPS age or altitude fields are normal on receivers without those features; the decoder shows them as dashes.
▸Is my data uploaded?
No. Decoding runs locally in your browser.