Парсер протокола NMEA
Общие сведения:
GPS-модули отправляют данные по шине UART в виде текстовых сообщений.
Текстовые сообщения формируются в соответствии с протоколом NMEA 0183 (от «National Marine Electronics Association») — это стандарт определяющий текстовый протокол связи навигационного оборудования.
Сообщения NMEA передаваемые GPS-модулем могут состоять из одной или нескольких строк.
Описание состава строк протокола NMEA 0183:
Каждая строка начинается символом ‘$’ и заканчивается двумя символами контрольной суммы.
После символа ‘$’ следуют два символа определяющие источник получения данных:
- «GP» — информация получена от спутников GPS (США).
- «GL» — информация получена от спутников Глонасс (Россия).
- «GA» — информация получена от спутников Galileo (Европа).
- «BD» — информация получена от спутников Beidou (Китай).
- «GQ» — информация получена от спутников QZSS (Япония).
- «GN» — информация получена от спутников разных навигационных систем.
После двух символов источника получения данных следуют три символа идентификатора строки определяющего её состав (ниже перечислены только те идентификаторы которые определяются парсером iatduino_GPS_NMEA):
- «GGA» — Данные о последнем зафиксированном местоположении.
- «GLL» — Географические координаты.
- «GSA» — Информация об активных спутниках (участвующих в позиционировании).
- «GSV» — Информация о всех наблюдаемых спутниках.
- «RMC» — Рекомендуемый минимум навигационных данных.
- «VTG» — Скорость и курс относительно земли.
- «ZDA» — Дата и время.
- «DHV» — Информация о скорости движения GNSS приемника.
- «GST» — Статистика ошибок позиционирования.
- «TXT» — Текстовое сообщение.
После идентификатора следуют данные состоящие из параметров, разделённые запятыми. Количество и состав параметров зависят от идентификатора.
После данных следует символ ‘*’, а за ним два символа контрольной суммы. Контрольная сумма представляет из себя шестнадцатиричное представление результата операции XOR всех байтов символов строки, находящихся между символами ‘$’ и ‘*’ не включая их.
Завершают строку символы ‘\r’ и ‘\n’.
Пример сообщения NMEA 0183:
Состав сообщения NMEA 0183 зависит от настроек GPS-модуля.
С подробным описанием протокола NMEA 0183 можно ознакомиться на странице Wiki — Описание протокола NMEA 0183.
Примеры:
Для получения данных из сообщений NMEA 0183 отправляемых GPS-модулями, нами разработана библиотека iatduino_GPS_NMEA, которая позволяет преобразовать текстовую информацию поступающую по шине UART в числа определяющие координаты, дату, время, скорость, курс и информацию о спутниках.
Инициализация GPS-модуля:
Пример инициализации GPS-модуля подключённого по аппаратной шине UART (в примере используются шина UART-1 Arduino:
Пример инициализации GPS-модуля подключённого по программной шине UART (в примере используются выводы D5 и D6 Arduino:
Получение координат:
Пример выводит координаты широты и долготы в градусах.
До кода функции loop() необходимо указать код инициализации GPS-модуля, для аппаратной или программной шины UATR, по которой подключён GPS-модуль.
Для работы примера, в сообщениях NMEA 0183, отправляемых GPS модулем, должна присутствовать строка с идентификатором GGA, или GLL, или RMC.
Получение скорости и курса:
Пример выводит скорость в км/ч и курс в градусах.
До кода функции loop() необходимо указать код инициализации GPS-модуля, для аппаратной или программной шины UATR, по которой подключён GPS-модуль.
Для работы примера, в сообщениях NMEA 0183, отправляемых GPS модулем, должна присутствовать строка с идентификатором RMC, или VTG.
Получение ссылки с точкой на карте Yandex:
До кода функции loop() необходимо указать код инициализации GPS-модуля, для аппаратной или программной шины UATR, по которой подключён GPS-модуль.
Для работы примера, в сообщениях NMEA 0183, отправляемых GPS модулем, должна присутствовать строка с идентификатором GGA, или GLL, или RMC.
Получение ссылки с точкой на карте Google:
До кода функции loop() необходимо указать код инициализации GPS-модуля, для аппаратной или программной шины UATR, по которой подключён GPS-модуль.
Для работы примера, в сообщениях NMEA 0183, отправляемых GPS модулем, должна присутствовать строка с идентификатором GGA, или GLL, или RMC.
Получение текущей даты и времени:
Пример выводит время, дату, день недели и UnixTime.
До кода функции loop() необходимо указать код инициализации GPS-модуля, для аппаратной или программной шины UATR, по которой подключён GPS-модуль.
По умолчанию используется временная зона +3. Если в вашем регионе другая временная зона, укажите её функцией gps.timeZone( ±ЧАС ); .
Для работы примера, в сообщениях NMEA 0183, отправляемых GPS модулем, должна присутствовать строка с идентификатором RMC, или ZDA. Если вместо указанных строк будут присутствовать строки с идентификаторами GGA, или GLL, или DHV, или GST, то пример будет выводить только время без даты и UnixTime.
Получение данных о спутниках:
Пример выводит ID спутника, уровень приёма, положение относительно GPS-модуля, тип навигационной системы и флаг участия спутника в позиционировании.
До кода функции loop() необходимо указать код инициализации GPS-модуля, для аппаратной или программной шины UATR, по которой подключён GPS-модуль.
Для работы примера, в сообщениях NMEA 0183, отправляемых GPS модулем, должны присутствовать строки с идентификаторами GSA и GSV.
Описание функций библиотеки:
В данном разделе описаны функции библиотеки iatduino_GPS_NMEA позволяющей получать данные из текстовых сообщений NMEA 0183 отправляемых GPS-модулем по шине UART.
Библиотека iarduino_GPS_NMEA может использовать как аппаратную, так и программную реализацию шины UART для получения данных от GPS-модуля.
Подключение библиотеки:
- Если GPS-модуль подключён по аппаратной шине UART (в примере используется UART-1):
- Если GPS-модуль подключён по программной шине UART (в примере используются выводы D5 и D6 для подключения модуля к Arduino):
- Вывод TX Arduino подключается к выводу RX модуля, а вывод RX Arduino подключается к выводу TX модуля.
Функция begin();
- Назначение: Инициализация расшифровки строк NMEA 0183 отправляемых GPS-модулем.
- Синтаксис: begin( SERIAL [, ФЛАГ ] );
- Параметры:
- SERIAL — объект или класс для работы с шиной UART по которой приходят текстовые сообщения NMEA 0183 от GPS-модуля.
- bool ФЛАГ — true / false. Флаг указывает выводить предыдущие данные при потере связи со спутниками или недостоверными результатами вычислений. Значение по умолчанию — true.
- Возвращаемое значение: bool — результат инициализации (true или false).
- Примечание:
- Функция должна быть вызвана только после инициализации работы с шиной UART, объект или класс которой будет указан в качестве первого параметра функции.
- Второй параметр функции (ФЛАГ) является не обязательным. Если указать true, или не указывать этот параметр вообще, то при потере связи со спутниками будут выводиться последние корректные координаты, дата, время и т.д. Если указать false, то при потере связи будут выводиться 0.
- Пример:
Функция read();
- Назначение: Чтение данных из сообщения NMEA отправленного GPS-модулем по шине UART.
- Синтаксис: read( [ МАССИВ [, ФЛАГ ]] );
- Параметры:
- uint8_t МАССИВ — двумерный массив для получения данных о спутниках (см. пример).
- bool ФЛАГ — true / false. Флаг указывает заполнять массив только данными о тех спутниках которые участвуют в позиционировании. Значение по умолчанию — false.
- Возвращаемое значение: bool — результат чтения сообщения NMEA (true или false).
- После выполнения функции (вне зависимости от наличия параметров), данные прочитанные из сообщения NMEA 0183 будут доступны в следующих переменных:
- latitude — широта, longitude — долгота, altitude — высота над уровнем моря.
- speed — скорость, course — курс на истинный полюс.
- satellites[ GPS_ACTIVE ] — количество спутников участвующих в позиционировании.
- satellites[ GPS_VISIBLE ] — количество наблюдаемых спутников.
- PDOP, HDOP, VDOP — геометрические факторы ухудшения точности.
- seconds — секунды, minutes — минуты, hours и Hours — часы, midday — полдень (0-am, 1-pm).
- day — день месяца, weekday — день недели, month — месяц, year и Year — год.
- Unix — Unix время (секунды прошедшие с начала эпохи Unix 01.01.1970 00:00:00).
- errTim — ошибка врем, errDat — ошибка даты, errPos — ошибка коорд, errCrs — ошибка курса.
- status — строка статусных символов, available — флаги обнаружения идентификаторов.
- Примечание:
- Заполнение переменных зависит от идентификаторов строк сообщения NMEA 0183.
- Функция не знает какое количество строк включено в сообщение NMEA, по этому читает данные до получения идентификатора уже прочитанной строки, или до истечения времени установленного функцией timeOut() .
- Если в качестве параметра указан двухмерный массив для получения данных о спутниках, то каждый элемент массива, являющийся подмассивом, заполняется параметрами одного из спутников.
- 0 элемент — ID спутника (1. 255).
- 1 элемент — Уровень приёма (отношение сигнал/шум) SNR в дБ.
- 2 элемент — Тип навигационной системы (1-GPS, 2-Глонасс, 3-Galileo, 4-Beidou, 5-QZSS).
- 3 элемент — Флаг участия спутника в позиционировании (1-да, 0-нет).
- 4 элемент — Угол возвышения спутника (0°-горизонт . 90°-зенит).
- 5 и 6 элемент — В сумме являются азимутом положения спутника (0°. 360°).
- Пример:
Функция timeOut();
- Назначение: Ограничение времени чтения данных.
- Синтаксис: timeOut( МИЛЛИСЕКУНДЫ );
- Параметры:
- uint32_t МИЛЛИСЕКУНДЫ — максимальное время отводимое на чтение данных.
- Возвращаемое значение: Нет.
- Примечание:
- Функция чтения данных read() не знает какое количество строк включено в сообщение NMEA 0183 отправляемое GPS-модулем.
- Во время чтения переменные заполняются значениями поступающими по мере чтения строк сообщения NMEA 0183 до тех пор, пока не истечет время заданное функцией timeOut() или не будет встречена строка с уже прочитанным идентификатором.
- Максимальное время отводимое для чтения данных по умолчанию равно 2000 мс.
- Функцию достаточно вызвать однократно в коде setup().
- Пример:
Функция timeZone();
- Назначение: Установить / получить часовой пояс.
- Синтаксис: timeZone( [±ЧАС] );
- Параметры:
- float ±ЧАС — количество часов на которое нужно сдвинуть время относительно UTC (±12).
- Возвращаемое значение:
- float ±ЧАС — установленное количество часов на которое сдвинуто время относительно UTC.
- Примечание:
- Если функция вызвана без параметров, то она только возвращает текущий часовой пояс.
- Если функция вызвана с указанием количества часов (±12), то прочитанные дата и время будут сдвигаться на указанное количество часов, пока временная зона не будет изменена.
- Если функция вызвана с параметром GPS_AutoDetectZone , то часовой пояс будет вычисляться автоматически, по координатам долготы. Стоит учесть, что часовой пояс будет вычисляться только по долготе, не учитывая политической карты и летнего времени. Например, долгота 37.5° проходит через г. Москва и делит его на 2 часовые зоны: +2 и +3.
- Функцию достаточно вызвать однократно в коде setup().
- По умолчанию установлен часовой пояс UTC+3.
- Пример:
Данные читаемые из сообщения NMEA 0183:
Обращение к функции read() приводит к чтению данных из текстового сообщения NMEA 0183 отправляемого GPS-модулем по шине UART в следующие переменные:
- float latitude — Широта (±90.0°).
- float longitude — Долгота (±180.0°).
- uint16_t altitude — Высота над уровнем моря (±32767м).
- uint8_t speed — Скорость (0-255 км/ч).
- float course — Курс (±180.0°).
- uint8_t satellites[GPS_ACTIVE] — Количество активных спутников (0-12).
- uint8_t satellites[GPS_VISIBLE] — Количество наблюдаемых спутников.
- float PDOP — Пространственный геометрический фактор ухудшения точности (0-25.5).
- float HDOP — Горизонтальный геометрический фактор ухудшения точности (0-25.5).
- float VDOP — Вертикальный геометрический фактор ухудшения точности (0-25.5).
- uint8_t seconds — Секунды (0-59).
- uint8_t minutes — Минуты (0-59).
- uint8_t hours — Часы (1-12).
- uint8_t Hours — Часы (0-23).
- uint8_t midday — Полдень (0-am, 1-pm).
- uint8_t day — День месяца (1-31).
- uint8_t weekday — День недели (0-воскресенье, 1-понедельник, . , 6-суббота).
- uint8_t month — Месяц (1-12).
- uint8_t year — Год (0-99).
- uint16_t Year — Год (0-65’535).
- uint32_t Unix — Unix время (0-4’294’967’296 сек).
Переменные PDOP, HDOP и VDOP указывают как сильно снижается точность вычисления координат от текущего положения спутников в пространстве: 0-1 идеальная точность, 2-3 отличная точность, 4-6 хорошая точность, 7-8 средняя точность, 9-20 точность ниже среднего, больше 21 — плохая точность.
Содержание данных в строках сообщения NMEA 0183:
Переменные: | Идентификаторы строк сообщения NMEA 0183 отправляемого модулем: | ||||||||
---|---|---|---|---|---|---|---|---|---|
latitude longitude | GGA | GLL | RMC | — | — | — | — | — | — |
altitude | GGA | — | — | — | — | — | — | — | — |
satellites | GGA | — | — | — | — | — | — | — | — |
speed course | — | — | RMC | VTG | — | — | — | — | — |
PDOP VDOP | — | — | — | — | — | GSA | — | — | — |
HDOP | GGA | — | — | — | — | GSA | — | — | — |
Hours hours minutes seconds midday | GGA | GLL | RMC | — | ZDA | — | — | DHV | GST |
day weekday month year Year | — | — | RMC | — | ZDA | — | — | — | — |
Unix | (GGA || GLL || RMC || ZDA || DHV || GST ) && ( RMC || ZDA ) | ||||||||
Массив | — | — | — | — | — | GSA | GSV | — | — |
Наличие в составе сообщения NMEA 0183, отправленного модулем, строки с любым из указанных в таблице идентификатором, приводит к заполнению данными соответствующей переменной.
Проверка достоверности полученных данных:
Проверить достоверность полученных данных можно при помощи следующих переменных:
- uint8_t errTim — Ошибка времени. Переменная может принимать следующие значения:
0 — нет ошибок, 1 — сообщение NMEA 0183 не прочитано, 2 — время недостоверно. - uint8_t errDat — Ошибка даты. Переменная может принимать следующие значения:
0 — нет ошибок, 1 — сообщение NMEA 0183 не прочитано, 2 — дата недостоверна. - uint8_t errPos — Ошибка координат. Переменная может принимать следующие значения:
0 — нет ошибок, 1 — сообщение NMEA 0183 не прочитано, 2 — координаты недостоверны. - uint8_t errCrs — Ошибка скорости и курса. Переменная может принимать следующие значения:
0 — нет ошибок, 1 — сообщение NMEA 0183 не прочитано, 2 — скорость и курс недостоверны.