Ажурирање (16.): Имамо доста залиха свих наших производа, пронађите нас и у    Како добити понуду

NMEA протокол и опис поруке

Преглед садржаја

A протокол је скуп правила који дефинише како се подаци форматирају, преносе и интерпретирају између два или више уређаја како би се могли међусобно разумети.

Замислите то као језик са строгим граматичким правилима — и пошиљалац и прималац морају да се придржавају потпуно истих правила, иначе је порука бесмислена. Без протокола, сваки произвођач би измислио свој формат и уређаји различитих брендова не би могли да комуницирају једни са другима.

NMEA-0183 протокол (од сада NMEA) је индустријски стандард за GNSS технологију.
Ову страницу смо припремили као референцу за дефиницију NMEA протокола и да бисмо пружили опис најпопуларнијих порука. Ако пропустите неку поруку или пронађете неку грешку у куцању, контактирајте нас и ми ћемо то поправити 🙂

Poruka Opis Доступност
ГГАПодаци о фиксирању глобалног позиционог система — положај, надморска висина, квалитет фиксирања и број сателитаСви примачи
ГЛЛГеографски положај — географска ширина и дужина са временом и статусомСви примачи
ГНСПодаци о фиксирању ГНСС-а — слични ГГА-у, али подржавају више констелација (ГПС, ГЛОНАСС, Galileo...)Сви примачи
ГРСГНСС резидуали домета — резидуали домета коришћени у навигационом решењуСви примачи
ГСАГНСС DOP и активни сателити — тип фиксирања (2Д/3Д) и коришћени сателитиСви примачи
GSTСтатистика грешака GNSS псеудорајзи — процене грешака позиције (RMS, географска ширина, географска дужина, надморска висина)Сви примачи
ГСВГНСС сателити у видљивом положају — број, елевација, азимут и јачина сигнала видљивих сателитаСви примачи
ХДТПрави смер — стварни смер пловила у односу на прави северSeptentrio Mosaic-H simpleRTK3B Heading
ИНСПВАКСАПодаци сензорске фузије — интегрисана позиција, брзина, став и њихове процењене грешкеUnicore УМКСНУМКС simpleRTK3B Fusion
PUBX,00Подаци о позицији — географска ширина, дужина, надморска висина и квалитет фиксирања (u-blox уређаји)Sve u-blox пријемници
PUBX,04Време дана — UTC време и подаци о сату (u-blox уређаји)Sve u-blox пријемници
РМЦПрепоручени минимални специфични GNSS подаци — позиција, брзина, курс и датумСви примачи
ЦРВЕНАБрзина окрета — брзина ротације пловила у степенима у минутиSeptentrio Mosaic-H simpleRTK3B Heading
ВТГКурс у односу на тло и брзина у односу на тло — путања и брзина у чворовима и км/хСви примачи
садВреме и датум — UTC време, дан, месец, година и локална временска зонаСви примачи
Nema rezultata.

Структура NMEA поруке

Свака порука почиње са $ знак праћен кратким кодом који идентификује врсту података које садржи (видети табелу у следећем одељку).
Пријемник затим попуњава сва поља са подацима одвојена зарезима — географску ширину, дужину, надморску висину, време, број сателита итд. — и завршава поруку са цхецкум, што је мали број који омогућава пријемном уређају да провери да ли су подаци оштећени током преноса.
Порука се завршава преломом реда, а следећа порука почиње одмах након тога.

Слика испод сумира како се генерише NMEA порука.

Структура NMEA поруке – инфографика преузета из u-blox документација

Генерисање NMEA контролне суме

Примери кода за генерисање NMEA контролне суме на основу 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)
				
			

NMEA валидација контролне суме

Ако желите да проверите да ли је NMEA порука легитимна или не, користите пример кода испод:

				
					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"
				
			

Онлајн калкулатор NMEA контролне суме

$ *--

Контролни збир (хекс)

--

Контролни збир (децимални)

--

Дужина носивости

--

Пуна реченица

-

Провери реченицу

Имате питања или захтеве?
Контактирајте нас! Одговорићемо <24 сата!

Икона
Контакт ArduSimple
близу
ArduSimple – високопрецизна RTK опрема за геодетска снимања и решења поједностављена

Желите да сазнате више о ГПС-у и РТК-у?

Ако сте тренутно заузети, наши инжењери вам могу послати 3 кратка имејла, објашњавајући све што треба да знате да бисте започели свој пројекат.