Aktualizacja (16 / 06 / 2026): Posiadamy duży zapas wszystkich naszych produktów, znajdziesz nas również w oraz    Jak uzyskać wycenę

Protokół NMEA i opis wiadomości

Spis treści

A protokół jest zbiorem reguł definiujących sposób formatowania, przesyłania i interpretowania danych pomiędzy dwoma lub większą liczbą urządzeń, tak aby mogły się one wzajemnie rozumieć.

Wyobraźmy to sobie jak język o ścisłych regułach gramatycznych – zarówno nadawca, jak i odbiorca muszą przestrzegać dokładnie tych samych zasad, w przeciwnym razie wiadomość jest pozbawiona sensu. Bez protokołów każdy producent wymyśliłby własny format, a urządzenia różnych marek nie mogłyby się ze sobą komunikować.

Protokół NMEA-0183 (od teraz NMEA) jest standardem branżowym dla technologii GNSS.
Przygotowaliśmy tę stronę jako źródło informacji o definicji protokołu NMEA oraz opis najpopularniejszych komunikatów. Jeśli przegapisz któryś komunikat lub znajdziesz literówkę, skontaktuj się z nami i naprawimy to 🙂

Treść wiadomości OPIS Dostępność:
GGADane GPS — pozycja, wysokość, jakość ustalenia pozycji i liczba satelitówWszystkie odbiorniki
GLLPołożenie geograficzne — szerokość i długość geograficzna wraz z czasem i statusemWszystkie odbiorniki
GNSDane GNSS Fix — podobne do GGA, ale obsługujące wiele konstelacji (GPS, GLONASS, Galileo...)Wszystkie odbiorniki
GRSResztki zasięgu GNSS — resztki zasięgów używanych w rozwiązaniu nawigacyjnymWszystkie odbiorniki
GSAGNSS DOP i aktywne satelity — typ stały (2D/3D) i używane satelityWszystkie odbiorniki
GSTStatystyki błędów pseudopomarańczowych GNSS — szacunki błędów położenia (RMS, szerokość geograficzna, długość geograficzna, wysokość)Wszystkie odbiorniki
GSVSatelity GNSS w zasięgu wzroku — liczba, wysokość, azymut i siła sygnału widocznych satelitówWszystkie odbiorniki
HDTKurs rzeczywisty — rzeczywisty kurs statku względem prawdziwej północySeptentrio Mosaic-H simpleRTK3B Heading
INSPVAXADane z Sensor Fusion — zintegrowane położenie, prędkość, postawa i ich szacowane błędyUnicore UM981 simpleRTK3B Fusion
PUBX,00Dane o położeniu — szerokość geograficzna, długość geograficzna, wysokość i jakość ustalenia pozycji (u-blox urządzenia)Wszystkie produkty u-blox odbiorniki
PUBX,04Pora dnia — czas UTC i dane zegarowe (u-blox urządzenia)Wszystkie produkty u-blox odbiorniki
PKMZalecane minimalne dane GNSS — pozycja, prędkość, kurs i dataWszystkie odbiorniki
REDPrędkość obrotu — prędkość obrotu statku w stopniach na minutęSeptentrio Mosaic-H simpleRTK3B Heading
VTGKurs nad ziemią i prędkość względem ziemi — tor i prędkość w węzłach i km/hWszystkie odbiorniki
USACzas i data — czas UTC, dzień, miesiąc, rok i lokalna strefa czasowaWszystkie odbiorniki
Nie znaleziono wyników.

Struktura wiadomości NMEA

Każda wiadomość zaczyna się od $ znak, po którym następuje krótki kod identyfikujący typ zawartych w nim danych (patrz tabela w następnej sekcji).
Następnie odbiorca wypełnia wszystkie pola danych oddzielone przecinkami — szerokość geograficzna, długość geograficzna, wysokość, czas, liczbę satelitów itd. — i kończy wiadomość suma kontrolna, która jest niewielką liczbą umożliwiającą urządzeniu odbiorczemu sprawdzenie, czy dane nie zostały uszkodzone podczas transmisji.
Wiadomość kończy się podziałem wiersza, a następna wiadomość zaczyna się zaraz po nim.

Poniższy rysunek przedstawia sposób generowania komunikatu NMEA.

Struktura komunikatu NMEA – infografika wyodrębniona z u-blox dokumentacja

Generowanie sumy kontrolnej NMEA

Przykłady kodu generującego sumę kontrolną NMEA na podstawie ładunku NMEA:

    
     def nmea_checksum(payload):
    checksum = 0
    for char in payload:
        checksum ^= ord(char)
    return f"{checksum:02X}"
    
