Ažuriranje (12.): Imamo dosta zaliha svih naših proizvoda, pronađite nas i ovdje i    Kako dobiti ponudu

NMEA protokol i opis poruke

Sadržaj

A protokol je skup pravila koji definira kako se podaci formatiraju, prenose i interpretiraju između dva ili više uređaja kako bi se mogli međusobno razumjeti.

Zamislite to kao jezik sa strogim gramatičkim pravilima - i pošiljatelj i primatelj moraju slijediti potpuno ista pravila, inače je poruka besmislena. Bez protokola, svaki bi proizvođač izmislio vlastiti format i uređaji različitih marki ne bi mogli međusobno komunicirati.

NMEA-0183 protokol (od sada NMEA) je industrijski standard za GNSS tehnologiju.
Ovu stranicu smo pripremili kao referencu za definiciju NMEA protokola i kako bismo pružili opis najpopularnijih poruka. Ako propustite neku poruku ili pronađete tipografsku grešku, kontaktirajte nas i popravit ćemo to 🙂

Poruka Opis Dostupnost
GGAPodaci o fiksaciji globalnog pozicijskog sustava — položaj, nadmorska visina, kvaliteta fiksacije i broj satelitaSvi primatelji
GLLGeografski položaj — zemljopisna širina i dužina s vremenom i statusomSvi primatelji
GPSPodaci o fiksaciji GNSS-a — slični GGA-u, ali podržavaju više konstelacija (GPS, GLONASS, Galileo...)Svi primatelji
GR proširenjeOstaci dometa GNSS-a — ostaci dometa korištenih u navigacijskom rješenjuSvi primatelji
GSAGNSS DOP i aktivni sateliti — vrsta fiksacije (2D/3D) i korišteni satelitiSvi primatelji
GSTStatistika pogreške pseudo-udaljenosti GNSS-a — procjene pogreške položaja (RMS, zemljopisna širina, zemljopisna dužina, nadmorska visina)Svi primatelji
GSVGNSS sateliti u vidnom polju — broj, elevacija, azimut i jačina signala vidljivih satelitaSvi primatelji
HDTPravi smjer — stvarni smjer plovila u odnosu na pravi sjeverSeptentrio Mosaic-H simpleRTK3B Heading
INSPVAXAPodaci fuzije senzora — integrirani položaj, brzina, stav i njihove procijenjene pogreškeUnicore UM981 simpleRTK3B Fusion
PUBX,00Podaci o položaju — zemljopisna širina, dužina, nadmorska visina i kvaliteta fiksne lokacije (u-blox uređaji)Svi u-blox prijemnici
PUBX,04Vrijeme dana — UTC vrijeme i podaci o satu (u-blox uređaji)Svi u-blox prijemnici
RMCPreporučeni minimalni specifični GNSS podaci — položaj, brzina, kurs i datumSvi primatelji
REDBrzina okretanja - brzina rotacije plovila u stupnjevima u minutiSeptentrio Mosaic-H simpleRTK3B Heading
VTGKurs u odnosu na tlo i brzina u odnosu na tlo — putanja i brzina u čvorovima i km/hSvi primatelji
SADVrijeme i datum — UTC vrijeme, dan, mjesec, godina i lokalna vremenska zonaSvi primatelji
Nisu pronađeni rezultati.

Struktura NMEA poruke

Svaka poruka počinje s $ znak nakon kojeg slijedi kratki kod koji identificira vrstu podataka koje sadrži (vidi tablicu u sljedećem odjeljku).
Primatelj zatim ispunjava sva podatkovna polja odvojena zarezima - zemljopisnu širinu, dužinu, nadmorsku visinu, vrijeme, broj satelita itd. - i završava poruku s Kontrolni zbroj, što je mali broj koji omogućuje prijemnom uređaju da provjeri jesu li podaci oštećeni tijekom prijenosa.
Poruka završava prijelomom retka, a sljedeća poruka počinje odmah nakon toga.

Donja slika sažima kako se generira NMEA poruka.

Struktura NMEA poruke – infografika preuzeta iz u-blox dokumentacija

Generiranje NMEA kontrolnog zbroja

Primjeri koda za generiranje NMEA kontrolnog zbroja na temelju NMEA korisnog tereta:

    
     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)
    
   

Validacija NMEA kontrolnog zbroja

Ako želite provjeriti je li NMEA poruka legitimna ili ne, upotrijebite primjer koda u nastavku:

    
     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"
    
   

Online kalkulator NMEA kontrolne sume

$ *--

Kontrolni zbroj (hex)

--

Kontrolni zbroj (decimalni)

--

Duljina korisnog tereta

--

Puna rečenica

-

Provjerite rečenicu

Imate pitanja ili zahtjeva?
Kontaktirajte nas! Odgovaramo <24 sata!

Ikona
Kontakt ArduSimple
Zatvori
ArduSimple – visokoprecizna RTK geodetska oprema i rješenja na jednostavan način

Želite li saznati više o GPS-u i RTK-u?

Ako ste trenutno zauzeti, naši inženjeri vam mogu poslati 3 kratka e-maila u kojima će objasniti sve što trebate znati za početak projekta.