/De10-Lite_HDL_GPS

Simple verilog project with ability to connect to GPS module using UART and parse NMEA coordinates using finite state machine

Primary LanguageVerilogMIT LicenseMIT

Задание

GPS трекер на ПЛИС. Подключить модуль GPS к ПЛИС, реализовать считывание получаемых координат о местоположении устройства и их накопление в памяти ПЛИС. Реализовать передачу хранимых координат на компьютер через UART соединение (USB) и индикацию текущих координат на внешнем дисплее или и 7-сегментном индикаторе.

Теоретические сведения

GPS модуль neo-6 поддерживает три протокола:

  1. NMEA – самый популярный протокол, передает данные в текстовом виде (колировка 8- битный ASCII), I/O
  2. UBX – проприетарный протокол компании u-blox, передает данные в бинарном формате, I/O
  3. RTCM – открытый протокол, I

А также три интерфейса для передачи данных:

  1. UART
  2. USB
  3. DDC

В нашей работе использовалась связка протокола NMEA и интерфейса UART.

Описание протокола NMEA

NMEA 0183 – стандарт определяющий текстовый протокол связи навигационного оборудования, особенно популярен в модулях GPS приемников, по нескольким причинам:

  1. Сообщения легко обрабатывать, за счет их простой структуры
  2. Каждое сообщение занимает мало памяти
  3. Сообщения передаются в текстовом, а не в бинарном виде, поэтому необработанное сообщение удобно читать человеку
  4. Протокол можно потенциально расширить новыми типами сообщений
  5. Каждое сообщение передает свою контрольную сумму, что позволяет проверять корректность принятого пакета

Формат сообщений NMEA 0183:

  1. "$" – маркер начала сообщения
  2. 5-буквенный идентификатор сообщения, определяет тип передаваемого сообщения:
    1. Первые две буквы – идентификатор источника сообщения, в случае GPS модуля это всегда "GP"
    2. Последние три буквы – тип сообщения
  3. Список данных сообщения. Количество и формат этих данных зависит от сообщения, однако для передаваемой информации обязательны следующие признаки:
    1. Все данные разделяются запятыми – ","
    2. В случае отсутствия каких-либо данных в сообщении запятые все равно ставятся (возможна ситуации по типу ",,,") – количество запятых в определенном типе сообщения постоянно и не зависит от данных, это сделано для упрощения процесса обработки сообщения
  4. "*" – маркер начала контрольной суммы
  5. 2 символа контрольной суммы – контрольная сумма считается как XOR-сумма всех символов между "$" и "*" не включительно. Полученная сумма представляется в шестнадцатеричном виде в двух ASCII символах (буквы передаются в верхнем регистре)
  6. "<CR><LF>" – 2 символа, маркирующих конец сообщения:
    1. <CR> – ASCII carriage return, шестнадцатеричное значение – 0D
    2. <LF> – ASCII line feed, шестнадцатеричное значение – 0A

Максимальная длина сообщения ограничена 82 символами.

В данной работе обрабатывалось одно NMEA сообщение – GPGLL (Geographic Position Latitude/Longitude)

Формат сообщения GPGLL:

$GPGLL,DDMM.MMMMM,S,DDDMM.MMMMM,S,HHMMSS.SS,S*CC

  1. $GPGLL – идентификатор сообщения
  2. Координата широты
  3. Буква N (север) или S (юг)
  4. Координата долготы
  5. Буква E (восток) или W (запад)
  6. Текущее UTC время в данной позиции
  7. Статус сообщения:
    1. A – валидные данные
    2. V – некорректные данные (такой статус выставляется например когда GPS модуль еще не подключился к спутникам)
  8. Контрольная сумма
  9. <CR><LF>

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

$GPGLL,3723.2475,N,12158.3416,W,161229.487,A*2C

Описание интерфейса UART

UART – универсальный асинхронный приемопередатчик. Преобразует передаваемые данные в последовательный вид так, чтобы было возможно передать их по одной физической цифровой линии другому аналогичному устройству.

Передача данных в UART осуществляется по одному биту в равные промежутки времени. Этот временной промежуток определяется заданной скоростью UART и для конкретного соединения указывается в бодах (что в данном случае соответствует битам в секунду). Существует общепринятый ряд стандартных скоростей: 300; 600; 1200; 2400; 4800; 9600; 19200; 38400; 57600; 115200; 230400; 460800; 921600 бод. Скорость (S) и длительность бита (T) связаны соотношением T=1/S.

Помимо информационных бит, UART автоматически вставляет в поток синхронизирующие метки, так называемые стартовый и стоповый биты. При приёме эти лишние биты удаляются из потока. Обычно стартовый и стоповый биты обрамляют один байт информации (8 бит), при этом младший информационный бит передаётся первым, сразу после стартового. Обрамленные стартом и стопом биты являются минимальной посылкой. Некоторые реализации UART используют два стоповых бита при передаче для уменьшения вероятности рассинхронизации приёмника и передатчика при плотном трафике.

Принято соглашение, что пассивным (в отсутствие потока данных) состоянием входа и выхода UART является логическая 1. Стартовый бит всегда логический 0, поэтому приёмник UART ждёт перепада из 1 в 0 и отсчитывает от него временной промежуток в половину длительности бита (середина передачи стартового бита). Если в этот момент на входе всё ещё 0, то запускается процесс приёма минимальной посылки. Для этого приёмник отсчитывает 9 битовых длительностей подряд (для 8-битных данных) и в каждый момент фиксирует состояние входа. Первые 8 значений являются принятыми данными, последнее значение проверочное (стоп-бит). Значение стоп-бита всегда равно 1. Если реально принятое значение иное, UART фиксирует ошибку.

alt text

