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 aj pre začiatočníkov. Existuje však aj framework pre vývoj IoT aplikácii - ESP-IDF 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.
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 procesora (ESP32 používa dvojjadrový procesor Xtensa), 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á okrem stacku aj prioritu s možnosťou zvolenia jadra procesora Xtensa 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. Štandardné podporogramy pre meranie je vhodné spúšťať na druhom tzv. aplikačnom jadre procesora Xtensa.
FreeRTOS som využíval posledný rok pri vytváraní demonštračnej aplikácie senzorového uzla na ESP32 v diplomovej práci. Rozhodol som sa vytvoriť ukážkovú implementáciu aj do projektu Hladinomer, ktorý ESP32 využíva, avšak program bol vytvorený iba v prostredí Arduino IDE. 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. Queue využíva FIFO buffer, t.j. prvá položka pridaná do fronty je čítaná druhým taskom čítaná ako prvá (First in, First out). 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
- Čaká 300 sekúnd
Task B (consumer task - používa dáta)
- Čaká na dostupné dáta v Queue
- Počas čakania nevyužíva procesorový čas, ktorý môže efektívne využívať iný task
- Po prijatí dát vymaže prvok z Queue
- Vykoná jednorázový HTTP(S) POST request s dátami na webserver
Po úspešnom prevzatí položky z fronty je táto položka z buffra vymazaná. 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, 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 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 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 iba 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 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 request obsahoval aj inicializáciu WiFi adaptéru 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 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 (v CLI ESP-IDF je netruálna farba biela).
Po pripojení na WiFi sieť získa ESP32 okrem IPv4 aj IPv6 link-local adresu. 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.
HTTP 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í. Okamžite po prijatí dát sa HTTP 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.
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/Hladinomer
Viac 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/