Руководство по GNSS протоколам: NMEA, UBX, PAIR/PQTM, Unicore

Все статьи

Сравнительная таблица протоколов

ПараметрNMEA 0183UBX (u-blox)PAIR/PQTM (Quectel)Unicore (NovAtel)
Тип протоколаASCII-текстБинарныйASCII-текстASCII + бинарный (UNCB)
ЧеловекочитаемостьДаНет (требует декодер)ДаСмешанный
Размер пакетаБольшой (200-500 байт)Компактный (50-100 байт)Средний (100-200 байт)Средний/Большой
Скорость передачиОграничена объемомВысокаяСредняяВысокая (при бинарном)
Поддержка в ArduPilotПолнаяПолная + расширенные функцииЧерез NMEAЧерез NMEA (ограниченно)
Конфигурация модуляОграниченаПолнаяЗависит от версииПолная (через утилиты)
ДиагностикаБазоваяРасширеннаяСредняяРасширенная
АнтиджаммингНетAIC (автоматический)Зависит от моделиAdaptive AIC + CRPA
RTK поддержкаЧерез RTCMНативнаяЧерез RTCMНативная + многоконстелляционная
GPS BlendingНетДаНетЧерез внешнюю логику
СовместимостьУниверсальнаяТолько u-bloxТолько Quectel/MTKТолько Unicore
LC29HAA✅ Да❌ Нет✅ Да❌ Нет
UM980✅ Да❌ НетНет✅ Да
u-blox F9P✅ Да✅ Да❌ НетНет

Поддерживаемые команды по модулям

КомандаНазначениеLC29HAAUM980u-blox F9P
$PQTMCFGRA,W,N*XXЧастота обновления✅ 1/2/4 Гц
$PAIR050,N*XXЧастота (расширенная)
$PAIR066,N*XXВыбор созвездий
$PAIR074,N*XXАнтиджамминг
$PQTMSAVEPAR*5AСохранение в NVM
CONFIG GNSSВыбор созвездий
CONFIG ANTJAMНастройка антиджамминга
UBX-CFG-RATEЧастота обновления
UBX-CFG-MSGУправление сообщениями
SAVECONFIGСохранение настроек

Что выбрать для европейской части РФ (без RTK)

ЗадачаРекомендуемый модульПротоколПричина
Бюджетный квадрокоптерLC29HAANMEA + PQTMДостаточно 2 Гц, низкая цена, простая интеграция
Дальнобойный/картографическийUM980NMEA + UnicoreМногодиапазонный прием, лучше работа в условиях городской застройки
ПомехозащищенныйUM982 + CRPAUnicoreАдаптивный антиджамминг, работа в условиях РЭБ
Максимальная совместимостьu-blox F9P/F10UBXПолная поддержка ArduPilot, UBX-протокол, документация
Гоночный дронUM980 или F9PUnicore/UBXВысокая частота обновления (10-50 Гц)

⚠️ Важно: При использовании Quectel или Unicore с GPS_AUTO_CONFIG=0 убедитесь, что SERIALx_BAUD точно совпадает с настройками модуля — иначе ArduPilot не получит данные.


Содержание

  1. NMEA 0183
  2. UBX Protocol (u-blox)
  3. PAIR/PQTM (Quectel)
  4. Unicore Commands
  5. Практические примеры для ArduPilot

1. NMEA 0183

Структура сообщения

$<TalkerID><Sentence>,<Data1>,<Data2>,...*<Checksum><CR><LF>

Поля:

  • $ — начало сообщения
  • TalkerID (2 символа):
  • GP — GPS
  • GL — GLONASS
  • GN — Mixed (все системы)
  • GB — BeiDou
  • GA — Galileo
  • Sentence (3 символа) — тип сообщения
  • Data — данные через запятую
  • *XX — контрольная сумма (XOR)
  • — конец строки (0x0D 0x0A)

Основные сообщения

GGA — GPS Fix Data (основные данные)

Пример:

$GNGGA,123519.000,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*6C

Расшифровка:

ПолеЗначениеОписание
1123519.000Время UTC (12:35:19)
24807.038Широта (48°07.038′)
3NСеверная (N/S)
401131.000Долгота (11°31.000′)
5EВосточная (E/W)
61Качество: 1=GPS, 2=DGPS, 0=No Fix
708Количество спутников
80.9HDOP (горизонтальное ухудшение)
9545.4Высота над уровнем моря (м)
10MЕдиницы: метры
1146.9Высота геоида
12MЕдиницы геоида

Парсинг в Python:

def parse_gga(sentence):
    parts = sentence.split(',')
    return {
        'time': parts[1],
        'latitude': float(parts[2][:2]) + float(parts[2][2:])/60,
        'lat_dir': parts[3],
        'longitude': float(parts[4][:3]) + float(parts[4][3:])/60,
        'lon_dir': parts[5],
        'quality': int(parts[6]),
        'satellites': int(parts[7]),
        'hdop': float(parts[8]),
        'altitude': float(parts[9])
    }

RMC — Recommended Minimum Data

Пример:

$GNRMC,123519.000,A,4807.038,N,01131.000,E,0.00,237.6,140122,,,A*6B

Расшифровка:

ПолеЗначениеОписание
1123519.000Время UTC
2AСтатус: A=Active, V=Void
34807.038Широта
4NНаправление широты
501131.000Долгота
6EНаправление долготы
70.00Скорость (узлы)
8237.6Курс (градусы)
9140122Дата (14.01.2022)
10Магнитное склонение
11Направление склонения
12AРежим: A=Autonomous, D=DGPS

GSV — Satellites in View (спутники в поле зрения)

Пример (4 сообщения):

$GPGSV,3,1,09,11,23,43,191,32,16,40,288,17,29,37,133,22,26,35,130,13*67
$GPGSV,3,2,09,12,54,321,25,15,67,089,31,18,12,045,28,21,78,234,19*65
$GPGSV,3,3,09,24,45,156,22*4D

Расшифровка:

ПолеЗначение
13 — всего сообщений
21 — номер текущего
309 — всего спутников
411 — PRN спутника 1
523 — угол места (elevation)
643 — азимут
7191 — SNR (сигнал/шум)

GSA — Active Satellites и DOP

Пример:

$GNGSA,A,3,04,05,06,16,18,22,24,10,12,14,15,,1.8,1.1,1.4*3E

Расшифровка:

ПолеЗначение
1A — Auto selection
23 — 3D fix
3-14PRN активных спутников
151.8 — PDOP
161.1 — HDOP
171.4 — VDOP

Расчет контрольной суммы

def calculate_checksum(sentence):
    """Рассчитать XOR checksum для NMEA"""
    # Убрать $ и *XX
    if sentence.startswith('$'):
        sentence = sentence[1:]
    if '*' in sentence:
        sentence = sentence.split('*')[0]

    checksum = 0
    for char in sentence:
        checksum ^= ord(char)
    return f"{checksum:02X}"

# Пример
msg = "GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M"
print(f"${msg}*{calculate_checksum(msg)}")
# Результат: $GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M*XX

2. UBX Protocol (u-blox)

Структура пакета UBX

UBX Packet Structure

Поля заголовка:

  • Sync Char 1: 0xB5 (181)
  • Sync Char 2: 0x62 (98)
  • Class: Класс сообщения (1 байт)
  • ID: Идентификатор сообщения (1 байт)
  • Length: Длина payload (2 байта, Little Endian)
  • Payload: Данные (переменная длина)
  • CK_A, CK_B: Checksum (2 байта)

Классы сообщений

ClassHexОписание
UBX-CFG0x06Configuration
UBX-NAV0x01Navigation
UBX-ACK0x05Acknowledge
UBX-MON0x0AMonitoring
UBX-RXM0x02Receiver Manager

Примеры сообщений

UBX-NAV-PVT — Position Velocity Time

Структура:

B5 62 01 07 58 00 ...payload 88 байт... CK_A CK_B

Payload (первые поля):

typedef struct {
    uint32_t iTOW;      // Time of week (ms)
    uint16_t year;      // Year
    uint8_t month;      // Month
    uint8_t day;        // Day
    uint8_t hour;       // Hour
    uint8_t min;        // Minute
    uint8_t sec;        // Second
    uint8_t valid;      // Validity flags
    uint32_t tAcc;      // Time accuracy estimate
    int32_t nano;       // Fraction of second
    // ... еще поля
} UBX_NAV_PVT;

Полный пример (hex):

B5 62 01 07 58 00 
14 1A 01 00           // iTOW = 69604 ms
E4 07                 // year = 2020
01                    // month = January
01                    // day = 1
00                    // hour = 0
00                    // min = 0
10                    // sec = 16
...                   // остальные поля
CK_A CK_B             // checksum

UBX-CFG-MSG — Configure Message Rate

Команда для включения NAV-PVT на 1 Гц:

Отправка:

B5 62 06 01 08 00 01 07 01 00 01 00 00 00 18 99

Расшифровка:

  • B5 62 — Sync
  • 06 — Class CFG
  • 01 — ID MSG
  • 08 00 — Length = 8 bytes
  • 01 07 — msgClass=0x01 (NAV), msgID=0x07 (PVT)
  • 01 — rate on UART1 = 1 Hz
  • 00 00 00 — rates on other ports = 0
  • 18 99 — Checksum

Python для расчета checksum UBX:

def ubx_checksum(payload):
    """Рассчитать checksum для UBX"""
    ck_a = 0
    ck_b = 0
    for byte in payload:
        ck_a = (ck_a + byte) & 0xFF
        ck_b = (ck_b + ck_a) & 0xFF
    return ck_a, ck_b

# Пример
msg = bytes([0x06, 0x01, 0x08, 0x00, 0x01, 0x07, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00])
ck_a, ck_b = ubx_checksum(msg)
print(f"Checksum: {ck_a:02X} {ck_b:02X}")  # 18 99

UBX-CFG-RATE — Configure Update Rate

Установить 5 Гц (200 мс):

B5 62 06 08 06 00 C8 00 01 00 01 00 DE 6A

Расшифровка:

  • C8 00 — measRate = 200 ms (0x00C8)
  • 01 00 — navRate = 1 (каждое измерение)
  • 01 00 — timeRef = 1 (UTC)

3. PAIR/PQTM (Quectel)

PAIR команды (MTK chipset)

Структура:

$PAIR<ID>,<param1>,<param2>,...*<Checksum>

$PAIR050 — Update Rate

Примеры:

$PAIR050,1*26     // 1 Hz (по умолчанию)
$PAIR050,5*23     // 5 Hz
$PAIR050,10*28    // 10 Hz

⚠️ Важно: На LC29HAA эта команда НЕ РАБОТАЕТ! Используйте $PQTMCFGRA.

$PAIR066 — GNSS Constellation

$PAIR066,0*26     // GPS only
$PAIR066,1*25     // GPS + GLONASS
$PAIR066,3*27     // GPS + GLONASS + Galileo + BeiDou

⚠️ Важно: На LC29HAA НЕ РАБОТАЕТ!

$PAIR074 — Anti-Jamming

$PAIR074,0*24     // Disable
$PAIR074,1*25     // Enable

PQTM команды (Quectel proprietary)

$PQTMCFGRA — Configure Rate

Примеры для LC29HAA:

$PQTMCFGRA,W,1*2D    // 1 Hz
$PQTMCFGRA,W,2*2C    // 2 Hz ✅ РАБОТАЕТ
$PQTMCFGRA,W,4*2E    // 4 Hz

Структура:

  • $PQTMCFGRA — команда
  • W — Write
  • N — частота (1/2/4)
  • *XX — checksum

$PQTMSAVEPAR — Save Parameters

$PQTMSAVEPAR*5A

Сохраняет текущие настройки в NVM (неvolatile memory).

$PQTMSRR — Soft Reset

$PQTMSRR*4B

Перезагружает модуль.

Расчет checksum для PAIR/PQTM

def pair_checksum(sentence):
    """Рассчитать checksum для PAIR/PQTM команд"""
    # Убрать $ и *
    if sentence.startswith('$'):
        sentence = sentence[1:]

    checksum = 0
    for char in sentence:
        checksum ^= ord(char)

    return f"{checksum:02X}"

# Примеры
print(f"$PAIR050,1*{pair_checksum('PAIR050,1')}")    // $PAIR050,1*26
print(f"$PQTMCFGRA,W,2*{pair_checksum('PQTMCFGRA,W,2')}")  // $PQTMCFGRA,W,2*2C

4. Unicore Commands

Структура команд Unicore

Unicore использует два формата:

  1. NMEA-like (ASCII): $<CMD>,<params>*<checksum>
  2. UNCB (Binary): бинарный протокол

Основные команды

CONFIG GNSS — Выбор созвездий

CONFIG GNSS GPS GLONASS
CONFIG GNSS GPS GLONASS GALILEO BEIDOU
SAVECONFIG

CONFIG ANTJAM — Anti-Jamming

CONFIG ANTJAM MODE AUTO           // Адаптивный режим
CONFIG ANTJAM THRESHOLD -30       // Порог -30 dBm
CONFIG ANTJAM ENABLE
SAVECONFIG

LOG — Включение логирования

LOG GPGGA ONTIME 0.1    // GGA каждые 100 мс (10 Hz)
LOG GPRMC ONTIME 0.1
LOG RAWEPHEM ONCE       // Эфемериды один раз

SAVECONFIG — Сохранение

SAVECONFIG

Сохраняет все настройки в энергонезависимую память.

Примеры Unicore UM980

Настройка на 10 Hz с GPS+GLONASS:

