Protokol NMEA dan deskripsi pesan
Daftar Isi
A protokol adalah seperangkat aturan yang mendefinisikan bagaimana data diformat, ditransmisikan, dan diinterpretasikan antara dua perangkat atau lebih sehingga mereka dapat saling memahami.
Bayangkan seperti sebuah bahasa dengan aturan tata bahasa yang ketat — baik pengirim maupun penerima harus mengikuti aturan yang sama persis, jika tidak, pesan tersebut tidak akan berarti. Tanpa protokol, setiap produsen akan menciptakan format mereka sendiri dan perangkat dari merek yang berbeda tidak akan dapat berkomunikasi satu sama lain.
Protokol NMEA-0183 (selanjutnya disebut NMEA) adalah standar industri untuk teknologi GNSS.
Kami telah menyiapkan halaman ini sebagai referensi untuk definisi protokol NMEA dan juga untuk memberikan deskripsi tentang pesan-pesan yang paling populer. Jika Anda melewatkan pesan apa pun atau menemukan kesalahan ketik, hubungi kami dan kami akan memperbaikinya 🙂
Pesan-pesan NMEA populer
| Pesan | Deskripsi | Ketersediaan |
|---|---|---|
| GGA | Data Perbaikan Sistem Penentuan Posisi Global — posisi, ketinggian, kualitas perbaikan, dan jumlah satelit. | Semua penerima |
| GLL | Posisi Geografis — garis lintang dan garis bujur beserta waktu dan status | Semua penerima |
| GPS | Data Perbaikan GNSS — mirip dengan GGA tetapi mendukung beberapa konstelasi (GPS, GLONASS, Galileo...) | Semua penerima |
| GRS | Sisa Jarak GNSS — sisa jarak yang digunakan dalam solusi navigasi. | Semua penerima |
| GSA | GNSS DOP dan Satelit Aktif — jenis perbaikan (2D/3D) dan satelit yang digunakan | Semua penerima |
| GST | Statistik Kesalahan Pseudorange GNSS — perkiraan kesalahan posisi (RMS, lintang, bujur, ketinggian) | Semua penerima |
| GSV | Satelit GNSS yang Terlihat — jumlah, elevasi, azimut, dan kekuatan sinyal satelit yang terlihat | Semua penerima |
| HDT | Haluan Sejati — haluan sebenarnya kapal relatif terhadap utara sejati | Septentrio Mosaic-H simpleRTK3B Heading |
| INSPVAXA | Data Fusi Sensor — posisi, kecepatan, orientasi terintegrasi, dan perkiraan kesalahannya. | Unicore UM981 simpleRTK3B Fusion |
| PUBX,00 | Data Posisi — lintang, bujur, ketinggian, dan kualitas perbaikan (u-blox perangkat) | Semua u-blox receiver |
| PUBX,04 | Waktu dalam Sehari — Data waktu dan jam UTC (u-blox perangkat) | Semua u-blox receiver |
| RMC | Data GNSS Spesifik Minimum yang Direkomendasikan — posisi, kecepatan, arah, dan tanggal | Semua penerima |
| ROT | Laju Putar — kecepatan rotasi kapal dalam derajat per menit | Septentrio Mosaic-H simpleRTK3B Heading |
| VTG | Arah dan Kecepatan di Atas Permukaan Tanah — arah dan kecepatan dalam knot dan km/jam | Semua penerima |
| ZDA | Waktu dan Tanggal — Waktu UTC, hari, bulan, tahun, dan zona waktu lokal | Semua penerima |
Struktur pesan NMEA
Setiap pesan dimulai dengan sebuah $ Tanda diikuti dengan kode singkat yang mengidentifikasi jenis data yang dikandungnya (lihat tabel di bagian selanjutnya).
Penerima kemudian mengisi semua kolom data yang dipisahkan oleh koma — lintang, bujur, ketinggian, waktu, jumlah satelit, dll. — dan mengakhiri pesan dengan sebuah checksum, yang merupakan angka kecil yang memungkinkan perangkat penerima untuk memverifikasi bahwa data tidak rusak selama transmisi.
Pesan tersebut diakhiri dengan jeda baris dan pesan berikutnya dimulai segera setelahnya.
Gambar di bawah ini merangkum bagaimana pesan NMEA dihasilkan.

Pembuatan checksum NMEA
Contoh kode untuk menghasilkan checksum NMEA berdasarkan payload 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)
Validasi checksum NMEA
Jika Anda ingin memvalidasi apakah pesan NMEA sah atau tidak, gunakan kode contoh di bawah ini:
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
#include
#include
#include
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
#include
#include
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 checksum NMEA online
Checksum (heksadesimal)
--
Checksum (desimal)
--
Panjang muatan
--
Kalimat lengkap
-
Verifikasi sebuah kalimat
ke