IoT Prakticky: Ovládanie digitálneho výstupu ESP32 prostredníctvom UDP datagramov

Mikrokontroléry
0

S technickými parametrami vývojovej dosky ESP32, prvotnou konfiguráciou, ale aj prvým “Blink” programom v prostredí Arduino IDE ste sa bližšie mohli zoznámiť v predchádzajúcom článku na pcrevue.sk. Ako je z článku zrejmé, čip ESP32 disponuje okrem značného výkonu aj WiFi konektivitou, ktorá umožňuje toto zariadenie pripojiť do WiFi siete, internetu a zostaviť si vlastné IoT zariadenie. 

Dnes si ukážeme, ako zapnúť a vypnúť LED-ku, či relé (ovládaním digitálneho vývodu) cez domácu WiFi sieť. Programová implementácia projektu bola realizovaná cez prostredie Arduino IDE a je vhodná aj pre začiatočníkov a mierne pokročilých používateľov. Jedným z najjednoduchších riešení je využitie UDP správ - datagramov pre komunikáciu. 

UDP protokol sa radí do skupiny “nespoľahlivých” protokolov, ktoré negarantujú doručenie informácie prijímateľovi, rovnako tak ani viacnásobné doručenie rovnakého datagramu.  UDP má ale aj radu výhod, predovšetkým rýchlosť a vhodnosť pre aplikáciu, kedy server odpovedá jednému, alebo viacerým klientom s dátovo nenáročnými požiadavkami. 

Počiatočná konfigurácia popisuje, ako boli platformy nastavené počas testovania v domácej WiFi sieti:

Platforma
IP ADRESA
UDP PORT - ČÍSLO SLUŽBY
ESP32
192.168.0.102
4444
Packet Sender (Windows)
192.168.0.101
62804 (Zmena nemá vplyv na implementáciu)

Packet Sender
V prvom rade potrebujeme vhodný program pre odosielanie (aj prijímanie) UDP správ, prostredníctvom ktorého budeme môcť komunikovať a prijímať informácie z ESP32. Jedným z najpoužívanejších je Packet Sender, ktorý podporuje okrem protokolu UDP taktiež TCP, SSL. Plne podporuje IPv6 s možnosťou logovania všetkých informácii. Packet Sender je možné stiahnuť z adresy: https://packetsender.com/, pričom je okrem Windows vezie možnosť stiahnuť aj verziu pre Linux, MacOS.
Po inštalácii je nutné Packet Sender nastaviť pre našu UDP aplikáciu. Prejdeme do nastavení File → Settings, kde povolíme UDP Server a zapneme 500ms pauzu po pripojení (pre Slow devices) - v prípade, že nie je táto možnosť navolená, ESP32 nestihne spracovať datagramNásledne prejdeme na úvodné okno Packet Sendera, kde vyplníme informácie o Cieľovej IP adrese a porte (Dáta o ESP32 - cieľová IP a jej port). 

Týmto je nastavenie Packet Sendera ukončené a je pripravený pre odosielanie UDP správ na ESP32 UDP server. Správu (Payload) zadávame do poľa ASCII, hodnotu ZAP, alebo VYP. Parametrom Resend Delay (v sekundách) môžeme nastaviť opakované odosielanie UDP správy automaticky. Ako prenosovú metódu volíme UDP. Tlačidlom Send odošleme správu na cieľovú IP adresu a cieľový port.
ESP32 a programová implementácia UDP servera

Programová implementácia využíva knižnicu AsyncUDP pre UDP server, klient.  Knižnica WiFi obsluhuje pripojenie na domácu WiFi sieť pre dosiahnutie konektivity. Do programu je nutné zadať meno WiFi siete a heslo, na ktorú chcete ESP32 pripojiť. UDP server využíva port 4444, na ktorom očakáva UDP správu. Tento port je definovaný v programe vo funkcii udp.listen. Na základe prijatej UDP správy vypíše ESP32 na UART (Sériovú linku - s rýchlosťou 115200 baud/s) prijaté informácie o IP adrese odosielateľa, prijímateľa, ich portov, taktiež dĺžku správy - payloadu a samotný payload, ktorý obsahuje informáciu, v tomto prípade text ZAP, alebo VYP.  Pre lepšiu predstavu poslúži farebne vyznačený screenshot zo Serial monitoru. 

