Esp8266 & C# (UDP)

Spesso capita di dover far comunicare Arduino con qualche altro dispositivo e di volerlo fare via WiFi.

Spesso capita di dover far comunicare Arduino con qualche altro dispositivo e di volerlo fare via WiFi. In questo articolo prenderò in considerazione una comunicazione seriale tramite la WiFi domestica (WPA2-Personal).

In questo articolo utilizzerò un modulo ESP-01.

Panoramica in funzione

Test del modulo ESP-01

Come primo step, voglio fare la cosa più semplice che si possa fare. Scrivere sulla seriale:

  1. l'ip ottenuto (appena disponibile)
  2. ogni secondo, un intero che incrementa di uno solo se l'ESP-8266 è connesso alla rete.

 Il codice da caricare è il seguente:

#include <ESP8266WiFi.h>

//casa
const char* ssid = "inserisci qui il nome della tua rete"; //case sentitive!
const char* password = "password di rete";


WiFiServer wifiServer(80);

void setup() {
  Serial.begin(9600);
  Serial.println("Connecting");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("Connected, IP address: ");
  Serial.println(WiFi.localIP());

  wifiServer.begin();
    
}

int myInt=0;

void loop() {
  myInt++;
  delay(1000);
  Serial.println(myInt);
}

Il risultato atteso è qualcosa di questo tipo:

Connecting
......Connected, IP address: 
192.168.1.250
1
2
3
4

Test trasmissione e ricezione pacchetti UDP

Come secondo step voglio che l'ESP-01 riceva e trasmetta dei pacchetti UDP inviati da un applicativo C#.

Per la trasmissione, Arduino invierà ogni secondo un pacchetto UDP con un valore incrementato di 1 ad ogni ciclo.

Per la ricezione, invierò un pacchetto UDP tramite C# e l'ESP01 lo leggerà.


 Il codice C# è il seguente:

//Ricezione
UdpClient receivingUdpClient = new UdpClient(int.Parse(TxtEsp8266Port.Text));
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);

while (true)
{
   Byte[] receiveBytes = receivingUdpClient.Receive(ref RemoteIpEndPoint);
   TxtFromEsp8266.Text += string.Join(" ", receiveBytes) + Environment.NewLine;
   Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate { }));
}

//Invio
private void Send(string remoteIp, int remotePort, string message)
{
    UdpClient udpClient = new UdpClient(remoteIp, remotePort);
    Byte[] sendBytes = Encoding.ASCII.GetBytes(message);
    udpClient.Send(sendBytes, sendBytes.Length);
}

 Il codice per Arduino invece è il seguente:

#include <ESP8266WiFi.h>
#include <WiFiUDP.h>

//casa
const char* ssid = "nome rete"; //case sensitive
const char* password = "password";


WiFiServer wifiServer(80);
WiFiUDP UDP;


void setup() {
  Serial.begin(9600);
  Serial.println("Connecting");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("Connected, IP address: ");
  Serial.println(WiFi.localIP());

  wifiServer.begin();
  
  i f(UDP.begin(82) == 1)
  {
    Serial.println("Connected");
  }
  else{
    Serial.println("Connection failed");
  }
}
int valore;

char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; 

void loop() {
  valore++;
  
  //send UDP packets
  UDP.beginPacket("192.168.1.162", 82);
  UDP.write(valore);
  UDP.endPacket();
  delay(1000);

  //receive
  int packetSize = UDP.parsePacket();
  i f(packetSize)
  {
    UDP.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);
    Serial.println("Contents:");
    int value = packetBuffer[0]*256 + packetBuffer[1];
    Serial.println(packetBuffer[0]); //first packet
    Serial.println(packetBuffer[1]); //second packet
    Serial.println(value);     
  }   
}

Test comunicazione ESP8266 e Arduino nano

Come terzo step voglio che:

  1. l'Arduino accenda il led sulla sua piccola board quando da C# invio una "a"
  2. l'Arduino spenga il led quando invio un pacchetto UDP che contiene una "b"
  3. Emetta 5 lampeggii quando invio un pacchetto UDP che contiene una "c"
  4. Emetta 10 lampeggii molto veloci quando invio un pacchetto UDP che contiene un carattere diverso dai precedenti

 Il principio di funzionamento è:

  1. Il codice C# che gira su un pc invia un pacchetto UDP contenente l'informazione (a=97, b=98, c=99 oppure altro), all'IP del modulo WiFi su una certa porta (l'82 nel mio caso)
  2. L'ESP8266 che è in ascolto sulla porta, riceve il pacchetto, estrapola l'informazione ricevuta e inoltra un comando sulla sua porta seriale
  3. Un Arduino nano è collegato alla seriale tramite i pin D2 e D3. Di fatto tramite la libreria SoftwareSerial è possibile simulare una seriale. Unico inconveniente è che la velocità è limitata a 9600 baud.
  4. All'Arduino Nano è collegato un display TFT che mostra ciò che è stato ricevuto tramite la seriale connessa ai pin 2 e 3

 Lo schema è il seguente:

Schema dell' Arduino Nano connesso al modulo espo1 e al display TFT

Ecco il codice sorgente da caricare sull' Arduino nano:

#include <Arduino.h>
#include <SoftwareSerial.h>

#include "Adafruit_GFX.h"    // Core graphics library
#include "Adafruit_ST7735.h" // Hardware-specific library for ST7735

#include "SPI.h"


#define TFT_SCLK 13 //clk
#define TFT_MOSI 11 //sda

#define TFT_CS   10
#define TFT_DC   9
#define TFT_RST 8

const int  ARDUINO_SERIAL_RX = 2;
const int  ARDUINO_SERIAL_TX = 3;

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
SoftwareSerial serial_from_esp01(ARDUINO_SERIAL_RX, ARDUINO_SERIAL_TX);
  
void setup() {
  Serial.begin(9600);
  while (!Serial) {
     ; //attendi finché la seriale non sia inizializzata in modo corretto
  }
  Serial.print("Pronto");
  serial_from_esp01.begin(9600);

  tft.initR(INITR_BLACKTAB);
  tft.setRotation( 1 );     
  tft.fillScreen(ST77XX_WHITE);
  tft.setTextSize(1);

  tft.setTextColor(ST77XX_RED);

  tft.setTextSize(1);
}

String cmd_from_esp01_old;
void loop(){
  //devo leggere dalla seriale connessa all'esp01

  i f (serial_from_esp01.available())
  { 
    String cmd_from_esp01 = serial_from_esp01.readString();
    Serial.println(cmd_from_esp01);
    

    tft.setCursor(10,10 );
    tft.setTextColor(ST77XX_WHITE);
    tft.print(cmd_from_esp01_old);
  
    tft.setTextColor(ST77XX_BLACK);
    tft.setCursor(10,10); 
    tft.print(cmd_from_esp01);
    cmd_from_esp01_old=cmd_from_esp01;
  }else{
    //Serial.println("Non pronto");
  }

  
  delay(1);
  }
  

 Il codice da caricare sul modulo ESP01 è il seguente:

#include <ESP8266WiFi.h>
#include <WiFiUDP.h>

//casa
//const char* ssid = "nome rete";
//const char* password = "password rete";


WiFiServer wifiServer(80);
WiFiUDP UDP;


void setup() {
  Serial.begin(9600);
  Serial.println("Connecting");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("Connected, IP address: ");
  Serial.println(WiFi.localIP());

  wifiServer.begin();
  
  i f(UDP.begin(82) == 1)
  {
    Serial.println("Connected");
  }
  else{
    Serial.println("Connection failed");
  }
}
int valore;

char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; 

void loop() {
  valore++;
  
  //send UDP packets
  UDP.beginPacket("192.168.1.19", 82);
  UDP.write(valore);
  UDP.endPacket();
  delay(1000);

  //receive
  int packetSize = UDP.parsePacket();
  i f(packetSize)
  {
    UDP.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);
    
    int value = packetBuffer[0]*256 + packetBuffer[1];
    i f(packetBuffer[0] == 97) //a
    {
      Serial.println("ON");
    }else if(packetBuffer[0] == 98) //b
    {
      Serial.println("OFF");
    }else if(packetBuffer[0] == 99) //c
    {
      Serial.println("BLINK");
    } else 
    {
      Serial.println("ERROR");
    }
   
  }   
}