NMEA 協定:GNSS 接收機的通用語言

當你打開任何一款 GNSS 接收機的串口監控軟體,看到的第一個畫面通常是一串串以 $GP 開頭的文字訊息,不斷地滾動更新,有一種很洗畫面的感覺。這就是 NMEA 協定,幾乎所有 GNSS 接收機都支援的標準輸出格式。

在我剛開始開發 GNSS 應用時,面對這像火星文的字串完全摸不著頭緒。但當我慢慢理解了 NMEA 的結構後,才發現它其實沒那麼難懂,而且包含了定位所需的幾乎所有資訊。今天就來完整解析 NMEA 協定,讓你也能輕鬆讀懂衛星的「語言」。


一、什麼是 NMEA?

NMEA(National Marine Electronics Association,美國國家海洋電子協會)是一個制定海洋電子設備通訊標準的組織。NMEA-0183 是其在 1983 年發布的串列通訊協定標準,原本用於船舶導航設備,後來成為 GNSS 接收機的事實標準。

為什麼 NMEA 這麼流行?

  • 文字格式:人類可讀,方便除錯
  • 簡單易解析:用逗號分隔,不需複雜的解碼
  • 廣泛支援:幾乎所有 GNSS 接收機都支援
  • 跨平台:不依賴特定硬體或作業系統
  • 標準化:不同廠商的接收機輸出格式一致

主要特點

  • 串列通訊:RS-232 或 USB 虛擬串口
  • 波特率:常見 4800、9600、38400、115200 bps
  • 資料格式:ASCII 文字,每行一條訊息
  • 更新率:通常 1 Hz,部分接收機支援 5-10 Hz

二、NMEA 訊息的基本格式

每條 NMEA 訊息都遵循固定的結構:

$GPGGA,123519,2503.1234,N,12100.5678,E,1,08,0.9,545.4,M,46.9,M,,*47
↑  ↑   ↑                                                        ↑
|  |   |                                                        校驗碼
|  |   資料欄位(用逗號分隔)
|  訊息類型(Sentence ID)
對話者 ID(Talker ID)

結構說明

  1. $:訊息開始符號
  2. Talker ID(2 字元):
    • GP = GPS
    • GL = GLONASS
    • GA = Galileo
    • GB = BeiDou
    • GN = 多 GNSS 組合
  3. Sentence ID(3 字元):訊息類型(如 GGA、RMC)
  4. 資料欄位:用 , 分隔,空欄位表示無資料
  5. *:校驗碼分隔符
  6. 校驗碼(2 位元組十六進位):XOR 校驗
  7. \r\n:換行符號(結束)

校驗碼計算

校驗碼是 $* 之間所有字元的 XOR 運算:

範例

$GPGGA,123519,2503.1234,N,12100.5678,E,1,08,0.9,545.4,M,46.9,M,,*47

計算步驟:
1. 取出 $ 和 * 之間的字串:
   GPGGA,123519,2503.1234,N,12100.5678,E,1,08,0.9,545.4,M,46.9,M,,

2. 對每個字元的 ASCII 碼做 XOR 運算:
   'G' XOR 'P' XOR 'G' XOR 'G' XOR 'A' XOR ',' XOR ...

3. 結果轉成十六進位:47

為什麼需要校驗碼?
– 檢測傳輸錯誤
– 確保資料完整性
– 串列通訊可能有雜訊干擾


三、常用 NMEA 訊息詳解

$GPGGA – 定位資訊(最重要)

包含完整的 3D 定位資訊,是最常用的訊息。

$GPGGA,123519,2503.1234,N,12100.5678,E,1,08,0.9,545.4,M,46.9,M,,*47

欄位解析

欄位 內容 說明
0 $GPGGA 訊息類型
1 123519 UTC 時間(12:35:19)
2 2503.1234 緯度(25°03.1234’)
3 N 北緯(N)或南緯(S)
4 12100.5678 經度(121°00.5678’)
5 E 東經(E)或西經(W)
6 1 定位品質(0=無效, 1=GPS, 2=DGPS, 4=RTK固定解, 5=RTK浮點解)
7 08 使用的衛星數量
8 0.9 HDOP(水平精度因子,無單位)
9 545.4 海拔高度(公尺)
10 M 高度單位(公尺)
11 46.9 大地水準面高度(公尺)
12 M 單位(公尺)
13 DGPS 資料齡期(空=無 DGPS)
14 DGPS 基站 ID
15 *47 校驗碼

