GPS-приймач u-blox NEO-6M – проектування мініатюрного Lua-драйвера для ESP8266 з прошивкою NodeMCU та програмним soft-UART інтерфейсом

Ми маємо намір підключити до контролера ESP8266 з прошивкою NodeMCU та мовою Lua, GPS-приймач u-blox NEO-6M. То ж, для чого нам потрібен драйвер і чому ми його програмуємо на рівні Lua?

Драйвер потрібен для того, щоб забезпечити програмний інтерфейс (API) взаємодії між двома пристроями, які не підтримують комунікацію один з одним, але мають сумісні інтерфейси, достатні, щоб організувати роботу протоколу взаємного обміну даними.

Прошивка NodeMCU славетна тим, що вже має велику кількість C-модулів на вибір, що фактично виконують роль драйверів, написаних на Сі, та прокладають програмний інтерфейс на рівень Lua. 

Примітка. Статтю про модулі, можна прочитати за посиланням:

Але у випадку з GPS-приймачем, такого готового модуля – драйвера, у прошивці немає. І тому нам потрібно написати свій драйвер. Ми могли б написати свій драйвер на рівні Сі, але в такому випадку, потрібно випускати свою версію прошивки NodeMCU, що абсолютно не входить до наших планів, адже потім цей модуль постійно потрібно буде тягнути самотужки за собою з версії у версію прошивки і так далі і тому подібне.

Ще один, шлях загальнодоступний для вирішення задачі, це написати драйвер на Lua. 

Як не дивно, але це перевірений власним досвідом, а також закріплений спільнотою розробників прошивки NodeMCU, надійний, швидкий і зручний підхід. На рівні Lua вже написано купу драйверів. Приклади можливо подивитися тут: 

https://github.com/nodemcu/nodemcu-firmware/tree/master/lua_modules

І ця робота постійно кипить у спільноті. На Сі зараз під NodeMCU пишуться лише ті драйвери зовнішніх пристроїв, які складно, чи не продуктивно розробляти на Lua.

Ми теж для своїх продуктів розробили багато низькорівневих драйверів для АЦП, розширювачів портів, ІЧ-портів, аналогових, дискретних та цифрових сенсорів і актюаторів.

Перш ніж перейти до безпосереднього програмування драйвера, ми спробуємо спроектувати його дизайн і частково опишемо цей процес у даному тексті. – Перерахуємо наші власні вимоги до того, який драйвер GPS нас влаштував би, з усвідомленням, що ми його плануємо застосовувати всередині мікроконтролера ESP8266 з прошивкою NodeMCU та мовою Lua – середовищі з асинхронним виконанням коду, що орієнтоване на обробку подій.

Те, що ми зразу обрали GPS-приймач u-blox NEO-6M, вже підказує, що ми приблизно знаємо його можливості і оцінили з нашого досвіду роботи з цим модулем, що теоретично і потенційно він нас влаштовує у якості джерела даних.

А яка ж у нас задача? – Наша задача зробити такий драйвер, який дозволить з мінімальним об’ємом пам’яті та інших ресурсів контролера, отримувати з “сенсора” необхідний набір даних для звичайних (простих, щоденних) користувацьких застосувань.

Серед простих задач окреслимо, в якості прикладу, задачу періодичного отримання координат розташування з низькою частотою. Відтак, оберемо тривалий період розрахунку даних (хвилини), отримання ж сирих даних з сенсора – буде відбуватися по волі їх надходження через програмний UART. От таку задачу і будемо тримати за еталон під час проектування.

До користувацьких даних віднесено всі корисні для користувача складові повідомлень, які вміє надсилати наш GPS-приймач u-blox NEO-6M:

  • розташування: широта, довгота;
  • висота над рівнем моря;
  • горизонтальні швидкість і напрямок руху відносно поверхні.

Такі дані можуть міститися у різних повідомленнях, і наша задача:

  • полягатиме у тому, щоб їх оптимізувати;
  • і якомога компактніше реалізувати їх обробку і підготовку.

Примітка: статтю про типи повідомлень NMEA і їх вміст, можливо прочитати за посиланням:

У переліку ж складних задач, які ми свідомо відкидаємо і на які не розраховуємо дизайн нашого драйвера, лишаються задачі побудови маршрутів, онлайн гео-локація, навігація у приміщенні і тому подібні сценарії, які вимагають потужної системи реального часу.

І от тепер можемо переходити до розробки власних вимог щодо вирішення задачі, яку ми щойно окреслили.

Перерахуємо вимоги до драйвера, які плануємо втілити під час програмування. І щоб зручніше їх класифікувати, зведемо їх у таблицю:

ВимогаРеалізація
1Швидкісний і простий обробник подій інтерфейсу softuart;обов’язково
2Режими роботи обробника подій softuart:
2.aперіодичне прослуховування UART подій, кожних Х хвилин;бажано
2.bпостійна обробка вхідних даних за подіями UART;обов’язково
3Детектування наявності GPS-приймача;обов’язково
4Приймач має займати (задіяно тільки Rx порт ESP8266) 1 GPIO портобов’язково
5Програмна ознака готовності, актуальності та достовірності даних з приймачабажано
6Отримання користувацьких даних:
6.aпро розташування :
широта, градуси;індикатор північ / південь;
довгота, градуси;
– індикатор схід / захід;
обов’язково
6.bпро висоту :
висота над еліпсоїдом, м;
різниця висоти між геоїдом та рівнем моря;
бажано
6.cпро рух :
швидкість руху, км/год;
– напрямок руху, градуси;
бажано
7Контроль якості даних з UART шляхом перевірки checksum-коду для отриманих сирих данихбажано
8Період перерозрахунку користувацьких даних має задаватися користувачем і бути в межах від 1 хвилини до Х хвилинобов’язково
9Надсилання даних на інтерфейс UART для інтеграції з іншими системамибажано

