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

Protokół NMEA i opis wiadomości

Protokół NMEA i opis wiadomości
Protokół NMEA i opis wiadomoś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

Do

Zweryfikuj zdanie

Asystent RTK

Znajdź najlepsze produkty dla swoich potrzeb, odpowiadając na zaledwie kilka pytań.

Jeśli podobały Ci się te treści, możesz nas śledzić Twitter, YouTube, Facebook or LinkedIn aby być na bieżąco z takimi treściami.

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.