Подключение микроконтроллера к GPS приемнику
Возникла потребность в приборе, который бы показывал координаты текущего местоположения и отклонения от заложенных в него координат (контрольных точек). Покупать ради этого навигатор, который стоит от 800 грн и выше нет возможности, да и потребности в отображении карты также нет. Поэтому было принято решение «завязать» GPS приемник с микроконтроллером (МК). Эта идея витала в воздухе довольно давно, только GPS-приемника на руках не было. В данной статье хочу ознакомить Вас с тем, как подключить МК к GPS-приемнику.
Введение
На днях удалось взять GPS-приемник для экспериментов (см. рисунок 1) у друга aka Kalina. GPS-приемник (далее просто приемник) модель – MARS-200AS с ТТЛ выходом и разъемом PS/2. Документация на данный прибор здесь [1].
* Комментарий автора.
Стоит отметить, что данный прибор имеет и USB исполнение, но изначально приобретался для возможности подключения к МК. Поэтому при работе приемника с ПК необходимо подключать его через RS232 или USB конверторы. Данный приемник поддерживает протокол NMEA-0183, битрейт 9600 (указано на корпусе приемника), напряжение питания 5В. Теория по стандарту NMEA-0183 была взята из www.gps-profi.ru/nmea.php
Итак, протокол данного приемника передает такую информацию:
GGA – информация о фиксированном решении;
GLL – данные широты и долготы;
GSA – общая информация о спутниках;
GSV – детальная информация о спутниках;
RMC – рекомендованный минимальный набор GPS данных;
VTG – вектор движения и скорости;
ZDA – дата и время.
Протокол обмена представляет собой пересылаемые с периодом в 1 сек данные, которые имеют строго определенную последовательность данных и представляют собой символы из ASCII таблицы символов.
Практическая часть
Для того чтобы та каша в голове, которая образовалась при прочтении теории о протоколе, упорядочилась я решил подключить приемник к ПК и с помощью монитора портов содрать протокол обмена. Связь проводил с помощью программы SkyTraq 0.4.263 [2], протокол сдирал утилиткой. После экспорта данных из нее и подредактировав, я анализировал код в WinHex [3]. Для удобства анализа пользовался таблицей ASCII [4].
Числовые данные представлены кодами каждой цифры из таблицы ASCII соответсвенно.
** Комментарий автора.
Данный дамп получен сразу после включения питания и запуска обмена, т.е. приемник еще на стадии холодного старта и не видит спутников. Учтите, что данные в таблице после символов <CR><LF> указаны в HEX (16-тиричном формате).
Итак, все сообщения с приемника начинаются со значка $ (0×24), затем GP (0×47,0×50) после этих трех байтов идет три байта означающие, какая информация в данном информационном пакете заключена: RMC, VTG, GGA, GSA, GSV, GLL. Различные данные в пакете разделены между собой запятой «,» (0×2C). В конце после информационных данных стоит звездочка «*» (0×2A). Она означает, что сейчас будет два байта контрольной суммы, затем символы CR LF (0×0D, 0×0A). Это команда – возврат каретки, по сути конец пакета.
Ниже выкладываю дамп той части, где приемник видит спутники и выдает информацию о местположении и так далее:
$GPRMC,185536.00,A,5051.12898,N,02873.41497,E,0.000,,170610,,,A*77 244750524D43 2C 3138353533362E30302C41 2C 353035312E31323839382C4E 2C30323837332E 3431343937 2C 452C302E303030 2C2C 313730363130 2C2C2C 41 2A37370D0A $GPVTG,,T,,M,0.000,N,0.000,K,A*23 2447505654472C2C542C2C4D2C302E3030302C4E2C302E3030302C4B2C412A32330D0A $GPGGA,185536.00,5051.12898,N,02873.41497,E,1,04,9.82,21.5,M,28.7,M,,*66 2447504747412C3138353533362E30302C353035312E31323839382C4E 2C30323837332E34313439372C452C312C30342C392E38322C32312E352C4D 2C32382E372C4D2C2C2A36360D0A $GPGSA,A,2,31,02,05,10,,,,,,,,,9.87,9.82,1.00*03 2447504753412C412C322C33312C30322C30352C31302C2C2C2C2C2C2C2C2C392E3837 2C392E38322C312E30302A30330D0A $GPGSV,2,1,06,12,38,129,26,31,42,286,31,02,34,054,42,05,21,102,35*71 2447504753562C322C312C30362C31322C33382C3132392C32362C33312C3432 2C3238362C33312C30322C33342C3035342C34322C30352C32312C3130322C33352A37310D0A $GPGSV,2,2,06,10,21,067,37,30,71,148,*70 2447504753562C322C322C30362C31302C32312C3036372C33372C33302C37312C3134382C2A37300D0A $GPGLL,5051.12898,N,02873.41497,E,185536.00,A,A*6F 244750474C4C2C353035312E31323839382C4E2C30323837332E34313439372C452C31 38353533362E30302C412C412A36460D0A
Поскольку реализовывать весь данный протокол я пока не собираюсь, так как цель – вывод текущих координат и вывод требуемых координат на ЖКИ (индикатор на жидких кристаллах). Для этой цели подойдет пакет с заголовком RMC. Он включает в себя:
$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A
где: RMC – заголовок, 123419 – UTC время (12:34:59), А – статус (А – активный, V – игнорировать), 4807.038,N – широта (48 градусов 07.038 минут северной широты), 01131.000,Е – долгота (11 градусов 31.000 минута восточной долготы), 022.4 – скорость (в узлах), 084.4 – направление движения (в градусах), 230394 – дата (23 марта 1994 года), 003.1,W – магнитные вариации.
Сравним с посылкой, которую я «задампил»:
$GPRMC,185536.00,A,5051.12898,N,02873.41497,E,0.000,,170610,,,A*77
Замечу, что после долготы (Е) идет скорость в узлах, т.к. я сидел за компьютером, то естественно скорость была нулевая, но после нее идет направление движения в градусах, у меня сразу идет запятая, затем дата 170610, и после нее идти должны магнитные вариации, вместо этого три запятых и буква А. Таким образом, если какие-либо данные неуместны или не вычисленны для данного момента, то либо ставятся нули, либо просто ставятся запятые по количеству пропущенных значений.
Итак, данное сообщение нас полностью устраивает, так как содержит: координаты, дату и время. Кроме того, еще скорость и направление, но пока мы их не будем использовать. Таким образом, обработка принятых данных будет сводиться к следующим этапам:
- определение начала $ пакета и выделения команды GPRMC;
- выделение данных о времени 185536.00;
- выделение широты и долготы 5051.12898,N,02873.41497,E;
- выделение даты 170610;
- контрольная сумма и конец сообщения.
Стоит также отметить, что конец определенного типа данных можно определить по запятой после него. Также, если не учитывать дату, то для упрощения обработки данных, после информации о долготе, нужно ожидать условие контрольной суммы и конца сообщений, остальные данные можно пропустить (но в этом случае достоверность данных нельзя будет определить по контрольной сумме).
С этим вроде бы разобрались. Теперь перейдем к схеме электрической принципиальной и разработке алгоритма…
В предыдущей части мы исследовали протокол NMEA -0183 и разобрались с пакетами данных, которые шлет приемник. Осталось определиться, что из себя будет представлять прибор и что он будет выполнять. Реализовать я его собираюсь на МК фирмы Атмел ATmega8L и ЖКИ NOKIA 3310.
Задача*** прибора:
- с компьютера залить контрольные точки, а затем, при подключении GPS-приемника, выборочную точку;
- вывод на ЖКИ текущего местоположения (координаты) и координаты требуемой точки.
*** Комментарий автора.
Усложнять себе задачу – указывать в какую сторону идти и так далее, я пока не буду. Если и захочется реализовать данную «фичу», тогда допишу и выложу в отдельной статье.
Памяти МК с лихвой хватит для ASCII таблицы, программной реализации обмена с ЖКИ и приема и обработки данных. Кодить буду на ассемблере. Поскольку все равно прийдется реализовывать выбор пакетов по содержимому, а также определять начало пакета, блок данных, контрольную сумму и конец данных, то по такому же принципу реализую обмен с ПК. Для этого начало пакета данных будет $GPPCD (GP Personal Comuter Data), окончание такое же как и в приемнике *CS CR LF (CS- checksum).
На данной схеме частота кварца ZQ1 выбрана равной 7.3728 MHz. Данная частота выбрана из даташита на ATmega 8, так как при данной частоте работа с последовательным портом USART происходит с нулевым процентом ошибок. Питание устройства я решил сделать от 9-ти вольтовой «Кроны». Диод Шоттки VD1 защищает схему от переполюсовки, стабилизатор питания 78L05 обеспечивает 5В питание, последовательно включенный по питанию диод VD2 понижает 5 В до 3.8 В для питания ЖКИ. Выводы USART выведены на разъем XS4 (female). SW1 – тумблер питания, SA1-SA3 – кнопки управления прибором. Данные кнопки думаю реализовать ввиде джойстика от мобильника. Конденсаторы С3…С5 для антидребезга при нажатии кнопок, чтобы не «заморачиваться» программно. Разъем XS3 предназначен для подключения ЖКИ от мобильного телефона Nokia 3310.
Чтобы не усложнять программу (во вред универсальности), я буду анализировать только необходимые байты – остальные же пропускать. Т.е. при анализе протокола я анализирую символ «$» начала пакета и три символа команды – «GPR», остальные три пропускаю вместе с запятой. Далее идут данные о времени, их я анализаирую и после долготы жду только условие возврата каретки <CR><LF> (0×0D 0×0A).
Предварительные итоги…
Итак. После кропотливой работы над данным устройством и обсуждения с человеком, которому оно требовалось – получилось такое:
- никакого ввода данных трекерных точек;
- никакой связи с ПК;
- никакого ручного ввода координат (позже я подумал о вводе координат вручную).
Поскольку я пытался упростить обработку информации, то координаты первой точки занимали бы 19 байт. А с объемом ЕЕПРОМ в 512 кБ сильно много не запишешь – максимум 26 точек. В итоге получился прибор для отображения текущих координат и времени. Клавиатура не задействована, подсветка тоже. Анализ происходит по принятию заголовка $GPRMC. Я адаптировал и упростил обработку данных конкретно для моего приемника. А судя по описаниям протокола, приемники различных фирм могут выдавать в одних и тех же заголовках разное количество символов.
Посылка с нумерацией байтов отображена в таблице 2 (выделил только часть заголовка, который будем анализировать):
Для анализа протокола назначим регистр состояния StReg. Где биты в нем использовал как флаги состояния StRx, StHd, StDt, StStrt, StStop. Где:
StRx – флаг приема байта, устанавливался при получении байта по USART;
StHd – флаг приема заголовка. Устанавливался тогда когда получен заголовок $GPRMC;
StStrt – флаг приема байта начала сообщения, устанавливался при приеме символа $;
StStop – флаг окончания приема пакета, устанавливался после получения 45 байта (конец «полезных» байт пакета).
Анализ начала сообщения и заголовка я сделал в обработчике прерывания по USART. Рассмотрим подпрограмму обработки:
;************* Обработка прерывания по приему байта ReceiveByte: In UBR_R,UDR Sbrs StReg,StStrt ; пропустить если установлен флаг начала сообщения Rjmp R_st ; прыжок на проверку байта начала сообщения Sbrs StReg,StHd ; пропустить если установлен флаг заголовка сообщения Rjmp R_Header ; прыжок на проверку байта заголовка Inc Count Cpi Count,20 ; данная проверка счетчика сделана для того чтобы определить когда появятся координаты breq zpt ; изначально пока приемник не настроился и не определил координаты – он гонит в этих строках запятые RB_1: Cpi Count,45 ; проверка счетчика равенство последнему байту 45 Brge End_GP ; если равен – прыжок на метку выхода обработки пакета Sbr StReg,StRx_m ; установка флага приема байта (устанавливается только после принятия заголовка) Reti ; выход из прерыванияzpt: cpi UBR_R,’,' ; проверка 20 байта на равенство знаку «,» brne RB_1 ; если равен – тогда конец обрабатываемого пакета End_GP: ; Конец принятого сообщения (для нужной нам части пакета) Clr StReg ; очищаем регистр состояния Clr Count ; очищаем счетчик байтов пакета Sbr StReg,StStop_M ; устанавливаем флаг конца сообщения Sbr StReg,StRx_m ; устанавливаем флаг приема байта reti R_st: Cpi UBR_R,’$' ; условие начала сообщения было? Breq StartSet ; да прыжок на метку Reti R_Header: ; проверка на прием заголовка (байты 2-4) Cpi Count,1 ; проверка на литеру »G» Breq G_Lit Cpi Count,2 ; проверка на литеру »P» Breq P_Lit Cpi Count,3 ; проверка на литеру »R» Breq R_Lit Return: ; выход Clr Count ; очистка счетчика Cbr StReg,StStrt_m ; очистка бита начала сообщения Cbr StReg,StRx_m ; очистка бита приема байта Cbr StReg,StHd ; очистка бита приема заголовка reti StartSet: ; Установка флага условия СТАРТ ($) Sbr StReg,StStrt_m ldi Count,1 reti G_Lit: Cpi UBR_R,’G’ brne Return inc Count reti P_Lit: Cpi UBR_R,’P’ brne Return inc Count reti ;***** Проверка на команду RMC****** R_Lit: Cpi UBR_R,’R’ brne Return Sbr StReg,StHd_m inc Count reti
Где:
UBR_R – регистр принятого байта, StReg – регистр статуса, Count – регистр счетчик принятых байтов.
Для анализа были использованы только первые 4 байта.
В основном теле программы определяем или установливаем флаг StRx (если да, то сохраняем принятый байт в соответствующую ячейку ОЗУ, в зависимости от номера байта). С данного ОЗУ ведем обновление значений на экране ЖКИ. А также в конце проверяем или установливаем флаг StStop (если установлен, тогда обновляем данные на экране ЖКИ).
Заключение
Собранное устройство – всего лишь один из простейших вариантов чтения данных с GPS модуля и обработки координат. Я использовал программный вывод данных на ЖКИ. Используя аппаратный SPI для ЖКИ можно в разы уменьшить время вывода данных на экран и освободить ядро МК для обработки других данных. На основе данных модулей можно делать множество интересных устройств. Например, велокомпьютер с GPS, причем не обязательно выводить карту на экран, можно просто периодически сохранять точки на SD-card и затем уже дома на ПК просмотреть свой маршрут. Можно встраивать в модели машин, роботов, либо просто для контроля местоположения или для четко запрограммированного маршрута и его корректировки. При комбинировании с GSM модемами есть возможность следить за объектом, на котором установлен модуль****. Применение данных модулей ограничивается только Вашей фантазией и функциональностью конкретного типа модуля.
**** Комментарий автора.
Сейчас широко распространен это метод для слежения за грузоперевозками: координаты передаются по GSM или GPRS каналам на сервер, где строится маршрут объекта.