Коментарі до таблиці вимог:

  1. Швидкісний і простий обробник подій інтерфейсу softuart. 

Оскільки наш Lua-драйвер працює через події C-модуля softuart, ми повинні написати швидкісний і простий обробник події, що буде підключено у якості callback. Якщо ми дозволимо собі складну обробку події, то наш драйвер буде викликати спрацювання Software Watchdog, який буде постійно рестартувати контролер.

  1. Режими роботи обробника подій softuart. 

Бажано забезпечити два режими роботи з вхідними подіями – періодична обробка подій, або постійна обробка подій. Якщо виявиться, що С-модуль softuart, дозволяє програмно відключати обробник подій на програмному порту UART без перезапуску контролера, то ми плануємо реалізувати у драйвері можливість лише періодичного отримання подій, і тим самим спробувати значно розвантажити мікроконтролер для інших задач, що виконуються паралельно з кодом нашого драйвера. Вважаємо, що призначення нашого драйвера не вимагає неперервної обробки даних про розташування, що можуть і будуть надходити з приймача u-blox NEO-6M. А тому, запланували собі як вимогу, реалізацію двох режимів, якщо це можливо.

  1. Детектування наявності GPS-приймача. 

Оскільки інтерфейс UART не дає нам інших інструментів з детектування наявності приймача у системі, плануємо реалізувати цю функцію нашого драйвера через отримання хоча б якихось даних, схожих на ті, що очікуємо в межах певного таймауту по часу. Обов’язковим повідомленнях у межах NMEA, є GPRMC (мінімальні рекомендовані дані), які періодично надсилає u-blox NEO-6M за будь-яких умов. Це повідомлення і буде для нас ознакою наявності зв’язку і нормальної роботи GPS-приймача.

  1. Приймач має займати (задіяно тільки Rx порт ESP8266) 1 GPIO порт. 

Під час ініціалізації модуля softuart, ми зобов’язані обрати і вказати два піни (Rx і Tx), але оскільки ми завжди намагаємося оптимізувати використання портів GPIO контролера ESP8266, а також через те, що ми не використовуємо передачу команд від контролера до GPS-приймача, ми маємо надію використовувати порт Tx, для інших задач. Цю можливість потрібно перевірити. Станом на зараз, ми лише знаємо з документації, що пін обраний на роль Tx, може одночасно використовувати декількома екземплярами модуля softuart:

“Note that rx pin cannot be shared between instances but tx pin can.”

  1. Програмна ознака готовності, актуальності та достовірності даних з приймача. 

В якості такої ознаки, ми плануємо ввести окрему змінну, яка буде повертати агрегований дискретний стан (1/0). 

Як ознаку готовності даних – застосуємо наявність необхідних користувацьких даних. Актуальність будемо визначати по часу, з моменту оновлення даних. Найбільші запитання до достовірності даних, адже її досить складно розрахувати базуючись на відповідних параметрах з NMEA повідомлень. Але ми спробуємо.

  1. Отримання користувацьких даних. 

Для зберігання користувацьких даних, заради яких і розробляємо драйвер, плануємо створити масив властивостей типу gps_point={}, який буде періодично оновлюватися із заданою користувачем драйвера частотою.

  1. Контроль якості даних з UART шляхом перевірки checksum-коду для отриманих сирих даних. 

Оскільки програмний UART, схильний псувати повідомлення “сміттям”, нам бажано перевіряти кожне повідомлення, що декодує парсер, на коректність отриманих драйвером сирих даних з приймача GPS. З цих міркувань, плануємо реалізувати передачений виробником GPS-приймача механізм перевірки контрольної суми.

  1. Період перерозрахунку користувацьких даних має задаватися користувачем і бути в межах від 1 хвилини до Х хвилин. 

Ми вже кілька разів згадували цей періодичний процес у попередніх коментарях. Йдеться про функцію, яка має оновлювати користувацькі дані, а також змінні різноманітних програмних ознак. Оновлення запускається за таймером, таймаут якого обрав користувач нашого драйвера. 

З нашого досвіду, у стаціонарних системах, такий таймаут може бути 5, або навіть 10 хвилин. Але ми маємо передбачити можливість встановлення даного періоду користувачем самостійно. 

У будь-якому випадку, ми не радимо робити цей “головний” період меншим за хвилину, адже це призведе до надмірного навантаження на контролер, а додаткової корисності не дасть.

  1. Надсилання даних на інтерфейс UART для інтеграції з іншими системами.

Бажано реалізувати спеціальний потік повідомлень з користувацькими даними та даними налагодження в апаратний UART консолі розробника ESP8266, щоб забезпечити можливість автономної інтеграції модуля ESP8266 з підключеним до нього u-blox NEO-6M, в якості “сенсора” у інші системи, які мають можливість отримувати дані з UART. 

Ця можливість має особливо зацікавити розробників рішень, в яких взагалі немає потреби програмувати – включили живлення і отримуєте вже оброблені, користувацькі дані.

На виході отримуємо драйвер, який інтегровано через програмний UART, що періодично готує необхідні нам користувацькі дані про розташування, як от, наприклад, але не обмежуючись:

Далі ці дані можливо використовувати в інших складових частинах розумного пристрою, який задумав користувач даного драйвера.

Ось мабуть і все, що на даному етапі ми хотіли розповісти про проектування нашого власного драйвера на Lua для прошивки NodeMCU.

Сподіваємося, що ця стаття буде користрою не лише для нас, як можливість підсумувати свої плани з розробки, а і для всіх хто її прочитав.

Самі ж, тим часом, можемо переходити до програмування.

Бажаємо успіхів!