定位品質指標詳解

說明 精度
0 無效定位
1 GPS 單點定位(SPS) 5-15 公尺
2 差分 GPS(DGPS) 1-5 公尺
4 RTK 固定解 1-3 公分
5 RTK 浮點解 10-50 公分
6 推算定位 依賴慣性導航

經緯度格式轉換

NMEA 使用「度分」格式(DDMM.MMMM),需要轉換成十進位度:

範例:2503.1234,N

步驟:
1. 前兩位是度:25°
2. 後面是分:03.1234'
3. 轉換公式:度 + 分/60
4. 計算:25 + 03.1234/60 = 25.052056°

如果是南緯(S)或西經(W),結果要加負號

實際範例
– 緯度 2503.1234,N25.052056°N
– 經度 12100.5678,E121.009463°E
– 緯度 3351.8765,S-33.864608°S
– 經度 15112.3456,W-151.205760°W

💡 實務經驗: 我們曾經遇過一個 bug,在南半球測試時,緯度一直是正值。原因是忘記檢查 N/S 標記,導致所有位置都被定位到北半球。這個錯誤提醒我們,永遠不要假設資料格式,要嚴格按照協定解析


$GPRMC – 推薦最小資料

包含時間、日期、位置、速度、航向,是最精簡但完整的訊息。

$GPRMC,123519,A,2503.1234,N,12100.5678,E,022.4,084.4,230394,003.1,W*6A

欄位解析

欄位 內容 說明
0 $GPRMC 訊息類型
1 123519 UTC 時間(12:35:19)
2 A 狀態(A=有效, V=無效)
3 2503.1234 緯度
4 N 北/南緯
5 12100.5678 經度
6 E 東/西經
7 022.4 地面速率(節,knots)
8 084.4 地面航向(度,真北為 0°)
9 230394 UTC 日期(23/03/1994,DD/MM/YY)
10 003.1 磁偏角(度)
11 W 磁偏角方向(E/W)
12 *6A 校驗碼

速度單位轉換

1 節(knot)= 1.852 公里/小時
1 節(knot)= 0.514444 公尺/秒

範例:022.4 節
→ 22.4 × 1.852 = 41.5 公里/小時
→ 22.4 × 0.514444 = 11.5 公尺/秒

航向說明
– 0° = 正北
– 90° = 正東
– 180° = 正南
– 270° = 正西

RMC 的優勢
– 包含日期(GGA 沒有)
– 包含速度和航向
– 資料最精簡
– 適合記錄軌跡


$GPGSA – 衛星狀態與 DOP 值

顯示定位模式、使用的衛星、DOP 值。

$GPGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1*39

欄位解析

欄位 內容 說明
0 $GPGSA 訊息類型
1 A 模式(M=手動選擇 2D/3D, A=自動選擇)
2 3 定位類型(1=無定位, 2=2D, 3=3D)
3-14 04,05,... 使用的衛星 PRN 編號(最多 12 顆)
15 2.5 PDOP(位置精度因子,無單位)
16 1.3 HDOP(水平精度因子,無單位)
17 2.1 VDOP(垂直精度因子,無單位)
18 *39 校驗碼

定位類型說明

說明 需要衛星數
1 無定位 < 3 顆
2 2D 定位(固定高度) 3 顆
3 3D 定位 ≥ 4 顆

DOP 值的關係

\text{PDOP}^2 = \text{HDOP}^2 + \text{VDOP}^2

範例驗證
– HDOP = 1.3
– VDOP = 2.1
– PDOP = √(1.3² + 2.1²) = √(1.69 + 4.41) = √6.1 ≈ 2.47 ≈ 2.5 ✓

DOP 值判讀