# Pass only the part between $ and *
print(nmea_checksum("GNGGA,092725.00,4717.11399,N,00833.91986,E,1,08,1.01,499.6,M,48.0,M,,"))
# Returns: '4E' (or whatever the correct checksum is)
    
   

Walidacja sumy kontrolnej NMEA

Jeśli chcesz sprawdzić, czy komunikat NMEA jest prawdziwy, skorzystaj z poniższego przykładowego kodu:

    
     def validate_nmea(sentence):
    sentence = sentence.strip()
    if not sentence.startswith('$') or '*' not in sentence:
        return False
    
    payload, claimed = sentence[1:].split('*', 1)
    
    checksum = 0
    for char in payload:
        checksum ^= ord(char)
    
    return f"{checksum:02X}" == claimed.strip()[:2].upper()
    
print(validate_nmea("$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A"))  # True
print(validate_nmea("$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*FF"))  # False
print(validate_nmea("invalid sentence"))  # False
    
   
    
     #include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>

bool validate_nmea(const char *sentence) {
    if (!sentence || *sentence != '$') return false;

    const char *star = strchr(sentence, '*');
    if (!star || strlen(star) < 3) return false;

    uint8_t checksum = 0;
    const char *p = sentence + 1;
    while (p != star) {
        checksum ^= (uint8_t)*p++;
    }

    uint8_t claimed;
    if (sscanf(star + 1, "%2hhX", &claimed) != 1) return false;

    return checksum == claimed;
}

int main() {
    printf("%d\n", validate_nmea("$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A")); // 1
    printf("%d\n", validate_nmea("$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*FF")); // 0
    printf("%d\n", validate_nmea(NULL));  // 0
    printf("%d\n", validate_nmea("invalid")); // 0
    return 0;
}
    
   
    
     function validateNmea(sentence) {
    sentence = sentence.trim();
    if (!sentence.startsWith('$') || !sentence.includes('*')) return false;

    const starIdx = sentence.indexOf('*');
    const payload = sentence.slice(1, starIdx);
    const claimed = sentence.slice(starIdx + 1, starIdx + 3).toUpperCase();

    if (claimed.length < 2 || !/^[0-9A-F]{2}$/.test(claimed)) return false;

    let checksum = 0;
    for (let i = 0; i < payload.length; i++) {
        checksum ^= payload.charCodeAt(i);
    }

    return checksum.toString(16).toUpperCase().padStart(2, '0') === claimed;
}

validateNmea("$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A"); // true
validateNmea("$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*FF"); // false
validateNmea("invalid"); // false
    
   
    
     #include <stdint.h>
#include <string.h>
#include <stdio.h>

uint8_t nmea_checksum(const char *sentence) {
    // Skip leading '$' if present
    if (*sentence == '$') sentence++;
    
    uint8_t checksum = 0;
    while (*sentence && *sentence != '*') {
        checksum ^= (uint8_t)*sentence++;
    }
    return checksum;
}

int main() {
    const char *sentence = "$GNGGA,092725.00,4717.11399,N,00833.91986,E,1,08,1.01,499.6,M,48.0,M,,";
    printf("Checksum: %02X\n", nmea_checksum(sentence));
    return 0;
}
    
   
    
     function nmeaChecksum(sentence) {
    // Strip leading $ and everything from * onwards
    sentence = sentence.replace(/^\$/, '').split('*')[0];
    
    let checksum = 0;
    for (let i = 0; i < sentence.length; i++) {
        checksum ^= sentence.charCodeAt(i);
    }
    return checksum.toString(16).toUpperCase().padStart(2, '0');
}

nmeaChecksum("GNGGA,092725.00,4717.11399,N,00833.91986,E,1,08,1.01,499.6,M,48.0,M,,");
// Returns: "4E"
    
   

Kalkulator sum kontrolnych NMEA online

$ *--

Suma kontrolna (szesnastkowa)

--

Suma kontrolna (dziesiętna)

--

Długość ładunku

--

Pełne zdanie

-

Zweryfikuj zdanie

Masz pytania lub prośby?
Skontaktuj się z nami! Odpowiemy <24 godziny!

Ikona
Kontakt ArduSimple
Zamknij
ArduSimple – sprzęt i rozwiązania do pomiarów RTK o wysokiej precyzji w prosty sposób

Chcesz dowiedzieć się więcej o GPS i RTK?

Jeśli jesteś w tej chwili zajęty, nasi inżynierowie mogą wysłać Ci 3 krótkie wiadomości e-mail, w których wyjaśnią wszystko, co musisz wiedzieć, aby rozpocząć swój projekt.