Недавно платформа .NET nanoFramework для микроконтроллеров отметила свой юбилей. За 5 лет платформа превратилась из малоизвестного проекта в успешное коммерческое open-source решение. К инструментам разработчика добавили Visual Studio Code, теперь на Linux также можно программировать на C#, как и в Windows. Были переработаны nuget-пакеты, появилась коммерческая поддержка, обновлена документация. В практической части подключим OLED дисплей на контроллере SSD1306, немного доработаем драйвер под новую модификацию дисплея и отправим код в upstream, напишем небольшой сканер Wi-Fi сетей.
Разработка в Visual Studio Code
До недавнего времени разработка для .NET nanoFramework велась только в Visual Studio 2019 под Windows 10+. Это крайне сужало список используемых платформ для разработки. Для олдскульников Windows 7 не работало окно обзора подключенных устройств, что приводило к невозможности запуска отладки программы.
Но теперь есть расширение .NET nanoFramework для VS Code, с помощью которого вы сможете прошивать микроконтроллер, собирать и развертывать приложения на C# для .NET nanoFramework. Поддерживаются платформы Mac, Linux (64 bits) и Windows (64 bits). Для работы расширения требуется .NET 6.0 и Visual Studio build tools для Windows (в Linux/macOS необходимо установить пакет mono-complete). Но пока, к сожалению отладка работает только в Windows с Visual Studio.
Использование расширения NET nanoFramework для VS Code
От команды разработчиков потребовалось немало усилий, чтобы собрать в один инструмент возможность прошивать и развертывать приложения для процессоров ESP32, STM32, NXP и TI.
При реализации режима отладки выяснилось, что VS Code использует новый протокол адаптера отладки, взамен устаревшего в Visual Studio. В общем, для реализации отладки в VS Code необходимо практически полностью переписать библиотеку отладки, включая собственный код на C/C++. По оценкам трудозатрат на решение данной задачи, необходим 1 разработчик работающий на протяжение 6 месяцев при полном рабочем дне. С текущими небольшими пожертвованиями, это задачу отложили на потом. Но, не смотря на отсутствие отладки, вы можете отправлять отладочные сообщение привычным способом, используя метод Debug.Write(Line). Для чтения которых достаточно открыть последовательный порт на скорости 921600 бод используя программу putty или любую другу работающую с последовательными портами. Это, конечно же, не комфортная отладка в Visual Studio, но все же можно программировать. Visual Studio 2019 по прежнему поддерживается, включая бесплатную Community редакцию. Более детально о процессе разработки расширения в блоге разработчиков. Ссылка на Руководство по началу работы с расширением .NET nanoFramework VS Code.
Все есть nuget-пакеты
В предыдущей публикации к отладочной плате ESP32 DevKit подключался температурный датчик BME280. Драйвер к данному датчику приходилось брать в виде исходного кода из репозитория GitHub nanoFramework.IoT.Device — BMxx80 Device Family. Теперь все драйверы к датчикам оформлены в виде отдельных nuget-пакетов:
Nuget-пакеты для .NET nanoFramework
Символический рубеж загрузок NuGet-пакетов в 1 миллион был достигнут 7 мая прошлого года, к этой цифре шли долгих 5 лет. Благодаря активному развитию платформы, уже второй миллион был достигнут всего за 9 месяцев!
Суммарный график загрузок Nuget-пакетов .NET nanoFramework
Более детально в публикации 2 MILLION NUGET DOWNLOADS AND COUNTING.
Новая стратегия развития
Благодаря достижению «зрелости» всех библиотек .NET nanoFramework, с увеличением числа пользователей и очень редкими сообщениями об ошибках и/или проблемах, в конце мая команда разработчиков приняла решение о публикации только стабильных (stable) версий прошивок и пакетов. На практике это существенно упрощает разработку. Раньше приходилось постоянно искать предварительные версии, затем их обновлять до стабильной версии, иногда возникали несоответствия, и было трудно найти правильную комбинацию для успешной сборки и/или развертывания. Все это уйдет в прошлое.
Что касается репозиториев проекта GitHub, теперь ветка по умолчанию является «main» для всех библиотек, и команда разработчиков отказывается от ветки «develop». За исключением описанной выше процедуры. Это сделает более понятным программный код для всех, кто хочет внести свой вклад или просто его просматривает.
Если вам необходима коммерческая помощь в разработке устройств, инструментов проектирования, обучению по .NET nanoFramework, то вы можете обратиться к компаниям Eclo Solutions (Португалия) и CSA Engineering AG (Швейцария).
Плата OrgPal PalThree сертифицирована для Azure Device
Устройство PalThree — используется для частого и точного мониторинга нефтегазовых месторождений. PalThree — сертифицированное устройство Azure IoT Ready Gateway & Edge Point для сбора данных и телеметрии с последующей передачей в облако Azure IoT. На борту большой набор входных интерфейсов для получения данных о технологических процессах. Устройство построено на STM32 ARM 4 и ARM 7, поставляется в двух вариантах с микроконтроллерами STM32F469x и STM32F769x, с 1 МБ SDRAM на плате, флэш-памятью SPI и QSPI. Программное обеспечение основано на .NET nanoFramework, с ChibiOS для STM32. Немного об этом устройстве в публикации .NET nanoFramework — платформа для разработки приложений на C# для микроконтроллеров.
Плата PalThree от OrgPal
PalThree это первое устройство с .NET nanoFramework получившее статус Azure Certified Device и также сертифицировано для IoT Plug and Play. Это важный рубеж команды разработчиков платформы т.к. сертификация говорит о высоком качестве программного решения.
Если внимательно посмотреть, то было сертифицировано не только само устройство, но и библиотеки .NET nanoFramework, в частности библиотека Azure IoT, которая играет ключевую роль и позволяет создавать невероятно функциональные устройства. Помимо этого, сама плата также прошла сертификацию как IoT Plug and Play решение.
На разработку библиотеки Azure IoT ушло много сил. Интерфейсы API были приведены в соответствии с официальной библиотекой C# Azure IoT.
PalThree теперь находится в каталоге Azure Certified Device, и это здорово! Плата используется как часть предложения телеметрии компании Orgpal, а также доступна третьим сторонам в качестве компонента ODM.
Телеметрия устройств устройств OrgPal
Компания Orgpal давно поддерживает .NET nanoFramework. Это одна из тех компаний, которые для себя выбрали путь open-source, полностью понимая важность будущей стратегии развития, взамен пути полной закрытости экосистемы. Orgpal не только спонсируют проект ежемесячными взносами, но и в последние годы разрабатывает некоторые функции и библиотеки, которыми все пользуются.
Обновление документации
Какая бы ни была замечательная разработка, всегда требуется полная и качественная документация. И в этом направлении команда разработчиков не отстает от написания кода. Добавились инструменты автоматической сборки актуальной документации вместе с библиотеками. Обновилось руководство для начала работы с платформой nanoFramework.
Для желающих собрать собственные прошивки доступно руководство Building .NET nanoFramework.
Более подробно про документацию в публикации .NET NANOFRAMEWORK ❤️(AUTOMATED) DOCUMENTATION.
Одной строкой
- Обновлен инструмент для прошивки микроконтроллеров nanoFirmwareFlasher — nanoff. Теперь для его работы требуется .NET 6.0. Совет! Если не удается прошить устройство ESP32, то попробуйте при прошивке долго удерживать кнопку Boot. Если не помогло, то выполните следующий порядок действий: подключите плату по USB, зажмите кнопку Boot и не отпускайте, нажмите кнопку EN (reset) и отпустите, отпустите кнопку Boot, теперь попробуйте прошить устройство.
- Изменены названия прошивок. Теперь прошивка ESP32_WROOM_32_BLE соответствует прошивке ESP32_BLE_REV0. Актуальную информацию о соответствии прошивок для различных плат смотрите на странице Recommended devices to start with .NET nanoFramework. Обновление модуля ESP-WROOM-32.
- Добавлена поддержка протокола WebSocket, разработан сервер и клиент. Пространство имен System.Net.WebSockets.
- Некоторые библиотеки объявлены устаревшими или переименованы, в частности Devices.Can в Device.Can и System.Device.Wifi.
Подключение OLED LCD на контроллере SSD1306 по шине I2C
В предыдущей публикации в качестве вишенке на торте хотелось подключить небольшой LCD экран, но как говорится пацан к успеху шёл, не получилось, не фартануло. На странице SSD13xx & SSH1106 OLED display опубликован драйвер для LCD SSD1306 работающий по I2C протоколу. Как оказалось, существует две версии данного LCD. Первая, только с интерфейсом I2C. Вторая, более новая с интерфейсами I2C и SPI.
Стоимость в магазине обоих версий была практически одинакова. Всегда хочется большего, вот и был приобретен вариант LCD с I2C/SPI. При подключение к Arduino выяснилось, что в варианте I2C/SPI недостаточно просто перепаять перемычки для работы только в режиме I2C, необходимо дополнительно еще инициализировать дисплей, поэтому пришлось немного дополнить драйвер для LCD. Теперь все по порядку.
Характеристики:
- Размер: 0,96 дюйма;
- Разрешение: 128x64 точек;
- Цвет: монохромный (доступны разные цвета);
- Драйвер IC: SSD1306;
- Интерфейсы: I2C (4 контакта) и I2C/SPI (7 контактов);
- Питание: 3.3~5 В (логика управления 5 В и 3.3 В), очень низкое энергопотребление 0,08 Вт.
Самый простой вариант для подключения это LCD только на I2C. На плате всего четыре контакта: 3V3, GND, SCK и SDA. Но если вы любите приключения, то для вас есть вариант LCD I2C/SPI, на котором необходимо запаять перемычки, резисторы:
- I2C — R1, R4, R8;
- SPI — R3, R4.
Соответственно для работы по I2C запаиваем перемычки R1, R4, R8.
OLED 0,96 inch SSD1306 I2C/SPI на 7 контактов, вид снизу
В варианте LCD I2C/SPI распаяно 7 контактов. Дополнительно к контактам как в варианте только I2C, присутствую контакты: RES, DC, CS. Контакт DC необходимо подтянуть к линии питания 3V3. Контакт RES используется для инициализации/сброса LCD. Контакт CS используется только в варианте подключения по SPI.
Таблица подключения LCD I2C/SPI:
Pin No: | Pin Name: | Description: |
1 | Ground (Gnd) | Connected to the ground of the circuit |
2 | Supply (Vdd,Vcc,5V) | Can be powered by either 3.3V or 5V |
3 | SCK (D0,SCL,CLK) | The display supports both IIC and SPI, for which clock is supplied through this pin |
4 | SDA (D1,MOSI) | This is the data pin of the both, it can either be used for IIC or for SPI |
5 | RES(RST,RESET) | When held to ground momentarily this pin resets the module (operational work, High value) |
6 | DC (A0) | I2C — must be connected to power (3.3V or 5V). SPI — this is command pin |
7 | Chip Select (CS) | Normally held low, used only when more than one SPI device is connected to MCU |
Схема подключения OLED LCD SSD1306 на I2C (fzz) и I2C/SPI (fzz)
В Arduino библиотеке Adafruit_SSD1306 файл Adafruit_SSD1306.cpp для инициализации/сброса контроллера SSD1306 выполняется следующий код:
// Reset SSD1306 if requested and reset pin specified in constructor
if (reset && (rstPin >= 0)) {
pinMode(rstPin, OUTPUT);
digitalWrite(rstPin, HIGH);
delay(1); // VDD goes high at start, pause for 1 ms
digitalWrite(rstPin, LOW); // Bring reset low
delay(10); // Wait 10 ms
digitalWrite(rstPin, HIGH); // Bring out of reset
}
Вначале выставляется уровень HIGH, затем контроллер подтягивается к земле (GND) и переходит в режим сброса, и затем отпускается линия сброса для инициализации контроллера. Данный код необходимо выполнять перед работой с LCD, но этого кода не было в стандартном драйвере для .NET nanoFramework.
Поэтому теперь перепишем программный код на C#, проект Init-SSD1306-on-I2C-SPI, файл Program.cs:
var pinOut = 18;
//Init
var s_GpioController = new GpioController();
GpioPin rstPin = s_GpioController.OpenPin(pinOut, PinMode.Output);
rstPin.Write(PinValue.High);
Thread.Sleep(1); // VDD goes high at start, pause for 1 ms
rstPin.Write(PinValue.Low); // Bring reset low
Thread.Sleep(10); // Wait 10 ms
rstPin.Write(PinValue.High); // Bring out of reset
Но на этом изменения не закончены. У варианта LCD I2C/SPI отличается I2C адрес. Адреса LCD для I2C шины:
- LCD only I2C — 0x3C;
- LCD I2C/SPI — 0x3D.
До использование шины I2C необходимо декларировать используемые контакты самой шины. Это связано с тем, что nanoFramework работает на различных микроконтроллерах и номера контактов шины I2C будут различаться. Например, для платы ESP32 DevKit v1 (ESP-WROOM-32) шина I2C задействует контакты 21 (DATA) и 22 (CLOCK). Для декларирования используется метод Configuration.SetPinFunction(...), с указание контакта и назначенной функции. Пример декларирование шины I2C:
Configuration.SetPinFunction(21, DeviceFunction.I2C1_DATA);
Configuration.SetPinFunction(22, DeviceFunction.I2C1_CLOCK);
Для работы с дисплеем возьмем драйвер — SSD13xx & SSH1106 OLED display family. Добавим новый код инициализации дисплея LCD с I2C/SPI, соберем новый драйвер и выведем изображение. Обратите внимание на параметр функции I2cConnectionSettings(1, ..., цифра 1 — означает номер линии I2C, берется из DeviceFunction.I2C1_DATA. Проект Ssd13xx, файл Program.cs:
Configuration.SetPinFunction(21, DeviceFunction.I2C1_DATA);
Configuration.SetPinFunction(22, DeviceFunction.I2C1_CLOCK);
//Tested with 128x64 and 128x32 OLEDs
using Ssd1306 device = new Ssd1306(I2cDevice.Create(new I2cConnectionSettings(1, Ssd1306.DefaultI2cAddress)), Ssd13xx.DisplayResolution.OLED128x64);
//with reset pin
//using Ssd1306 device = new Ssd1306(I2cDevice.Create(new I2cConnectionSettings(1, Ssd1306.SecondaryI2cAddress)),18, Ssd13xx.DisplayResolution.OLED128x64);
device.ClearScreen();
device.Font = new BasicFont();
device.DrawString(2, 2, "nF IOT!", 2);//large size 2 font
device.DrawString(2, 32, "nanoFramework", 1, true);//centered text
device.Display();
Вывод изображения на LCD приложением nanoFramework
По итогу работы был подготовлен Pull request в основной проект nanoFramework.
Сканер устройств на I2C шине
Для поиска LCD на шине I2C необходимо воспользоваться проектом NanoI2cScanner, для поиска устройств на I2C шине. Выполним поиск устройств. Обнаружены два дисплея:
Отчет найденных устройств на I2C шине
В отличие от кода для Arduino, в nanoFramework поиск устройств на шине I2C выполняется существенно дольше, из-за отсутствия метода установлении линии передачи данных SDA из состояния 1 в 0 при SCL=1, как в Arduino. Пример для Arduino:
Wire.beginTransmission(address);
error = Wire.endTransmission();
В ходе процедуры приемник должен перевести в 0 данную линию на время данного импульса. Если ведомый приемник не подтверждает прием, то линия данных переводится в 1 ведомым, при этом генерируется стоп условие для обрыва передачи. Таким образом, поиск всех устройств на шине занимает всего несколько секунд, т.к. данные на устройство не передаются.
Но в nanoFramework отсутствую методы позволяющие отдельно управлять линией, вместо этого доступны только методы записи данных I2cDevice.WriteByte(0x07) и чтения данных I2cDevice.Read(0x07). В результате время сканирования возрастает до нескольких десятков секунд (~30-40 секунд).
Сканер Wi-Fi сетей
Для работы с Wi-Fi сетями используется пространство имен System.Device.Wifi (nuget: nanoFramework.System.Device.Wifi), взамен устаревшего Windows.Devices.WiFi.
Для сканирования сетей возьмем плату Wemos TTGO WiFi/Bluetooth BLE с OLED-экраном 0.96 дюйма на ESP-WROOM-32. На плате уже распаян LCD OLED на контроллере SSD1306, который рассматривался выше. Особенностью платы является возможность автономной работы используя аккумуляторную батарею 18650 NCR (немного больше формата AA) на 3.7 В, емкостью 3400 мА·ч. Как заявлено на сайте, ESP32 на этом аккумуляторе может проработать не менее 17 часов.
Плата Wemos TTGO WiFi/Bluetooth BLE с OLED-экраном 0.96 дюйма на ESP-WROOM-32
Интегрированный светодиод подключен на GPIO16, будет включаться на время сканирования эфира. Контакты шины I2C отличаются от стандартных (21,22):
- I2C1_DATA — GPIO5;
- I2C1_CLOCK — GPIO4.
Сканер Wi-Fi сетей, проект nanoframework-esp32-scan-wifi, файл Program.cs:
// Get the first WiFI Adapter
WifiAdapter wifi = WifiAdapter.FindAllAdapters()[0];
// Set up the AvailableNetworksChanged event to pick up when scan has completed
wifi.AvailableNetworksChanged += Wifi_AvailableNetworksChanged;
// Loop forever scanning every 15 seconds
while (true)
{
Debug.WriteLine("starting Wifi scan");
wifi.ScanAsync();
Thread.Sleep(15000);
}
Сканирование сетей выполняется в асинхронном режиме, по итогу генерируется событие Wifi_AvailableNetworksChanged. Минимальное необходимое время для сканирования эфира составляет 8 секунд.
private static void Wifi_AvailableNetworksChanged(WifiAdapter sender, object e)
{
Debug.WriteLine("Wifi_AvailableNetworksChanged - get report");
// Get Report of all scanned Wifi networks
WifiNetworkReport report = sender.NetworkReport;
// Enumerate though networks looking for our network
foreach (WifiAvailableNetwork net in report.AvailableNetworks)
{
// Show all networks found
Debug.WriteLine($"Net SSID :{net.Ssid}, BSSID : {net.Bsid}, rssi : {net.NetworkRssiInDecibelMilliwatts}, signal : {net.SignalBars}");
}
После сканирования формируется отчет в виде списка, затем перебираем список и выводим данные об обнаруженных точках доступа.
Сканирование Wi-Fi сетей на nanoFramework
Видео:
Что дальше?
LCD дисплей подключили, но из коробки поддержка русского языка отсутствует, вообще никакие языки кроме английского не поддерживаются! Поэтому в продолжение, добавим не только русский язык, а попробуем обеспечить мультиязычность, с простым добавление любого языка (за исключением написания языков справа-налево). И еще подключим, один очень интересный LCD дисплей для секретного проекта ;)