DOP 值 評級 衛星幾何 定位精度估計
< 1 理想 極佳 極少達到
1-2 優秀 很好 誤差 < 5 公尺
2-5 良好 誤差 5-15 公尺
5-10 中等 普通 誤差 15-50 公尺
10-20 不佳 誤差 > 50 公尺
> 20 極差 很差 不建議使用

為什麼 DOP 很重要?

因為 DOP 值反映衛星的幾何分布:
DOP 低:衛星分布均勻,定位精度高
DOP 高:衛星聚集在某個方向,定位精度低

實際定位誤差 = DOP × 測距誤差


$GPGSV – 可見衛星詳細資訊

顯示所有可見衛星的仰角、方位角、訊噪比。

$GPGSV,3,1,11,03,03,111,00,04,15,270,00,06,01,010,00,13,06,292,00*74
$GPGSV,3,2,11,14,25,170,00,16,57,208,39,18,67,296,40,19,40,246,00*74
$GPGSV,3,3,11,22,42,067,42,24,14,311,43,27,05,244,00,,,,*4D

欄位解析(第一條訊息)

欄位 內容 說明
0 $GPGSV 訊息類型
1 3 總訊息數(需要 3 條訊息)
2 1 當前訊息編號(第 1 條)
3 11 可見衛星總數(11 顆)
4-7 03,03,111,00 衛星 1:PRN=03, 仰角=3°, 方位角=111°, C/N0=00
8-11 04,15,270,00 衛星 2:PRN=04, 仰角=15°, 方位角=270°, C/N0=00
12-15 06,01,010,00 衛星 3:PRN=06, 仰角=1°, 方位角=10°, C/N0=00
16-19 13,06,292,00 衛星 4:PRN=13, 仰角=6°, 方位角=292°, C/N0=00
20 *74 校驗碼

每條 GSV 訊息最多包含 4 顆衛星資訊,所以 11 顆衛星需要 3 條訊息(4+4+3)。

衛星參數說明

1. PRN(Pseudo-Random Noise)編號
– GPS:1-32
– GLONASS:65-96
– Galileo:1-36(Talker ID 為 GA)
– BeiDou:1-63(Talker ID 為 GB)

2. 仰角(Elevation)
– 範圍:0-90°
– 0° = 地平線
– 90° = 天頂(正上方)
– 仰角越高,訊號品質通常越好

3. 方位角(Azimuth)
– 範圍:0-359°
– 0° = 正北
– 90° = 正東
– 180° = 正南
– 270° = 正西

4. C/N0(訊噪比,Carrier-to-Noise Ratio)

C/N0 值 訊號品質 環境 可用性
> 45 dB-Hz 優秀 空曠戶外 ✅ 定位精度高
40-45 dB-Hz 良好 一般戶外 ✅ 可靠定位
35-40 dB-Hz 中等 有遮蔽 ⚠️ 可用但精度降低
30-35 dB-Hz 嚴重遮蔽 ⚠️ 精度很低
< 30 dB-Hz 極差 室內/峽谷 ❌ 通常無法定位
00 無訊號 ❌ 可見但未追蹤

💡 實務經驗: 在開發定位品質監控功能時,我們發現單看衛星數量不夠,還要看 C/N0。曾經在室內測試,接收機顯示 8 顆衛星,但 C/N0 都低於 25 dB-Hz,定位結果完全不可用。後來我們加入 C/N0 門檻過濾(> 30 dB-Hz),定位品質明顯改善。

GSV 的應用
– 診斷訊號品質問題
– 判斷天線安裝是否正確
– 分析遮蔽物影響
– 選擇最佳觀測時段


$GPGST – 精度統計(選配)

部分高階接收機支援,提供定位精度估計。

$GPGST,123519,3.2,6.6,4.7,47.3,5.8,5.6,22.6*58

欄位解析

欄位 內容 說明
0 $GPGST 訊息類型
1 123519 UTC 時間
2 3.2 RMS 誤差(公尺)
3 6.6 誤差橢圓長軸標準差(公尺)
4 4.7 誤差橢圓短軸標準差(公尺)
5 47.3 誤差橢圓方位角(度)
6 5.8 緯度誤差標準差(公尺)
7 5.6 經度誤差標準差(公尺)
8 22.6 高度誤差標準差(公尺)
9 *58 校驗碼

