![](https://habrastorage.org/getpro/habr/upload_files/26b/7dc/cbf/26b7dccbf1e3e32471fa57a3c141a040.gif)
Решаем задачу непрерывной передачи данных от встраиваемой системы c Azure RTOS на персональный компьютер. Рассмотрим проблему с точки зрения наиболее эффективных и доступных способов приёма телеметрии.
Если при использовании UART мы имеем один коммуникационный порт, при использовании USB можем получить несколько портов, то при использовании TCP/IP мы можем одновременно работать c десятками и сотнями портов с разными протоколами. В предыдущей статье было показано как реализовать соединение по TCP/IP и подключиться к интернету через USB. Здесь поднимемся выше и посмотрим что можно выжать из прикладных сетевых протоколов Azure RTOS. Весь проект здесь. В качестве аппаратной платформы выступает плата полифункционального зарядника.
Нам нужно передавать телеметрию. Выбор способа передачи зависит от сетевой инфраструктуры, от объёма данных, от требований масштабируемости, от ограничений на время доставки, … и других вещей. В проекте на базе Azure RTOS хорошо себя показали следующие способы:
Telnet, а также виртуальный COM порт надёжен и работает на самых медленных каналах. На стороне ПК нужна только программа терминал (есть масса таких программ под все операционные системы) и иногда драйвер виртуального COM порта Взаимодействие простое интерактивное и в основном ручное и не в реальном времени. Обмен ведётся данными и командами. Устройство выступает в роли сервера. Взаимодействие типа мастер-слэйв, мастером выступает компьютер. Но возможен асинхронный приём данных. Но не масштабируется на управление одновременно группой устройств в одном окне.
FreeMaster используется совместно со специализированной программой на ПК, которая есть только под Windows. Протокол добавляет незначительную избыточность поверх TCP, может передавать большие массивы данных. Протокол мультиканальный, обмен ведётся данными и командами. Устройство выступает в роли сервера. Взаимодействие типа мастер-слэйв, мастером выступает компьютер. FreeMaster удобен тем что обеспечивает доступ к любым переменным внутри устройства по их символьным именам извлекаемым из elf файла или из специальных таблиц в самом устройстве. Не масштабируется для управления группой устройств, но при отладке одного устройства очень хорош.
Node-RED не имеет какого-то выделенного протокола. Пользователь сам решает какими компонентами организовать обмен. Можно организовать любой способ: мастер-слэйв, равный к равному, публикация-подписка. В нашем случае тестировался вариант мастер-слэйв, подобный принятому в FreeMaster. Для приёма и анализа больших объёмов данных Node-RED не очень приспособлен. Но среда Node-RED открыта для сторонних расширений, поэтому от неё можно ожидать неожиданных преимуществ. Может масштабироваться для управления одновременно группой устройств.
MATLAB Simulink включает в стандартную библиотеку клиентские варианты компонента для установления связи по TCP. Взаимодействие типа мастер-слэйв, мастером выступает компьютер. Более подробно как работает этот канал связи было рассмотрено в этой статье. Но в целом у MATLAB такая же гибкость как и у Node-RED, все решают применяемые компоненты. Правда MATLAB умеет работать в реальном времени, легко обрабатывает гигабайтные объёмы данных и этим отличается от всех остальных средств упомянутых здесь.
FTP клиент в дивайсе работает с FTP сервером на ПК. Взаимодействие мастер-слэйв, мастером выступает устройство. Управления устройством как таковым возможно опосредовано через размещение объявлений на FTP сервере. Решение хорошо масштабируется для управления группой устройств, и устройствами за NAT и в глобальной сети. Доступны бесплатные FTP серверы под большинство операционных систем. Я использую FileZilla.
FTP сервер в дивайсе взаимодействует с FTP клиентом на ПК. Взаимодействие мастер-слэйв, мастером выступает компьютер. Взаимодействие интерактивное, ручное и не в реальном времени. Передача команд возможна через запись командных файлов на FTP. Несмотря на недостатки этот вариант весьма привлекателен, когда устройство само не в состоянии пробиться до ПК, либо не должно проявлять активность . Данные могут накапливаться в больших количествах на устройстве и FTP клиент даёт возможность селективного скачивания ограниченного количества данных, оставляя остальные для off-line транспортировки.
MQTT протокол в основном применяют для связи с большими группами устройствам через облака и для передачи коротких сообщений. Но MQTT также достаточно эффективно можно применить и для связи с одним устройством в пределах локальной сети и даже передавать файлы через этот протокол. Удобен в качестве командного менеджера для поддержки всех остальных каналов связи упомянутых выше.
Конфигурация стека USB для удобной работы через интернет
Две предыдущие статьи (1 , 2) описывали каждая один из вариантов создания TCP соединения через интерфейс USB (в режиме Host и в режиме Device). А теперь покажем как их совместить и переключаться от одного варианта к другому одной лишь опцией в оперативных настройках.
Конфигурация стека USB в Azure RTOS определяется в файле ux_user.h. Большинство опций закомментировано, но несколько важных опций опишем:
UX_HOST_SIDE_ONLY - эта объявленная опция разрешает компиляцию только стека хоста
UX_DEVICE_SIDE_ONLY- эта объявленная опция разрешает компиляцию только стека устройства (периферии).
Мы убираем определение макросов UX_HOST_SIDE_ONLY и UX_DEVICE_SIDE_ONLY. Это увеличит размер оперативной памяти под стек USB, но позволит переключаться между режимами Host и Device программно, а не выбирать одну из этих двух конфигураций на этапе компиляции.
Ещё включаем опцию UX_ENABLE_MEMORY_STATISTICS, если хотим наблюдать в отладчике размер памяти потребляемый стеком USB из своих пулов памяти. Это нужно для более точного определения размера массивов отводимых пулам памяти. Потом этот макрос можно закомментировать.
В файле USB_init.c определены размеры двух массивов необходимых стеку USB и передаваемые ему при инициализации.
// Размеры даны для случая когда макросы UX_HOST_SIDE_ONLY и UX_DEVICE_SIDE_ONLY закоментированы
#define USBX_HOST_REGULAR_MEMORY_SIZE (24000) // 24000 Минимальный размер определенный на основе статистики и тестирования при работе класса RNDIS или CDC ECM
#define USBX_HOST_CACHE_SAFE_MEMORY_SIZE (38000) // 38000 Минимальный размер определенный на основе статистики и тестирования при работе класса RNDIS или CDC ECM
Сам параметр переключающий режим работы USB интерфейса объявлен здесь . Поменять его можно либо через редактор параметров Telnet или в среде FreeMaster.
Важно понимать как устройство получает свой IP адрес в разных режимах работы интерфейса. Если плата работает как Host и к ней подключается Ethernet-USB адаптер, то программа на плате либо запускает DHCP клиента для получения IP адреса от сервера в сети, либо устанавливается фиксированный IP адрес в настройках устройства. Если плата работает как Device, то программа на плате либо запускает DHCP сервер, либо устанавливается фиксированный IP адрес.
Как подключать линию питания 5В от интерфейса USB
В случае отсутствия отдельного ключа питания (а на плате полифункционального зарядника это так) возникает сложность с реализацией на одном и том же интерфейсе режимов Device и Host. Стандартно в режиме Device подключение и отключение USB определяется по наличию напряжения на разъёме. Но поскольку на разъем постоянно подаётся напряжение 5 В, то такой способ работать не будет. В данном проекте решение найдено в отслеживании прерываний по получению пакетов SOF. Если пакеты перестают поступать, то принимается решение о том что USB интерфейс отключён.
Использование Telnet
Программа микроконтроллера использует стандартный поставляемый с Azure RTOS программный модуль сервера Telnet. Единственное что надо реализовать - в callback функции при установлении соединения с Telnet вызвать создание задачи Task_VT100, как показано здесь. После этого задача терминала VT100 приступает к приёму и передаче данных через сокет Telnet. Согласование опций соединения Telnet при этом происходит до вызова задачи VT100 и не обременяет пользователя этим взаимодействием. При отсоединении клиента от сервера Telnet задача VT100 удаляется из памяти. Таким образом достигается более эффективное использование оперативной памяти микроконтроллера.
На стороне ПК запуск терминала осуществляется одним из двух скриптов в зависимости от конфигурации USB интерфейса: Open_TeraTerm_Telnet_ECM.cmd или Open_TeraTerm_Telnet_RNDIS.cmd. Скрипты запускают на ПК программу терминал TeraTerm с заданным IP адресом и номеров порта.
В задаче VT100 выполняется интерактивное меню с различными панелями служащими для редактирования параметров или управления устройством. Это своеобразный продвинутый интерфейс CLI, но использующий управляющие коды по спецификации VT100. Во многих случаях сессия Telnet с успехом заменяет встроенный WEB сервер и требует меньше ресурсов процессора и оперативной памяти.
Telnet удобно использовать для непрерывной передачи лога из устройства. Поскольку популярные терминальные программы все имеют возможность записи получаемых данных в файл, то нет проблем сохранять большие объёмы данных о работе устройства.
Виртуальный COM порт через интернет
Интересной особенностью реализации Telnet сервера в Azure RTOS является возможность отключения этапа согласования опций Telnet канала с помощью объявления макроса NX_TELNET_SERVER_OPTION_DISABLE. Тогда сервер Telnet можно использовать в качестве виртуального COM порта через интернет. В качестве драйвера на стороне ПК удобно использовать бесплатный вариант такой утилиты. В ней надо выбрать режим работы канала связи RAW. На стороне микроконтроллера в Azure RTOS мной был разработан специальный драйвер для этих целей. О нем рассказано тут. Все это даёт возможность применения для сбора телеметрии старого софта способного работать только с последовательными COM портами компьютера.
Использование FreeMaster
Зачем нужен и как работает FreeMaster было рассказано тут. Это одно из наиболее удобных средств наблюдения и записи сигналов в реальном времени для малых встраиваемых платформ. Фирма ST предлагает для этих целей STM32CubeMonitor, но он работает только через отладочный адаптер, и это довольно неудобно.
В недавней версии FreeMaster появилось расширение протокола позволяющее выполнять соединения поверх TCP/IP. В нашем демо-проекте соответственно был обновлён протокол и теперь мы можем подключить приложение FreeMaster к микроконтроллеру под управлением Azure RTOS через интернет и удалённо получать полноценную телеметрию.
Портирование драйвера FreeMaster
FreeMaster поставляется с готовым драйвером для TCP в файле freemaster_net_lwip_tcp.c. Но в этом файле используется API стека lwIP. Стек lwIP к счастью очень честно придерживается спецификации BSD Socket API, но только к некоторым функциям подставляет префикс lwip_. Если убрать эти префиксы, то модуль BSD Socket API Compliancy Wrapper Azure RTOS будет работать также, как оригинальный стек lwIP. Это и было сделано в файле freemaster_netx_tcp.c . Далее потребовался некоторый рефакторинг имён в исходниках протокола FreeMaster для микроконтроллера и изменён вызов функции FMSTR_Init, так чтобы передавать ей указатель на текущий драйвер коммуникационного канала. Это повысило гибкость использования протокола и возможность менять коммуникационные каналы без перекомпиляции.
![Окно FreeMaster с передачей данных в реальном времени через интернет Окно FreeMaster с передачей данных в реальном времени через интернет](https://habrastorage.org/getpro/habr/upload_files/a04/8af/ae0/a048afae04d17ef28de7be52557c733b.gif)
Настройка BSD Socket API в Azure RTOS
Чтобы с минимальным рефакторингом применять исходники написанные под стек lwIP нам нужен для работы модуль BSD Socket API Compliancy Wrapper и пакета NetX Duo входящего в Azure RTOS.
API BSD требует наличия в управляющей структуре RTOS поля bsd_errno. Поэтому в файле tx_user.h надо переопределить макрос расширения следующим образом:
#define TX_THREAD_USER_EXTENSION ULONG environment; ULONG driver; ULONG bsd_errno;
Первые две переменные в макросе нужны для предыдущих кастомных усовершенствований RTOS описанных в статьях ранее.
Интеграция BSD Socket API заключается в копировании файлов в дерево директорий проектов и вызова функции bsd_initialize после того как будет создан объект NX_IP функцией nx_ip_create. Надо лишь отметить, что вызов bsd_initialize создаст дополнительную задачу BSD thread task, требующую своего стека
![](https://habrastorage.org/getpro/habr/upload_files/881/f27/9e2/881f279e232527f921dadabc76f29615.png)
Чтобы ненароком не создать смертельные локи (Deadlock) в программе надо хорошо подумать о приоритете задачи BSD thread task. Приоритет указывается при вызове функции bsd_initialize
Подключение и использование Node-RED.
Node-RED - это инструмент для визуального программирования выполненный на платформе Node.js. Под Windows поставляется в виде JavaScript файлов и модулей dll. По сути является сервером выполняющим JavaScript скрипты и дополняемый специализированными визуальными и не визуальными компонентами. Инструмент довольно компактный и FreeMaster Lite его целиком содержит в себе. Кроме того FreeMaster Lite добавляет в свой дистрибутив Node-RED компоненты для доступа к переменным через протокол FreeMaster. Есть несколько визуальных и компонент и основная масса для доступа к данным различного типа. Подключение к целевой плате происходит через поставляемые модули dll. Рекомендуемые варианты: через COM порт и через TCP подключение. В нашем случае было интересно TCP подключение.
Чтобы запускать Node-RED надо проинсталлировать FreeMaster Lite. Там потребуется получить бесплатную лицензию на сайте NXP.
После инсталляции файлы конфигурации с расширением .fmcfg будут открываться утилитой node.exe из пакета FreeMaster Lite.
Был создан демонстрационный файл конфигурации Node-RED_FreeMaster_example_config.fmcfg с текстом:
{
"port": 8090,
"node_red": true,
"open_path": "/red/",
"connections": [
{
"connection_string": "NET;192.168.3.1;type=TCP;port=3344;timeout=500",
"name": "TCP Connection",
"description": "TCP connection"
}
]
}
И был создан сам демонстрационный проект Node-RED_FreeMaster_example_proj.json
Проекты в Node-RED хранятся в формате JSON файлов.
Чтобы запустить проект надо скачать и щёлкнуть на файле конфигурации Node-RED_FreeMaster_example_config.fmcfg . Запустится утилита node.exe и она в свою очередь откроет окно браузера с приложением Node-RED. В приложении Node-RED надо импортировать наш файл проекта Node-RED_FreeMaster_example_proj.json через Clipboard.
![Вид меню при импорте проекта Вид меню при импорте проекта](https://habrastorage.org/getpro/habr/upload_files/718/794/638/718794638af3d4b7d76a7f5dda65b970.png)
После этого можно будет увидеть такое представление. В правой панели debug отображаются результаты работы созданного проекта.
![Окно работающего проекта Окно работающего проекта](https://habrastorage.org/getpro/habr/upload_files/82f/322/a11/82f322a112ee04854885160f5391cd6d.png)
К сожалению впечатление от компонентов FreeMaster в среде Node-RED осталось посредственным. Подключение TCP постоянно обрывалось. Компонент осциллографа не захотел работать, так и осталось неясным как это выглядит в работе. Для каждого типа данных (int, unsigned int, float … ) приходится использовать предназначенный для этого типа компонент. Это вызывает поток ошибок. Скорость получения данных не удалось сделать быстрее одного раза в секунду. Словом громоздкость и ограниченность компонентной палитры делают такое решение на базе Node-RED менее полезным чем представлялось.
В Node-RED остаётся вариант для подключения к устройствам по протоколу TCP без всяких промежуточных протоколов, но тогда возникает необходимость реализации согласованного кодирования и агрегации данных на обоих концах. Т.е. придётся по сути писать с нуля заменитель протокола FreeMaster на целевой платформе. А это противоречит поставленной цели потратить как можно меньше времени на разработку механизмов передачи телеметрии. Однако Node-RED оставляем в своём наборе инструментов как довольно занимательную штуковину если она будет эволюционировать.
Работа с MATLAB Simulink
Как это выглядит на стороне ПК было описано в этой статье и в вот в это статье.
Как и для всякого канала связи тут тоже нужно создать свою задачу в RTOS. Эта задача только отправляет пакеты. Приёмом пакетов занимается задача сервера TCP, который создаётся здесь. При создании сервера ему передаётся ссылка на функцию обработки принимаемых пакетов. Функция обработки пакетов проверяет целостность данных и назначение команд и сигнализирует основной задаче о необходимости принять новую команду с данными. Работа с MATLAB интересна, когда обмен идёт в реальном времени. Т.е. работа ведётся в локальной сети, чтобы не беспокоится о разрывах канала связи. Устройство с Azure RTOS здесь безопасно может выступать сервером, а ПК клиентом. В данном проекте также сохранена функциональность тестирования SD карт от прошлых демо-проектов.
Использование FTP сервера
FTP сервер незаменим, когда на устройство надо закачать или скачать с него файлы. Это могут быть прошивки, логи, телеметрия и проч. На ПК нужно иметь всего лишь клиента FTP. Клиенты FTP есть для всех OS общего применения, даже для смартфонов.
Весь функционал FTP сервера в Azure RTOS полностью реализован. Но для FTP сервера нужна файловая система FileX. Если у нас SD карта памяти размером больше 32 Гбайт, то нужно использовать вариант файловой системы exFAT. В текущей версии Azure RTOS система exFAT в FTP сервере не заработает. Чтобы это исправить надо предпринять следующие действия.
Во-первых, по умолчанию в FileX выключена опция FX_ENABLE_EXFAT. Её надо включить.
Во-вторых, в настоящей версии Azure RTOS работа с exFAT не поддерживается и поэтому мной была создана модификация FTP сервера с поддержкой exFAT и она находится в этом файле. Правда размеры файлов во многих FTP клиентах окажутся искажёнными, поскольку в exFAT размер файла представляется типом uint64_t.
Использование FTP клиента
Клиент FTP в Azure RTOS сам подключается к удалённому серверу и перекачивает туда свои файлы. В данном проекте это реализовано здесь. Задача клиента FTP занимается тем что непрерывно записывает каждую 1 мс данные о токах и напряжениях в файл. При достижении файлом определенного размера и наличии связи по TCP задача организует пересылку файла на удалённый FTP сервер. Если пересылка удалась, файл на SD карте устройства стирается. Адрес, логин и пароль FTP сервера задаются в энергонезависимых настройках и могут редактироваться через Telnet или через MQTT.
Как обычно и тут не обошлось без исправлений в стеке TCP Azure RTOS. На этот раз надо исправить функцию _nx_tcp_free_port_find добавив проверку на нулевую ссылку.
Использование MQTT
Про MQTT были статьи :
По прежнему для брокера и клиентской части на ПК я использую проект Eclipse Mosquitto. Библиотека хорошо себя зарекомендовала в приложениях от Windows 7 до Windows 11.
В Azure RTOS есть хорошая библиотека поддержки работы по MQTT.
Может показаться необычным, но в данном проекте используется всего 5 топиков, хотя разных типов передаваемых данных довольно много. Дело в том, что в данном случае топики используются как логические каналы передачи данных. По сути MQTT брокер немного превращается в прокси сервер. Был разработан специальный формат пакетов для передачи трафика через топики. Причём блоки данных сжимаются специальным компрессором для экономии трафика. А исходные данные и команды кодируются в формате JSON в блоки в которых могут помещаться значения десятков и сотен переменных и параметров.
Такой подход значительно экономит MQTT трафик, когда речь идёт о больших потоках данных, экономит усилия по управлению деревом топиков, но при этом остаётся возможность работы с облачными сервисами в традиционном стиле. MQTT с нашей кастомной надстройкой в открытом интернете мог бы заменить функциональность Telnet, FTP сервера и клиента, и другие протоколы. Так было бы проще обеспечить должный уровень защиты и надёжности канала связи. Если учесть релейные возможности MQTT брокеров, то тема становится ещё интересней. Кастомная надстройка сильно изменяет свойства нашего MQTT и к нему уже нельзя применять типичные сравнительные обзоры, как например тут LwM2M vs MQTT.
Заключение
Все перечисленные каналы передачи телеметрии в устройстве могут работать одновременно, но каждый может быть выключен или включён индивидуально в настройках. Как правило, не требуется все их иметь включёнными одновременно. FreeMaster больше нужен на этапе отладки, поскольку имеет дело с символьными именами из исходного кода. MATLAB нужен для исследований, когда не ясны характеристики объекта управления (аккумуляторов в данном случае). Telnet всю функциональность реализует в устройстве, его удобно предлагать для простой неглубокой диагностики и сбора логов с помощью любых пользовательских устройств. FTP сервер и клиент не дают должной реактивности, но способны накапливать большие объёмы, это подходит для обслуживания с большими паузами. MQTT позволяет гибко обходить трудности с очень удалённым доступом.
В статье ещё не были упомянуты протоколы: SNMP для обмена через MIB браузеры, HTTP для обмена через WEB броузеры, SMTP для обмена через почтовые серверы и LwM2M. Эти протоколы тоже реализованы в Azure RTOS. Об использовании HTTP и WEB сервера в Azure RTOS, кстати, было написано здесь. Но на мой взгляд это менее удобные способы передачи телеметрии, и потому не стал их включать в обзор.