Mikrokontróler ESP32 je možné programovať v rôznych vývojových prostrediach. Arduino IDE je jedno z najpopulárnejších najmä z dôvodu ľahkej programovej implementácie v jazyku Wiring (Arduino Core) aj pre začiatočníkov. Existuje však aj framework pre vývoj IoT aplikácii - ESP-IDF (Espressif IoT Development Framework) priamo z produkcie Espressif Systems, ktorá tieto mikrokontroléry vyrába. Umožňuje pristupovať bližšie k fyzickej vrstve mikrokontroléra, má rôzne vývojárske nástroje cez Python scripty a implementované nástroje pre spustenie systémových funkcionalít mikrokontroléra (Secure Boot, Flash Encryption a iné...). Vo frameworku ESP-IDF je možné napríklad obsluhovať koprocesor, využívať ho pre prebudenie hlavného procesora, komunikáciu so senzormi, čo v Arduino IDE nie je možné.
Framework obsahuje rôzne ukážkové implementácie projektov pre obsluhu zberníc, komunikáciu, ktoré využívajú FreeRTOS - operačný systém reálneho času, ktorý značne uľahčuje vývoj projektu, keďže umožňuje spúšťať podprogramy ako procesy, ktoré sú priradené k jadru, ktoré ho obsluhuje. Každý proces má pridelenú vlastnú pamäť (stack), ktorú môže využívať. Výhodou v porovnaní s programovaním v Arduino IDE je fakt, že jadro dokáže obsluhovať viacero funkcií zároveň, teda pri štandardnom programovaní dochádza napríklad pri použití funkcie delay() k zastaveniu celého programu, ktorý beží v tasku loop().
V tomto prípade sa zastaví na daný čas iba proces, pričom ostatné procesy dokážu fungovať ďalej. Každá úloha má taktiež priradenú prioritu (vyššie číslo prirority je vyššia priorita) s možnosťou zvolenia jadra ESP32 na ktorom bude daná úloha vykonávaná. Úlohy súvisiace s WiFi prenosom, Bluetooth konektivitou môžu byť na žiadosť používateľa spúšťané na jadre protokolu, kde je obsluhovaný aj WiFi / BT stack - Core 0 (PRO_CPU). Štandardné podprogramy, napríklad pre obsluhu ADC, komunikáciu s perifériami je vhodné spúšťať na druhom tzv. aplikačnom jadre procesora Xtensa - Core 1 (APP_CPU).
Rozhodol som sa vytvoriť ukážkovú implementáciu do existujúceho projektu Hladinomer, ktorý ESP32 využíva, avšak program bol vytvorený v prostredí Arduino IDE.
ESP32 funguje v úlohe senzorového uzla, ktorý vykonáva cyklicky raz za 5 minút meranie výšky hladiny vody s využitím ultrazvukového senzora vzdialenosti. Následne dáta raz odošle na vzdialené webové rozhranie cez internet. Pri vytváraní aplikácie som sa zameral a dal si za cieľ vytvoriť celkom 2 tasky, pričom využijem inter-task komunikáciu s využitím frontu - Queue, čo je FIFO buffer. Queue zároveň zaručuje aj bezpečný prenos dát. Štandardná Queue zo vzorového príkladu, ktorá bola použitá vytvorí FIFO buffer o veľkosti 20 prvkov veľkosti prvku (uint_32).
Task A (producer task - tvorí dáta)Vykonáva meranie ultrazvukovým senzorom vzdialenosti (10x meranie, priemer hodnôt)
Zapisuje hodnotu uint_32 do fronty Queue
Task B (consumer task - používa dáta)Čaká na dostupné dáta v Queue
Počas čakania nevyužíva procesorový čas
Po prijatí dát vymaže prvok z Queue
Vykoná jednorázový HTTP(S) POST request s dátami na webserver
Vymazanie prvku z Queue je podmienené použitou funkciou xQueueReceive(). Pre obsluhu Queue existujú aj pokročilé funkcie, ktoré môžu vybrať položku bez jej zmazania z buffra. K funkciám pre vloženie / vybratie položka z / do buffra existuje aj rozšírenie o ISR (Interrupt Service Routine), ktoré umožňuje ich použitie v rutinách prerušenia (garantuje sa ich obslúženie). Pri zápise do fronty je možné zapisovať na jej začiatok, alebo koniec. V tejto ukážkovej implementácii je to jedno, nakoľko sa task prenosu dát vykoná ihneď a meranie sa vykonáva po 5 minútach, teda nikdy v buffri nie je viac ako 1 položka.
Využitie frontu umožňuje jednému z taskov čakať na prijatie hodnoty ktorú mu odošle iný task. V mojom prípade bude jeden task obsluhovať ultrazvukový senzor vzdialenosti a vykonávať merania a druhý task bude čakať v cykle na hodnotu z merania, ktorú následne odošle na server, ukážkovo HTTP(S) POST metódou. V praxi sa Queues využívajú aj na zamknutie prístupu k zbernici, periférii, ktorú môže v reálnom čase využívať iba aktívna Queue, ostatné úlohy sú v "blokovacom" režime, nakoľko čakajú na hodnotu z aktívnej Queue.
Pri vytváraní programu som najprv vytvoril testovací "offline" program, ktorý umožňuje vyčítavať nameranú hodnotu z ultrazvukových senzorov HC-SR04, prípadne vodotesnej verzie JSN-SR04T a vypísať ju na UART monitor. Knižnicu pre senzor som našiel na Githube. Druhým krokom bola implementácia HTTP(S) requestu, ktorý je v ESP-IDF dostupný ako ukážkový projekt. Programová implementácia bola dostupná iba pre statickú cestu a GET metódu, ktorá nie je vhodná pre prenos dát. Z toho dôvodu som musel existujúcu HTTP hlavičku requestu pozmeniť, doplniť encoding dát prenášaných POST metódou.
Kombinácia oboch projektov bola jednoduchá, nakoľko oba využívali FreeRTOS, teda funkcia bola spustená cez tento plánovač. Stačilo teda iba nakopírovať funkcie a jeden riadok inicializácie úlohy do .c programu. Prvý testovací program obsahoval odosielanie dát na webserver každých 5 minút a meranie dát každých 5 sekúnd, pričom dáta boli zapísané v globálnej premennej - dát. typ uint32, ku ktorej mali obe úlohy prístup. Task pre HTTP(S) request obsahoval aj inicializáciu WiFi adaptéra spoločne s možnosťou konfigurácie SSID a hesla cez Menuconfig.
Menuconfig je v adresári projektu vyvolaný cez CLI (príkazový riadok), kde sa framework obsluhuje. V menu je možné v časti konektivity vybrať aj spôsob komunikácie - štandardne cez WiFi, alebo cez Ethernet PHY modul. V takomto prípade sa ovláda aj Ethernet cez WiFi kontróler. Pripojenie podporovaných Ethernet modulov sa realizuje cez RMII rozhranie.
Výpis na UART rozhranie sa realizuje cez štandardné C funkcie napr. printf(). Framework ESP-IDF však umožňuje využívať aj systém tagovania a logovania. Tagovaním je možné označiť konkrétny výpis s názvom tasku, ktorému výpis patrí a cez logovanie je možné priradiť výstupnému textu aj prioritu vo forme farby (vzorovo tagovanie http_request a ultrasonic_measurement na UART výstupe nižšie). Informačné výpisy (LOGI) sú vypísané zelenou farbou, varovania (LOGW) žltou farbou, chyby (LOGE) červenou farbou. Štandardný výpis cez printf() funkciu je neutrálnou - oranžovou farbou bez priority.
Po pripojení na WiFi sieť získa ESP32 okrem IPv4 aj IPv6 link-local adresu. Priamo do zdrojového kódu je vložená funkcia example_connect(), ktorá vykoná prvotné nastavenie adaptéra, no zároveň je aj v event-loop, čo znamená, že v prípade výpadku WiFi konektivity sa automaticky nezávisle na programe vykoná opätovné pripojenie k AP. Následne som implementoval jednoduchú Queue podľa vzoru pre Inter-task komunikáciu:
https://icircuit.net/esp32-inter-task-communication-using-freertos-queues/1946 V tomto prípade bol producer task meracia úloha a consumer task odosielacia úloha, ktorá sa spustila až po prijatí dát z FIFO buffra - Queue.
HTTP(S) request task tak nevyužíval vTaskDelay, ale funkciu xQueueReceive, ktorou sa vykonáva blokovanie úlohy po prijatie dát z Queue. Jedným z parametrov je časový interval po ktorý je čakacia slučka aktívna. Maximálne je možné zvoliť maximálnu 32-bitovú hodnotu, ktorú je možné získať premennou portMAX_DELAY, čo odpovedá rozsahu cca 50 dní (obdobne ako millis() v prípade Arduino Core). Okamžite po prijatí dát sa HTTP(S) request vykoná. Meracia úloha opakuje meranie s priemerovaním (10 hodnôt priemerovaných) každých 300 sekúnd.
Programová implementácia bola v prvej fáze vytvorená pre HTTP request s nešifrovaním spojením s webserverom, čo je vhodné napríklad pre komunikáciu s lokálnym serverom v sieti, kde zariadeniam veríme. Neskôr bola vytvorená aj programová implementácia pre ESP32 s využitím kryptografickej knižnice Mbed TLS, ktorá je natívne podporovaná v prostredí ESP-IDF. Pre šifrované spojenie s webserverom sa využíva certifikát certifikačnej autority (Root CA) v .pem formáte. Ak nevyužívate self-signed certifikát, mal by byť potrebný certifikát dostupný priamo v "Root CA bundles" a nie je nutné jeho manuálne kopírovanie, či vkladanie do zdrojového kódu aplikácie.
Vyskúšajte projekt Hladinomer (HTTP konektivita):
http://arduino.clanweb.eu/studna_s_prekladom/, alebo (HTTPS konektivita):
https://hladinomer.000webhostapp.com/ s vašim hardvérom pre implementáciu v prostredí Arduino IDE, alebo ESP-IDF pre mikrokontróler ESP32. Pre skompilovanie firmvéru vo frameworku ESP-IDF je potrebné stiahnuť aj projektový priečinok v repozitári projektu, ktorý obsahuje knižnicu pre komunikáciu s ultrazvukovými senzormi vzdialenosti. Zdrojové kódy jednotlivých projektov sú navrhnuté pre prenos dát na vyššie odkazované webové rozhrania, ktoré sú verejne dostupné na internete.
Implementácia bola otestovaná v release verziách ESP-IDF frameworku 4.2, 4.3.2, mala by byť plne kompatibilná aj s 4.0. Implementácie sú dostupné aj na Githube v repozitári projektu rozdelené podľa použitého komunikačného protokolu:
https://github.com/martinius96/hladinomer-studna-scripty/tree/master/examples/HladinomerViac informácii o projekte vrátane schém zapojenia, popisu podporovaného hardvéru nájdete na stránkach projektu, kde sú vždy aktuálne informácie:
https://martinius96.github.io/hladinomer-studna-scripty/Dodatok na záver: Nenastavujte prioritu tasku na 0, lebo sa nezačne vykonávať! Ušetríte si tým pár minút až hodín času analyzovaním chyby v zdrojovom kóde
.