水平精度估計

\text{水平精度} \approx \sqrt{\text{緯度誤差}^2 + \text{經度誤差}^2}

範例:√(5.8² + 5.6²) = √(33.64 + 31.36) = √65 ≈ 8.1 公尺

GST 的價值
– 接收機自己估計的精度
– 比 DOP 更直接
– 可用於品質控制
– 不是所有接收機都支援


四、實務應用建議

1. 選擇需要的訊息

不要輸出所有訊息,只啟用需要的:

應用場景 建議訊息組合 說明
基本定位 GGA + RMC 位置、時間、日期、速度
品質監控 GGA + GSA + GSV 加上 DOP 和衛星資訊
精度評估 GGA + GSA + GST 需要接收機支援 GST
軌跡記錄 RMC 最精簡,包含所有基本資訊
最小配置 RMC 一條訊息包含最多資訊

2. 波特率設定

根據更新率和訊息數量選擇合適的波特率:

更新率 訊息組合 每秒資料量 建議波特率
1 Hz GGA + RMC ~160 bytes 9600 bps
1 Hz GGA + RMC + GSA + GSV ~400 bytes 9600 bps
5 Hz GGA + RMC ~800 bytes 19200 bps
5 Hz GGA + RMC + GSA ~1000 bytes 38400 bps
10 Hz GGA + RMC ~1600 bytes 38400 bps
10 Hz GGA + RMC + GSA ~2000 bytes 115200 bps

計算公式

每條 NMEA 訊息約 70-100 字元
加上換行符號約 80-110 bytes

範例:5 Hz,輸出 GGA + RMC + GSA

每秒資料量 = (80 + 80 + 60) bytes × 5 Hz = 1100 bytes/s
需要頻寬 = 1100 × 10 bits = 11000 bps
建議波特率 = 19200 bps(留 2 倍餘裕)

3. 錯誤處理檢查清單

解析 NMEA 時,務必檢查:

基本格式檢查
– 訊息開頭是否為 $
– 是否包含 * 和校驗碼
– 校驗碼是否正確

資料有效性檢查
– 欄位數量是否足夠
– 數值欄位是否為空
– 定位狀態是否有效(GGA quality ≥ 1, RMC status = A)

格式轉換檢查
– 經緯度格式轉換(度分 → 十進位度)
– 南緯/西經要加負號
– 時間是 UTC 需轉換

合理性檢查
– 緯度範圍:-90° 到 +90°
– 經度範圍:-180° 到 +180°
– 高度是否合理
– 速度是否合理

4. 多 GNSS 處理

現代接收機會輸出多個系統的訊息:

$GPGGA,... (GPS 定位)
$GLGGA,... (GLONASS 定位)
$GAGGA,... (Galileo 定位)
$GBGGA,... (BeiDou 定位)
$GNGGA,... (多系統組合定位) ← 推薦使用

處理策略

策略 說明 優點 缺點
只用 GN 只解析 $GN 開頭的訊息 簡單,已是最佳結果 無法分析各系統
分別解析 解析所有系統的訊息 可比較各系統性能 複雜,資料量大
優先順序 GN > GP > GL > GA > GB 有備援機制 需要更多邏輯

推薦做法
– 定位應用:只用 $GN 訊息
– 診斷分析:解析所有系統的 GSV 訊息
– 研究開發:記錄所有訊息供後續分析

5. 效能優化建議

減少資料量
– 只啟用必要的訊息類型
– GSV 訊息資料量大,不需要時可關閉
– 降低更新率(如果應用允許)

提高解析效率
– 先檢查訊息類型,只解析需要的
– 使用查表法而非字串比較
– 快取經常使用的計算結果

記憶體管理
– 使用固定大小的緩衝區
– 避免動態記憶體分配
– 及時清理過期資料


五、常見陷阱與解決方案

❌ 陷阱 1:時間是 UTC 不是本地時間

問題

GGA 時間:123519
直接顯示:12:35:19(誤以為是台北時間)

正確做法

GGA 時間:123519(UTC)
台北時間(UTC+8):123519 + 8 小時 = 20:35:19