# Через терминал (115200 8N1)
UNLOGALL                  // Отключить все логи
LOG GPGGA ONTIME 0.1      // 10 Hz
LOG GPGLL ONTIME 0.1
LOG GPRMC ONTIME 0.1
CONFIG GNSS GPS GLONASS
SAVECONFIG
RESET                     // Перезагрузка

5. Практические примеры для ArduPilot

Настройка LC29HAA для квадрокоптера

1. Подключение:

LC29HAA          Flight Controller
TX  -----------  RX (Serial5)
RX  -----------  TX (Serial5)
GND -----------  GND
5V  -----------  5V (или отдельное питание)

2. Отправка команд через QGNSS:

$PQTMCFGRA,W,2*2C      // 2 Hz (достаточно для стабилизации)
$PQTMSAVEPAR*5A        // Сохранить
$PQTMSRR*4B            // Перезагрузка

3. Параметры ArduPilot:

# В Mission Planner (Full Parameter List)
GPS_TYPE = 2              # NMEA
GPS_AUTO_CONFIG = 0       # ⚠️ Обязательно отключить!
SERIAL5_PROTOCOL = 5      # GPS
SERIAL5_BAUD = 115200     # Скорость
GPS_RATE_MS = 500         # 2 Гц (500 мс)
GPS_GNSS_MODE = 0         # Использовать настройки модуля
GPS_SAVE_CFG = 0          # Не сохранять через ArduPilot

Настройка u-blox F9P (UBX protocol)

1. Через u-center:

  • Откройте u-center
  • View → Configuration View
  • Message Rates:
  • NAV-PVT: 1 Hz (или выше)
  • NAV-HPPOSLLH: 1 Hz (для RTK)
  • GNSS: выбрать GPS+GLONASS
  • Save to flash

2. Параметры ArduPilot:

GPS_TYPE = 5              # UBX
GPS_AUTO_CONFIG = 1       # ✅ Можно включить (ArduPilot сам настроит)
SERIAL5_PROTOCOL = 5
SERIAL5_BAUD = 115200
GPS_RATE_MS = 100         # 10 Гц для RTK
GPS_GNSS_MODE = 0

Настройка Unicore UM980

1. Через терминал:

UNLOGALL
LOG GPGGA ONTIME 0.1      # 10 Hz
LOG GPRMC ONTIME 0.1
LOG GPGSA ONTIME 1        # 1 Hz
CONFIG GNSS GPS GLONASS
CONFIG ANTJAM MODE AUTO
SAVECONFIG
RESET

2. Параметры ArduPilot:

GPS_TYPE = 2              # NMEA
GPS_AUTO_CONFIG = 0       # ⚠️ Отключить
SERIAL5_PROTOCOL = 5
SERIAL5_BAUD = 115200     # Или 230400 для высоких частот
GPS_RATE_MS = 100         # 10 Гц

Скрипт для автоматической настройки LC29HAA

Python скрипт:

import serial
import time

def configure_lc29h(port='COM5', baud=115200):
    ser = serial.Serial(port, baud, timeout=1)
    time.sleep(2)

    commands = [
        b'$PQTMCFGRA,W,2*2C\r\n',      # 2 Hz
        b'$PQTMSAVEPAR*5A\r\n',         # Сохранить
    ]

    for cmd in commands:
        print(f"Sending: {cmd.decode().strip()}")
        ser.write(cmd)
        time.sleep(0.5)
        response = ser.readline()
        print(f"Response: {response.decode().strip()}")
        time.sleep(0.5)

    # Перезагрузка
    ser.write(b'$PQTMSRR*4B\r\n')
    print("Module rebooting...")
    ser.close()

# Использование
configure_lc29h('COM5')

Отладка и диагностика

1. Проверка связи:

$PAIR000*32             # Версия прошивки (LC29H)

2. Мониторинг в реальном времени:

  • Откройте Mission Planner
  • Status → HUD
  • Смотрите GPS status:
  • GPS: OK — все хорошо
  • GPS: No GPS — проверьте подключение
  • GPS: 3D Fix — есть фикс

3. Логирование:

LOG_BITMASK = 65535     # Включить все логи
После полета: DataFlash Log → Download
Анализ: смотрите GPS статус и HDOP

📚 Источники


⚠️ Важно:

  • Всегда сохраняйте настройки командой сохранения ($PQTMSAVEPAR, SAVECONFIG, etc.)
  • После сохранения делайте перезагрузку модуля
  • При использовании с ArduPilot устанавливайте GPS_AUTO_CONFIG=0 для модулей Quectel и Unicore
  • Проверяйте контрольную сумму перед отправкой команд
Прокрутить вверх