IT Академия Samsung - Учебные наборы Unwired Devices # Работа с учебными наборами IoT от Unwired Devices ## Предисловие Вузы-участники программы [IT Академия Samsung](https://myitacademy.ru) в 2017 - 2018 гг. для изучения технологий интернета вещей комплектовались учебными наборами отечественного производства. Выпускала их компании ["ООО "Беспроводные технологии"](https://www.unwireddevices.com/) ([Unwired Devices](https://www.unwireddevices.com/)). Эти наборы обладают рядом плюсов: - низкая стоимость; - интегрированный модуль: микроконтроллер + модуль связи LoRa; - есть готовый стек LoRaWAN и драйверы для внешних устройств. К сожалению, они больше не выпускаются, и вузы-участники программы IT Академия Samsung постепенно переходят на новые учебные комплекты, работа с которыми и описывается в системе обучения [myitschool.ru/edu](https://myitschool.ru/edu/). И так как это достаточно длительный процесс, связанный с финансированием, организацией тендера на закупку и прочими организационными вопросами, мы в этом учебном году вынуждены адаптировать курс "Интернет вещей" для использования с имеющимся в нашем распоряжении оборудованием. ## Unwired Devices Kit Учебные наборы от [Unwired Devices](https://www.unwireddevices.com/) содержат достаточно большой набор компонентов, но нас в первую очередь будут интересовать два: * радиомодуль Unwired Range (UNWR); ![unwr](/assets/images/iot-academy/unwr.png) * плата-адаптер (UMDK-RF). ![umdk-rf107](/assets/images/iot-academy/umdk-rf107.png) Радиомодуль Unwired Range (подписан на плате как UNWR) содержит в себе микроконтроллер STM32 и приемопередатчик LoRa, и, таким образом, сам по себе является минимальным конечным устройством "Интернета вещей". К плате-адаптеру UMDK-RF можно подключать различные радиомодули (например, тот же UNWR). Разъём для них расположен снизу. А также различные датчики и исполнительные устройства (разъемы сверху). Помимо этого, на этой плате находятся: * зеленый светодиоды **D4** * красный светодиоды **D5** * кнопка **BOOT/POWER** * кнопка **RESET** * кнопка **SAFE** Для включения модуля UMDK-RF (v1.07) достаточно подать на него питание через расположенный на плате разъем micro-USB. Если после подключения кабеля USB загорается зелёный светодиод **D4**, модуль работает в штатном режиме. Управление модулем: * короткое нажатие на кнопку **BOOT/POWER** — включение/выключение питания; * длинное нажатие (более 2 секунд) — ввод радио-модуля в режим программирования по UART; * кнопка **SAFE** подключена к порту `PB_1`, и может использоваться в программах аналогично `USER_BUTTON`. Световая индикация: * медленное мигание зелёного светодиода — радио-модуль в режиме программирования по UART; * быстрое мигание зеленого светодиода — короткое замыкание на выходе 5 В; * мигание красного — активность модуля. Кроме того, на плате радиомодуля UNWR расположен красный светодиод, подключенный к порту `PB_0`, который можно использовать аналогично `LED1`. Мы не планируем сейчас использовать модуль связи LoRa - нам нужен на первых порах только микроконтроллер серии STM32. Тем не менее, посмотрите [документацию](https://unwireddevices.com/docs/) на этот набор оборудования, возможно, некоторые задачи в этом учебном году мы заменим аналогичными прошлых лет. Итак, соедините радиомодуль UNWR и плату-адаптер UMDK-RF. Обратите внимание, что у платы UNWR микросхемы должны быть направлены вниз. <div class="danger"> Аккуратно обращайтесь с антенной, она может сломаться.<br /> Не менее важно правильно обращаться с линейками штырьков, соединяющими платы между собой: они тонкие, и их легко погнуть. </div> У нас должна получиться такая конструкция: ![ud-min](/assets/images/iot-academy/ud-min.png) Теперь аппаратная часть у нас готова для начала работы! ## Среда разработки В настоящий момент времени курс Интернет вещей [IT Академии Samsung](https://myitacademy.ru) предполагает использование в качестве базовой среды разработки [PlatformIO](https://platformio.org). По сути это надстройка, которая может быть применена к большинству популярных IDE. Как и авторы курса мы будем использовать VSCode. ![pio_logo](/assets/images/iot-academy/pio_logo.png) ### Установка PlatformIO Если у вас современная операционная система (Windows 8/8.1/10/11 или Ubuntu 20.04 или новее), то проблем с установкой быть не должно. Тут все достаточно просто: 1. Установить [VSCode](https://code.visualstudio.com/) для своей операционной системы. 2. Установить расширение PlatformIO - это делается через менеджер расширений внутри VSCode. 3. Перезапустить VSCode. Если у вас Windows 7, то вам нужно скачивать более раннюю версию VSCode, а именно [1.70.3](https://code.visualstudio.com/updates/v1_70). Сделать это можно со странички **Updates** или перейдя по ссылке [https://code.visualstudio.com/updates/v1_70](https://code.visualstudio.com/updates/v1_70). Если же вы работаете с Ubuntu 18.04 (а именно такая версия операционной системы установлена у нас в лаборатории интернета вещей), то здесь тоже есть свои сложности. Все дело в том, что для успешной работы PlatformIO с нашим оборудованием необходима версия Python как минимум 3.8, но последняя официальная сборка для Ubuntu 18.04 - это Python 3.6.9. Причем, если принудительно обновить версию Python, то перестает работать множество системных приложений - порой отказывается работать даже Терминал! Как быть? Следовать инструкции ниже! 1. Установите PlatformIO, как указано в основном курсе IT Академии. 2. При создании нового проекта укажите плату ST Nucleo L152RE и фреймворк Mbed. 3. Если вы не получили никаких ошибок, то все Ок, и дальнейшие шаги можно пропустить. 4. **Закройте Visual Studio Code**. 5. Откройте приложение Терминал, и в нем наберите следующие команды: ``` python3 --version ls /usr/bin/python3* ``` 6. Запомните версии установленных приложений Python (скорее-всего это будет 3.6.9). ![term-py3-cfg](/assets/images/iot-academy/term-py3-cfg.png) 7. Нам нужно установить более новую версию Python. На текущий момент лучше всего подойдет версия 3.10, поэтому в том же Терминале введите: ``` sudo apt update sudo add-apt-repository ppa:deadsnakes/ppa sudo apt update sudo apt install python3.10 python3.10-venv ``` 8. Теперь сконфигурируйте систему на использование новой версии Python. Для этого в Терминале введите: ``` sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 1 sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.10 2 sudo update-alternatives --config python3 ``` 9. В ответ на появившийся запрос укажите номер, соответствующий **новой** версии Python. ![term-py3-cfg-3.10](/assets/images/iot-academy/term-py3-cfg-3.10.png) 10. Запустите Visual Studio Code, дождитесь обновления PlatformIO. 11. Попытайтесь снова создать проект с платой ST Nucleo L152RE и фреймворком Mbed. На этот раз должно получиться! 12. **Закройте Visual Studio Code**. 13. В Терминале перейдите в каталог с настройками PlatformIO: ``` cd ~/.platformio/penv/bin ``` 14. Установите использование новой версии Python для PlatformIO: ``` unlink python3 ln -s /usr/bin/python3.10 python3 ``` 15. Восстановите прежнюю версию Python для использования ее в системе по умолчанию: ``` sudo update-alternatives --config python3 ``` 16. В ответ на появившийся запрос укажите номер, соответствующий **прежней** версии Python (3.6). ![term-py3-cfg-3.6](/assets/images/iot-academy/term-py3-cfg-3.6.png) 17. Все, теперь можно работать! ## Первая программа Следуя за авторами любого языка программирования, первая программа - это всегде **Hello World**. Если же говорить о встраиваемых системах и программах для микроконтроллеров, то часто такая программа это **Blink** - программа, мигающая светодиодом. Собствено сделем и то, и другое! Откроем в PlatformIO наш проект (если вдруг его успели закрыть), перейдем к каталогу `src` и откроеем файл `main.cpp` на редактирование, и изменим его содержимое: ``` #include "mbed.h" DigitalOut led (LED1); int main() { // put your setup code here, to run once: int i = 0; led = 0; printf("Hello World !\n"); while(1) { // put your main code here, to run repeatedly: ThisThread::sleep_for(1s); led = !led; printf("This program runs since %d seconds.\n", i++); } } ``` Это простая программа, которая: * напечатает сообщение Hello World (его можно будет видеть, если подключиться к плате по последовательному порту связи программой-монитором; * будет мигать светодиодом 1 раз в секунду; * будет выводить в последовательный порт число секунд, прошедших с момента запуска программы. <div class="info"> Обратите внимание, что листинг этой программы несколько отличается от того, что предложен на сегодня (10.10.2022 г.) на сайте IT Академии, так как некоторые инструкции являются устаревшими и больше не работают в Mbed 6-й версии! </div> И еще несколько замечаний об использовании PlatformIO. 1. Это особенно важно для тех, кто работает под **Windows**: В полном пути к файлам проекта **не должно** быть символов, отличных от латинице. Собственно по умолчанию PlatformIO создает проекты в каталоге 'Documents\PlatformIO\Projects' пользователя. То есть, если, скажем, у вас имя пользователя - **Пользователь**, то это приведет к тому, что файлы будут размещаться в большинстве случаев по пути `C:\Users\Пользователь\Documents\PlatformIO\Projects`, а с такими именами компиляция программы завершится ошибкой! Под **Linus** такой проблемы нет! 2. Проекты в PlatformIO имееют свою структуру. Исходные файлы, содержащие код программы, нужно размещать в каталоге `src`, заголовочные файлы, созданные пользователем, - в каталоге `include`. Если в проекте используются библиотеки, то **каждая** библиотека должна находиться в своем собственном каталоге внутри каталога ``lib`. ### Компиляция программы Если бы у нас были в распоряжении *типовые* отладочные платы (те же ST Nucleo L152RE), то работа c PlatformIO была бы тоже типовой (и расписана в курсе IT Академии). Реальные же проекты редко когда выполняются на отладочных платах - у таких плат совершенно иная, очевидная из названия, задача. Соответственно, можно сказать, что нам повезло: имея в своем рапоряжении платы Unwired Range, и научившись их подключать к среде разработки, в дальнейшем можно будет аналогичным образом подключить и любую свою плату (Mbed и PlatformIO позволяют работать с *custom boards* - платами, отличающимися от официально поддерживаемых). Что же для этого нужно? Если вкратце, то: 1. Научить фреймворк Mbed "понимать" платы Unwired Range; 2. Научить PlatformIO "понимать" платы Unwired Range; 3. Сконфигурировать программу на использование платы Unwired Range. <div class="validation"> Есть несколько способов сделать все это, но остановимся на каком-то одном, наиболее простом способе (но все равно перед тем, как это делать, **дочитайте** материал до конца). </div> Конечно, платы от Unwired Devices не поддерживаются ни Mbed, ни PlatformIO, но мы создали описание платы Unwired Range для Mbed - создали таргет **UNWIRED_RANGE**! Этот таргет наша [собственная](https://github.com/iot-academy/mbed-os_unwr_target) инициатива, и в нем могут содержаться ошибки, но это лучше, чем ничего, а ошибки мы исправим! Скачать таргет можно либо из нашего [репозитория](https://github.com/iot-academy/mbed-os_unwr_target), либо с этого сайта по ссылкам: * [unwr.tar.gz для Mbed v.6.x](https://aiu.susu.ru/assets/components/fileattach/connector.php?action=web/download&ctx=web&fid=54kRpayReHGDm7U2GJmHMndzqmF1iAYn) * [unwr.tar.gz для Mbed v.5.x](https://aiu.susu.ru/assets/components/fileattach/connector.php?action=web/download&ctx=web&fid=tURKEqMK1Zea6HJFUZSuvMItEOwtbZGF) Для работы с PlatformIO **следует использовать версию 6.x!** Чтобы справиться с *первой* задачей, необходимо в корне своего проекта (рядом с файлом `platformio.ini`) разместить файл `custom_targets.json` из архива с таргетом **UNWIRED_RANGE**, а в каталоге `src` разместить каталог `TARGET_UNWIRED_RANGE` из того же архива. Для решения *второй* задачи в каталоге проекта PlatformIO нужно создать папку `boards` и разместить в ней файл `unwired_range.json` следующего содержания: ``` { "build": { "cpu": "cortex-m3", "extra_flags": "-DSTM32L151xC", "f_cpu": "24000000L", "mcu": "stm32l151ccu6", "product_line": "STM32L151xC" }, "debug": { "default_tools": [ "cmsis-dap" ], "jlink_device": "STM32L151CC", "openocd_extra_args": [ "-c", "cmsis_dap_vid_pid 0x1209 0xda42", "-c", "reset_config srst_only" ], "openocd_target": "stm32l1x_dual_bank", "svd_path": "STM32L15xC.svd" }, "frameworks": [ "cmsis", "mbed", "stm32cube", "libopencm3" ], "name": "Unwired Range", "upload": { "maximum_ram_size": 81920, "maximum_size": 524288, "protocol": "cmsis-dap", "protocols": [ "jlink", "cmsis-dap", "stlink" ] }, "url": "https://aiu.susu.ru/iot/samsung/", "vendor": "UMDK" } ``` И для решения *третьей* задачи нужно в файле `platformio.ini` указать использование нашей платы и таргета: ``` [env:unwired_range] platform = ststm32 board = unwired_range framework = mbed build_flags = -I$PROJECT_SRC_DIR/TARGET_UNWIRED_RANGE ``` А еще можно существенно упростить себе всю работу: скачать и распаковать (с заменой файлов) в корень своего проекта содержимое архива [pio_unwr.zip](https://aiu.susu.ru/assets/components/fileattach/connector.php?action=web/download&ctx=web&fid=JC1v926ByoJN4gK28LO4yj_DFi7ut9Zc), что приведет к выполнению всей необходимой работы. Сразу же можно дополнить секцию `[env:unwired_range]` файла `platformio.ini` настройками подключения к плате. Их изначально нет в архиве, так как они зависят от операционной системы и того, как плата Unwired Range определилась в системе. Под **Windows** посмотрите в *Диспетчере устройств*, какие новые последовательные порты у вас появились (их должно быть два, и в разных версиях операционной системы они могут называться по-разному). Нас интересует порт с **меньшим** номером. ![devmgr_win7](/assets/images/iot-academy/devmgr_win7.png) ![devmgr_win10](/assets/images/iot-academy/devmgr_win10.png) Для определенности пусть это будут порты COM3 и COM4, тогда в `platformio.ini` нужно добавить строки: ``` upload_port = COM3 monitor_port = COM3 ``` В операционной системе **Linux** (Ubuntu) наша плата должна определиться как `/dev/ttyACM0` и `/dev/ttyACM1`. Это тоже нужно проверить, например, командой в Терминале: ``` ls -la /dev/tty* ``` и так же в `platformio.ini` добавить устройство с меньшим номером: ``` upload_port = /dev/ttyACM0 monitor_port = /dev/ttyACM0 ``` Теперь можно компилировать и загружать прошивку в плату конроллера. ### Загрузка программы в плату Unwired Range Платы семейства [STM32Nucleo](https://www.st.com/en/evaluation-tools/stm32-nucleo-boards.html), на основе которых в курсе IT Академии рекомендуется выполнять лабораторные работы, в своем составе содержат программатор ST-Link/v2-1. Его назначение - загрузить программу в память микроконтроллера. Для отладочной платы это хорошо, но в каком-то готовом изделии наличие аппаратного программатора - это фактически пустая трата денег на ненужные детали. Поэтому очень часто аппаратные программаторы для микроконтроллеров выпускаются отдельно. Например, тот же ST-Link может выглядеть так: ![st-link-v2-1](/assets/images/iot-academy/st-link-v2-1.png) Вообще можно использовать любой программатор, лишь бы он справлялся со своей задачей. В отладочной плате (или учебном наборе) без программатора не обойтись. И платы Unwired Devices также в своем составе имеют программатор. Собственно плата-адаптер UMDK-RF - это и есть прежде всего программатор. Подключите плату-адаптер UMDK-RF с подключенным радиомодулем UNWR к компьютеру, используя micro-USB кабель. В современных Linux поддержка преобразователя USB-UART для этой платы встроена на уровне ядра, так что ничего дополнительно устанавливать не нужно - драйвера установятся автоматически. Но при первом подключении к компьютеру, светодиоды **D4** и **D5**, установленные на плате-адаптере UMDK-RF, возможно, будут часто мигать в процессе инициализации платы и установки драйверов. Как только плата "промигается", она готова к работе. Приведём последовательность действий, необходимых для загрузки прошивки: 1. Подключить плату к компьютеру. 2. Если плата включена, коротким нажатием (мене 2 секунд) на кнопку **BOOT/POWER** выключить её. 3. Включить плату коротким нажатием (мене 2 секунд) на кнопку **BOOT/POWER**. 4. Как можно скорее длинным нажатием (более 2 секунд) на кнопку **BOOT/POWER** перевести плату в режим программирования (зеленый светодиод **D4** начнет мигать с равными интервалами). 5. Запустить в PlatformIO прошивку платы (стрелка вправо на панели инструментов). ![pio_flash](/assets/images/iot-academy/pio_flash.png) 6. Длинным нажатием (более 2 секунд) на кнопку **BOOT/POWER** перевести плату в обычный режим работы (зеленый светодиод **D4** светится постоянно). #### Примечание Собственно зачем выключать и снова включать плату (п.&nbsp;2 и п.&nbsp;3)? Скорее всего в нашем случае в этом нет необходимости. Однако оригинальная прошивка для плат Unwired Range в своей работе использует порты, через которые осуществляется её переключение в режим программирования. Поэтому перевести плату с такой прошивкой в режим программирования возможно только до того, как она полностью проинициализировалась. Если установлена какая-то другая прошивка, то лишний раз плату можно и не выключать, достаочно длинным нажатием на **BOOT/POWER** перевести плату в режим программирования. ![anger](/assets/images/iot-academy/anger.png) ## Долгая компиляция Обратили внимание, что процесс компиляции программы занимает о-о-о-о-очень много времени? 1. Говорят, что на Linux компиляция происходит значительно быстрее, чем под Windows. Для примера время компиляции "пустой" программы под Windows&nbsp;10&nbsp;20H2 и Ubuntu&nbsp;18.04 на одном и том же компьютере (Intel(R) Xeon(R) CPU&nbsp;E5-2678&nbsp;v3 2.50&nbsp;GHz 16,0&nbsp;Гб) 258&nbsp;с и 65&nbsp;с соответственно! При этом Windows работает с SSD (NVME SSD 256GB), а Ubuntu - только с со стареньким и медленны HDD (FUJITSU MHV2200BT)! [![pv_compile_win10](/assets/images/iot-academy/pv_pio_compile_win10.png)](/assets/images/iot-academy/pio_compile_win10.png) [![pv_compile_ubuntu1804](/assets/images/iot-academy/pv_pio_compile_ubuntu1804.png)](/assets/images/iot-academy/pio_compile_ubuntu1804.png) Так что можно проверить - свободные компьютеры в аудитории есть. 2. Последующая компиляция, если не меняются файлы `platformio.ini`, `mbed_app.json` занимает существенно меньше времени. 3. Можно еще ускорить время компиляции, и не компилировать отдельные модули Mbed, благо разработчики предусмотрели такую возможность. Вообще с этой целью нужно создать файл `.mbedignore` в каталоге с библиотекой Mbed, и указать в нем какие файлы и каталоги не нужно компилировать. Но это не работает при использовании PlatformIO! Тем не менее, выход есть! [Kacper Kowalski](https://github.com/KKoovalsky) предложил способ, который к тому же позволяет для каждого проекта в PlatformIO иметь свои собственные исключения при компиляции Mbed - это его проект [PlatformIO-Helpers](https://github.com/KKoovalsky/PlatformIO-Helpers). Однако, нам больше нравится его [ответление](https://github.com/Copper-Bot/PlatformIO-Helpers), в котором есть несколько улучшений. Что нужно сделать, чтобы сократить время компиляции? - Установить систему контроля версий Git, если она у вас еще не установлена. В Ubuntu это можно сделать так: ``` sudo apt install git ``` - Перейти в каталог с фреймворком Mbed: ``` cd ~/.platformio/packages/framework-mbed ``` - Поместить текущее состояние фреймворка под управление системы контроля версий Git: ``` git init git add . git commit -m "Initial state" ``` - В файл `platformio.ini` добавить строку: ``` extra_scripts = pre:mbedignore.py ``` - В корень проекта добавить файл (кликабельно) [`mbedignore.py`](https://raw.githubusercontent.com/Copper-Bot/PlatformIO-Helpers/master/mbedignore.py) - В корне проекта создать файл `.mbedignore`, в котором указать каталоги библиотеки Mbed, которые не нужно компилировать в данном проекте: ``` connectivity/drivers/802.15.4_RF connectivity/drivers/ble connectivity/drivers/cellular connectivity/drivers/emac connectivity/drivers/lora connectivity/drivers/mbedtls connectivity/drivers/nfc connectivity/drivers/wifi connectivity/cellular connectivity/libraries connectivity/lorawan connectivity/lwipstack connectivity/mbedtls connectivity/nanostack connectivity/netsocket connectivity/nfc features/frameworks storage/kvstore ``` Как это работает? Непосредственно в самом Mbed можно запретить компилировать отдельные каталоги при помощи файла `.mbedignore`, в котором прописывается путь к каталогу и файлам, которые нужно исключить из процесса сборки. Символ `*` (звездочка) в таком файле запрещает компиляцию всего содержимого каталога, в котором находится такой файл `.mbedignore`. В PlatformIO нет полной поддержки синтаксиса таких файлов, и еще меньше в предлагаемом скрипте. Этот скрипт (`mbedignore.py`) считывает файл `.mbedignore` в корне проекта и по указанным в нем путям создает новые файлы `.mbedignore` с запретом компиляции всего (то есть `*`). Соответственно, раз в каталог с Mbed добавляются новые файлы, запрещающие компиляцию некоторых частей этого фреймворка, то при создании **нового** проекта в PlatformIO можно столкнуться с тем, что некоторые нужные компоненты Mbed так и не компилируются. В этой ситуации нужно либо вручную удалить все созданные скриптом `mbedignore.py` файлы `.mbedignore` (что достаточно тяжело), либо заставить сам скрипт `mbedignore.py` удалить файлы`.mbedignore` в структуре каталогов Mbed (создав пустой файл `.mbedignore` в корне своего проекта, но это работает не всегда), либо "откатить" все изменения в каталоге фреймворка Mbed при помощи системы контроля версий Git (благо мы в самом начале поместили фреймворк под контроль этой системы). Сделать это можно следующим образом в Терминале: ```shell cd ~/.platformio/packages/framework-mbed git reset --hard HEAD ``` ## Что дальше? Таким образом, мы фактически выполнили [пункт 1.1.2](https://myitschool.ru/edu/mod/book/view.php?id=1829&chapterid=1651) нашей [лабораторной работы 1.1](https://myitschool.ru/edu/mod/book/view.php?id=1829) на доступном для нас оборудовании. Соответственно, задача сведена к известной, и можно приступать к выполнению очередных частей практикума, модифицируя предлагаемые примеры самостоятельно.