Выполнение работы

Использованные устройства

  1. Плата Terasic DE10-Lite (использует Intel MAX 10)
  2. GPS модуль GY-GPS6MV2
  3. Керамическая антенна для GPS
  4. Breadboard и провода
  5. Плата Arduino и преобразователь напряжения (для проверки алгоритмов и их отладки)
  6. Компьютерс Intel Quartus Prime Lite 16.1

Разработка модуля обработки сообщений с GPS модуля

Для обработки сообщений с GPS модуля был разработан простой конечный автомат:

alt text

  1. Стартовое состояние (состояние покоя) – автомат ожидает сигнала от UART модуля, сообщающего что получены данные и по приходу этого сигнала проверяет данные, если пришло "$" – переходит в следующее состояние:

alt text

  1. Состояние сохраняет полученные с UART данные в массив NMEA[23:0] пока не встретит ",". Когда автомат встречает запятую он проверяет условие NMEA == "GLL", т.е. пришла ли необходимая команда и если условие выполняется – переходит в следующее состояние. Если с GPS модуля пришла другая команда – автомат возвращается в стартовое состояние

В массив NMEA сохраняются только последние три байта полученные с UART, т. к. именно они определяют тип сообщения, а остальная информация не требуется

alt text

  1. Данное состояние обрабатывает координату широты – оно записывает первые три ASCII байта с координатами в массив LAT[23:0]. Как только это состояние встречает символ запятой – оно переходит в следующее состояние

alt text

  1. В данном состоянии можно обрабатывать значение север/юг широты. Используемая плата имеет всего 6 семисегментных индикаторов, на 3 из которых выводилась координата широты, а на 3 других – координата долготы – поэтому значения север/юг широты и восток/запад долготы не обрабатывались, т.к. их некуда выводить, однако добавить их обработку не составит труда, т.к. состояние для этих случаев уже разработано и нужно просто записать полученные данные в желаемую переменную.

В нашем случае это состояние просто ждало "," и переходило в следующее состояние:

alt text

  1. Данное состояние обрабатывает координату долготы – принцип работы такой же, как и у обработчика координаты широты. Как только встречается символ переноса строки – происходит переход в стартовое состояние – данные которые идут далее нам не интересны

alt text

Данный конечный автомат удобен тем, что его можно легко масштабировать – можно улучшать обработку команды GPGLL и добавлять обработку новых команд – для добавления поддержки других команд необходимо просто добавить в состояние "ReadCMD" переход по другой полученной команде, вставить конечный автомат обрабатывающий параметры этой команды и конечное состояние этого обработчика связать с состоянием "Start" переходом по "<LF>".

В нашем случае обрабатывались только первые три байта координаты широты и долготы по техническим причинам, однако увеличить точность обработки достаточно просто – для этого необходимо увеличить переменную "precision" до необходимого значения точности.

Увеличить размерность массивов LAT и LON – необходимо по одному байту на каждую цифру точности. А также исправить заполнение этих массивов в состояниях "ReadLAT" и "ReadLON":

alt text

alt text

Модуль отображения информации на семисегментном индикаторе

Для отображения шестнадцатеричных значений на семисегментом индикаторе использовался модуль "hex7seg":

alt text

Т. к. с GPS модуля мы получали каждую координату в 1 байте ASCII символа, а один семисегментный индикатор выводит только половину байта, мы использовали простой прием, основанный на особенности кодов цифр в ASCII таблице – все цифры от 0 до 9 выражены кодами от 0x30 до 0x39, причем ASCII код каждой цифры оканчивается именно на эту цифру:

alt text

Поэтому мы передавали на семисегментный индикатор только вторую половину каждого байта координаты, т. к. именно вторая половина содержала необходимую для вывода информацию, а первая половина байта всегда хранила 0x3 (в случае, когда байт представлял цифру):

alt text

Сборка устройства

Сборка устройства не составила особого труда – плата была подключена к компьютеру с установленным Quartus, GPS модуль был подключен к breadboard, землю и питание платы (3.3 В) отправили также на breadboard, а оттуда к соответствующим пинам GPS модуля. Пины RX и TXGPS модуля были отправлены на GPIO[34] и GPIO[35] соответственно. В коде программы все необходимые номера пинов были установлены в PinPlanner и далее использованы в логике программы.

Отладка платы и кода

Для проверки корректности работы UART модуля и модуля обработки GPS координат использовалась плата Arduino на которой была запущена простая программа, которая в зависимости от напряжения на одном из пинов переходила в состояние отправки или приема данных. В случае отправки данных плата просто писала полученные данные в лог, в случае, когда была установлена конфигурация отправки данных – плата отправляла тестовое NMEA сообщение GPGLL на плату:

alt text

Т. к. Arduino и DE10-Lite используют разное напряжение для передачи логической единицы – 5В и 3.3В соответственно, был использован преобразователь напряжения для связывания этих двух устройств.

Итоговый результат

Плата успешно подключилась к GPS модулю и стала получать оттуда сигналы, выданный нам GPS модуль требует достаточно много для подключения к спутникам (может быть больше 40 минут, точное время в нашем случае не замерялось, для уменьшения времени подключения можно поменять антенну).

Пока GPS модуль не был подключен к спутнику он отправлял пустые GPGLL команды, в которых не было координат, а флаг корректности результата был установлен в состояние V (invalid). Как только модуль связался со спутником (об этом сигнализирует мигание синего индикатора) плата начала выводить правильные координаты:

alt text

alt text

Список источников

  1. U-blox neo6 datasheet
  2. Спецификация протокола NMEA 0183
  3. Описание сообщений NMEA 0183
  4. Описание интерфейса UART
  5. DE10-Lite user manual
  6. ASCII table