ESP32 po prijatí informácie aplikuje tento stav na digitálny (vstupno-)výstupný vývod. Aplikuje stav logickú 1, alebo logickú 0. Číslo vývodu, ktoré je použité t.j. 2 je číslo vývodu s integrovanou LED diódou (prípad ESP32 Devkit V1). Sériová linka slúži aj ako informačná zbernica pre používateľa na kontrolu, čo sa “deje” na strane mikrokontroléru a aké informácie prijíma.

Následne ESP32 odpovie UDP správou pôvodnému odosielateľovi s informáciou o dĺžke správy, ktorá bola prijatá. V tomto prípade je dĺžka payloadu vždy 3 bajty. Aj tu ale platí, že prijatie správy na strane Packet Sendera nie je garantované. Programová implementácia bola odtestovaná na verzii Arduino Core 1.0.1 pre ESP32.

Program pre ESP32:

Pôvodný príklad pre UDP server je možné nájsť aj v Arduino core Github repozitári pre ESP32:Repozitár. V mojej implementácii s nástrojom Packet Sender som sa zameral aj na meranie času medzi odoslaním a prijatím informácie od ESP32 (čas odozvy). Rozdiel časov medzi odoslaním UDP správy na ESP32 a prijatím odpovede bola väčšinou na úrovni 90-150ms, čo hodnotím ako prijateľný čas odozvy, nakoľko odozva je už samostatné UDP spojenie, ktorým ESP32 odpovedá nástroju Packet Sender o dĺžke prijatej UDP správy. Aj tu však platí, že správa nemusí byť prijatá na strane Packet Sendera. 

V budúcom článku sa môžete tešiť na praktické príklady klient  server TCP komunikácie založenej na protokole HTTP. Predstavíme si, ako vyhotoviť jednoduchý ESP32 webserver interpretujúci  HTML kód, ktorý dokáže prijímať dáta od iných ESP32 klientov GET a POST metódou. Postavíme si jednoduchú senzorickú sieť, ktorá vizualizuje na ESP32 webserveri posledné namerané dáta od ostatných ESP32 klientov.

Príklady možného rozšírenia projektu:

  • Ovládanie výkonových prvkov (relé, mosfet, tranzistor)
  • Vlastná UDP sieť s desiatkami UDP klientov
  • Prenášanie nameraných údajov zo senzorov (teplota, vlhkosť)
  • Ovládanie RC auta s nízkou odozvou
  • Vzdialené zapnutie TV cez IR vysielač

 

Zdrojový kód

/*|----------------------------------------------------------------------------|*/
/*|SKETCH PRE UDP OVLADANIE ESP32 PROSTREDNICTVOM PROGRAMU PACKET SENDER       |*/
/*|VYHOTOVIL: MARTIN CHLEBOVEC                                                 |*/
/*|Web: https://arduino.php5.sk/udp-control-esp32.php                          |*/
/*|Doska: ESP32 DevkitC v4 / ESP32 Devkit v1                                   |*/
/*|----------------------------------------------------------------------------|*/
 
#include "WiFi.h"
#include "AsyncUDP.h"
const char* ssid = "WIFI_MENO";
const char* pass = "WIFI_HESLO";
const int led = 2; //D pin (Build-in LED pre Devkit V1)
AsyncUDP udp;
 
void setup()
{
  Serial.begin(115200);
  pinMode(led, OUTPUT);
  WiFi.disconnect(true);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, pass);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
 
  if (udp.listen(4444)) {
    Serial.print("UDP server na IP: ");
    Serial.print(WiFi.localIP());
    Serial.println(" port: 4444");
    udp.onPacket([](AsyncUDPPacket packet) {
      Serial.print("Typ UDP datagramu: ");
      Serial.print(packet.isBroadcast() ? "Broadcast" : packet.isMulticast() ? "Multicast" : "Unicast");
      Serial.print(", Odosielatel: ");
      Serial.print(packet.remoteIP());
      Serial.print(":");
      Serial.print(packet.remotePort());
      Serial.print(", Prijimatel: ");
      Serial.print(packet.localIP());
      Serial.print(":");
      Serial.print(packet.localPort());
      Serial.print(", Dlzka spravy: ");
      Serial.print(packet.length()); //dlzka spravy
      Serial.print(", Payload: ");
      Serial.write(packet.data(), packet.length());
      Serial.println();
      String myString = (const char*)packet.data();
      if (myString.startsWith("ZAP")) {
        Serial.println("Akcia: Zapinam rele");
        digitalWrite(led, HIGH);
      } else if (myString.startsWith("VYP")) {
        Serial.println("Akcia: Vypinam rele");
        digitalWrite(led, LOW);
      }
      packet.printf("ESP32 prijalo %u bajty dat", packet.length()); //odpoved odosielatelovi
    });
  }
}
 
void loop()
{
  delay(1000); //nutny delay, UDP sprava sa nestiha nacitat
}

Zdrojový kód RAW Paste data

/*|----------------------------------------------------------------------------|*/
/*|SKETCH PRE UDP OVLADANIE ESP32 PROSTREDNICTVOM PROGRAMU PACKET SENDER       |*/
/*|VYHOTOVIL: MARTIN CHLEBOVEC                                                 |*/
/*|Web: https://arduino.php5.sk/udp-control-esp32.php                          |*/
/*|Doska: ESP32 DevkitC v4 / ESP32 Devkit v1                                   |*/
/*|----------------------------------------------------------------------------|*/
 
#include "WiFi.h"
#include "AsyncUDP.h"
const char* ssid = "WIFI_MENO";
const char* pass = "WIFI_HESLO";
const int led = 2; //D pin (Build-in LED pre Devkit V1)
AsyncUDP udp;
 
void setup()
{
  Serial.begin(115200);
  pinMode(led, OUTPUT);
  WiFi.disconnect(true);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, pass);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
 
  if (udp.listen(4444)) {
    Serial.print("UDP server na IP: ");
    Serial.print(WiFi.localIP());
    Serial.println(" port: 4444");
    udp.onPacket([](AsyncUDPPacket packet) {
      Serial.print("Typ UDP datagramu: ");
      Serial.print(packet.isBroadcast() ? "Broadcast" : packet.isMulticast() ? "Multicast" : "Unicast");
      Serial.print(", Odosielatel: ");
      Serial.print(packet.remoteIP());
      Serial.print(":");
      Serial.print(packet.remotePort());
      Serial.print(", Prijimatel: ");
      Serial.print(packet.localIP());
      Serial.print(":");
      Serial.print(packet.localPort());
      Serial.print(", Dlzka spravy: ");
      Serial.print(packet.length()); //dlzka spravy
      Serial.print(", Payload: ");
      Serial.write(packet.data(), packet.length());
      Serial.println();
      String myString = (const char*)packet.data();
      if (myString.startsWith("ZAP")) {
        Serial.println("Akcia: Zapinam rele");
        digitalWrite(led, HIGH);
      } else if (myString.startsWith("VYP")) {
        Serial.println("Akcia: Vypinam rele");
        digitalWrite(led, LOW);
      }
      packet.printf("ESP32 prijalo %u bajty dat", packet.length()); //odpoved odosielatelovi
    });
  }
}
 
void loop()
{
  delay(1000); //nutny delay, UDP sprava sa nestiha nacitat
}

.

Martin Chlebovec

Všetky autorove články
ESP32 UDP arduino

Pridať komentár

Mohlo by vás zaujímať

Mohlo by vás zaujímať