注意跨日問題:
UTC 時間:235959(23:59:59)
台北時間:235959 + 8 小時 = 次日 07:59:59

❌ 陷阱 2:空欄位處理

問題

$GPGGA,123519,,,,,0,00,,,M,,M,,*XX
↑ 無效定位時,經緯度等欄位是空的

正確做法
– 先檢查定位品質(欄位 6)
– 檢查欄位是否為空再解析
– 設定預設值或錯誤標記

❌ 陷阱 3:經緯度格式混淆

錯誤理解

緯度:2503.1234
誤以為:2503.1234 度

正確理解

2503.1234 = 25°03.1234'(度分格式)
轉換:25 + 03.1234/60 = 25.052056 度

❌ 陷阱 4:忘記檢查定位品質

問題

只要收到 GGA 訊息就使用位置資料
→ 可能使用無效的定位結果

正確做法

檢查 GGA 欄位 6(定位品質):
- 0 = 無效,不使用 ❌
- 1 = GPS 單點定位,可用 ✅
- 2 = DGPS,精度更高 ✅
- 4 = RTK 固定解,公分級 ✅
- 5 = RTK 浮點解,分米級 ✅

或檢查 RMC 欄位 2(狀態):
- A = 有效 ✅
- V = 無效 ❌

❌ 陷阱 5:HDOP 當成公尺

錯誤理解

HDOP = 1.5
誤以為:水平誤差 1.5 公尺

正確理解

HDOP = 1.5(無單位,是一個倍數)
測距誤差 = 5 公尺(假設)
實際水平誤差 ≈ 1.5 × 5 = 7.5 公尺

HDOP 只是幾何因子,不是誤差本身

❌ 陷阱 6:忽略校驗碼

問題

為了簡化,不驗證校驗碼
→ 可能使用損壞的資料

正確做法
– 永遠驗證校驗碼
– 校驗碼錯誤時丟棄整條訊息
– 記錄錯誤率用於診斷

💡 實務經驗: 在一個車載專案中,我們發現定位偶爾會「跳動」到奇怪的位置。後來發現是電磁干擾導致串口資料損壞,但我們沒有驗證校驗碼。加入校驗碼驗證後,這些異常資料被過濾掉,定位穩定性大幅提升。永遠不要跳過校驗碼驗證


六、總結

NMEA-0183 是 GNSS 接收機最通用的輸出格式:

✅ 優點

  • 人類可讀:方便除錯和理解
  • 廣泛支援:幾乎所有接收機都支援
  • 簡單易解析:用逗號分隔,結構清晰
  • 跨平台:不依賴特定硬體
  • 標準化:不同廠商格式一致

⚠️ 注意事項

  • 資料量大:文字格式佔用頻寬
  • 精度有限:小數位數固定
  • 需要轉換:經緯度、速度等格式
  • 時間是 UTC:需轉換成本地時間
  • 高更新率受限:10 Hz 以上效率低

🎯 關鍵要點

  1. 永遠驗證校驗碼
  2. 正確轉換經緯度格式(度分 → 十進位度)
  3. 處理空欄位(無效定位時很多欄位是空的)
  4. 檢查定位品質(GGA quality, RMC status)
  5. 時間是 UTC(需轉換成本地時間)
  6. DOP 是無單位的(不是公尺,是倍數)
  7. C/N0 很重要(判斷訊號品質)
  8. 多 GNSS 用 GN(組合定位結果最佳)

📊 快速參考表

訊息 更新率 用途 關鍵欄位
GGA 1 Hz 3D 定位 時間、經緯度、高度、HDOP、衛星數、定位品質
RMC 1 Hz 最小資料 時間、日期、經緯度、速度、航向、狀態
GSA 1 Hz DOP 值 定位模式、使用的衛星、PDOP/HDOP/VDOP
GSV 5 秒 衛星資訊 衛星編號、仰角、方位角、C/N0
GST 1 Hz 精度估計 RMS 誤差、各軸誤差標準差(選配)

💬 討論

你在解析 NMEA 時遇過什麼問題?歡迎留言討論!

分類: 技術相關,標籤: , , , , , , , , , , , , , , 。這篇內容的永久連結

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *