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.
Test del modulo ESP-01
Come primo step, voglio fare la cosa più semplice che si possa fare. Scrivere sulla seriale:
- l'ip ottenuto (appena disponibile)
- 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:
- l'Arduino accenda il led sulla sua piccola board quando da C# invio una "a"
- l'Arduino spenga il led quando invio un pacchetto UDP che contiene una "b"
- Emetta 5 lampeggii quando invio un pacchetto UDP che contiene una "c"
- Emetta 10 lampeggii molto veloci quando invio un pacchetto UDP che contiene un carattere diverso dai precedenti
Il principio di funzionamento è:
- 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)
- L'ESP8266 che è in ascolto sulla porta, riceve il pacchetto, estrapola l'informazione ricevuta e inoltra un comando sulla sua porta seriale
- 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.
- 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:
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");
}
}
}