Realizziamo una multipresa con ESP32 da poter gestire tramite WiFi su PC o Smartphone

Dopo il primo prototipo di multipresa realizzata con ESP8266, consultabile a questo LINK, passiamo ora a progettare e programmare un modello più complesso e pensato per funzionare con ESP32. Adopereremo il WiFi integrato per connettere la dev-board alla rete WiFi di casa e gestirle da locale, tramite un’apposita pagina web.

Progetto

Il progetto consiste in una multipresa a 5 posti, in grado di alimentare fino a 5 dispositivi e gestirli singolarmente. La ESP32 si collegherà alla rete WiFi di casa e ci permetterà di attivare e disattivare ogni singolo relè posto per il controllo di ogni presa.

Vista la nostra necessità di gestire 5 dispositivi, abbiamo preferito realizzare da noi il PCB per il progetto, anche grazie all’aiuto di PCBWay, sponsor del progetto.

Componenti

Il motore di tutto è la nostra ESP32-WROOM-32, che abbiamo imparato a programmare in questo ARTICOLO. Essa gestirà 5 relè con tensione di lavoro a 5V, controllati da 5 Transistor NPN 2n2222. Possiamo anche far attivare o disattivare i relè da 5 pulsanti, qualora non sia possibile farlo da WiFi. Per completare le componenti da saldare sul PCB, annoveriamo anche 5 diodi IN4007, 11 resistenze da 220 Ω, 5 resistenze da 1K Ω, 30 pin header femmina, 6 terminali, 6 Led, 2 switch e un condensatore da 10μF.



Per la scocca della multipresa abbiamo utilizzato un contenitore 2×5 Vimar, 4 prese bipasso Vimar, una presa schuko Vimar, 4 copriforo Vimar, 3 metri di cavo elettrico e una presa bipasso grande, circa 3 metri di cavo elettrico per il neutro, 3 metri per la fase e 3 metri per la messa a terra, un pressacavo, un alimentatore AC-DC 240V-5V da 500mA ottenuto da un vecchio caricabatterie per cellulari e un po’ di cavetti elettrici a cui collegare i led. Infine, per evitare sovraccarichi, un porta fusibile con un fusibile da 15A.

Tutto va, ovviamente, saldato sul PCB (misure 150 mm x 66 mm)che abbiamo realizzato con Fritzing, non tra i migliori software, ma sufficientemente adatto per questo tipo di lavoro. Lasceremo a disposizione il file Gerber da scaricare QUI e più avanti spiegheremo più nel dettaglio alcuni collegamenti.

Lista componenti su Amazon:



Collegamenti

Analizzando i collegamenti della Multipresa WiFi, partiamo prima dai collegamenti sul PCB e poi passeremo a quelli elettrici. Adopereremo i pin digitali 12, 13, 18, 19, 25 per inviare un segnale alla Base del transistor NPN. Tra ogni pin e transistor è stata posta una resistenza da 1KΩ. Tutto il sistema sarà alimentato a 5V, partendo dal terminale e trovando, subito dopo, una resistenza da 220 Ω e un led verde per attestare il passaggio di corrente. Più avanti uno switch che consentirà alla corrente di arrivare al pin Vin della dev-board e fornire alimentare tutto il resto degli attuatori. La tensione a 5V arriva anche ai relè, ai quali colleghiamo un diodo e un led rosso con relativa resistenza da 200 Ω; serviranno da ponte per il pin del ground del relè e serviranno per evitare ritorni di corrente e avvisarci quando il relè si attiva. Ponete attenzione a come collegare il diodo, poichè se sbagliate il verso esso non farà passare la corrente: il catodo (riconoscibile dalla striscia bianca) va connesso al Vcc del relè, mentre l’anodo al GND. Passiamo ora al collegamento del transistor: abbiamo tre pin di connessione, da sinistra verso destra troviamo Emettitore, Base e Collettore. L’Emettitore va connesso al GND, la Base, come detto sopra, ad uno dei pin digitali, mentre il Collettore va connesso al ground del relè.

Multipresa WiFi

Per la parte elettrica dedicata al relè, abbiamo adoperato il pin del NC (normalmente chiuso), in modo tale che l’interruttore sia nella posizione per far passare corrente.

Abbiamo poi adoperato anche i pin digitali 4, 5, 23, 26 e 27 per collegarci dei pulsanti. Alla loro pressione, i relè si attiveranno o disattiveranno, facendo così passare o meno la corrente alle prese. Concludiamo questa prima parte, annoverando che abbiamo anche incluso nel PCB un condensatore e uno switch tra il pin Enable e Ground della ESP32, in modo da poterla programmare direttamente mentre è sul PCB. Ricordatevi di spostare il relativo switch sulla posizione corretta per attivare la modalità di programmazione e di spostare anche l’altro switch del PCB, in modo da interrompere l’alimentazione diretta alla dev-board e evitare così problemi.

Passando alla parte elettrica, nella Multipresa WiFi adoperiamo non sono CC ma anche CA ad alto voltaggio, quindi non adoperatevi in questo progetto se non avete le giuste competenze. Nello schema in basso mostriamo nel modo più semplice possibile i collegamenti elettrici. Come si evince, ogni fase entra nel NC (normalmente chiuso) del relè e poi riparte dal COM (comune) dello stesso relè, così ogni presa è autonoma dalle altre. L’alimentatore AC-DC 240V-5V alimenta poi il PCB, fornendo tensione alla ESP32 ed ai relè.

Non abbiamo saldato direttamente i led al PCB, ma abbiamo deciso di sistemare ogni led sopra la corrispettiva presa, praticando un foro sul contenitore 2×5 e utilizzando dei cavetti elettrici per collegarli al PCB. Per la fase di montaggio della Multipresa WiFi vi consigliamo di numerare con attenzione i cavi, per evitare problemi nella fase finale di montaggio.

Codice

Nel codice della Multipresa WiFi, scaricabile a questo LINK, utilizziamo solo due librerie: la WiFi.h per la gestione dell’omonima connessione e la libreria ESPmDNS.h per dare un nome al nostro DNS e trovarlo facilmente. Notate bene che questa libreria funziona egregiamente per tutti i dispositivi, eccezion fatta per quelli mobile. Per tale ragione, da smartphone e tablet ci serviremo dell’indirizzo IP, che renderemo statico. Impostiamo anche il nome della rete WiFi e la relativa password, poi creiamo alcune stringe per gestire il cambiamento di stato dei relè e adoperiamo alcune variabili per la gestione dei tempi di risposta e richiesta tra server e client.


#include <WiFi.h>
#include <ESPmDNS.h>

const char* ssid = "nome-rete";
const char* password = "password-rete";

IPAddress local_IP(192, 168, 1, 153);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);

WiFiServer server(80);

unsigned long currentTime = millis();
unsigned long previousTime = 0;
const long timeoutTime = 2000;

String header;
String stato1 = "off";
String stato2 = "off";
String stato3 = "off";
String stato4 = "off";
String stato5 = "off";

Nel VOID SETUP impostiamo la direzione dei pin a cui collegheremo i relè e i pulsanti, predisponiamo i relè in modo che siano posizionati in modo da aprire il circuito e avviamo il monitor seriale.


pinMode(12, OUTPUT); // relè R2
pinMode(13, OUTPUT); // relè R1
pinMode(18, OUTPUT); // relè R4
pinMode(19, OUTPUT); // relè R5
pinMode(25, OUTPUT); // relè R3
pinMode(4, INPUT); // pulsante S3
pinMode(5, INPUT); // pulsante S4
pinMode(23, INPUT); // pulsante S5
pinMode(27, INPUT); // pulsante S6
pinMode(26, INPUT); // pulsante S7

digitalWrite(12, HIGH);
digitalWrite(13, HIGH);
digitalWrite(18, HIGH);
digitalWrite(19, HIGH);
digitalWrite(25, HIGH);

Serial.begin(9600);

Avviamo ora la connessione alla rete WiFi, creiamo il nostro DNS personalizzato e avviamo la ESP32 come server.


if (!WiFi.config(local_IP, gateway, subnet)) {
Serial.println("Impossibile assegnare IP Statico");
}

WiFi.begin(ssid, password);
Serial.print("Connessione");
while( WiFi.status() != WL_CONNECTED ){
delay(500);
Serial.print(".");
}

Serial.println("Connessione WiFi avvenuta!");
Serial.print("Indirizzo IP: ");
Serial.println(WiFi.localIP() );

if (MDNS.begin("multisocket")) {
Serial.println("http://multisocket.local/");
}

server.begin();

Nel VOID LOOP eseguiamo una serie di cicli while per cambiare lo stato dei relè ad ogni pressione dei pulsanti, in modo tale che con lo stesso pulsante attiviamo il relè finché non verrà ripremuto.


while (digitalRead(4)==HIGH){
digitalWrite(13, !digitalRead(13));
delay (500);
}

while (digitalRead(5)==HIGH){
digitalWrite(12, !digitalRead(12));
delay (500);
}

while (digitalRead(23)==HIGH){
digitalWrite(25, !digitalRead(25));
delay (500);
}

while (digitalRead(27)==HIGH){
digitalWrite(18, !digitalRead(18));
delay (500);
}

while (digitalRead(26)==HIGH){
digitalWrite(19, !digitalRead(19));
delay (500);
}

Passiamo ora alla verifica del client. Se si connetterà, stampiamo un messaggio sul monitor seriale, poi memorizziamo sulla stringa currentLine i dati in arrivo dal client. Durante tutto il tempo in cui il client rimane connesso, i dati ricevuti vengono letti e stampati su monitor seriale.



All’arrivo di una linea vuota, generata da \n, il client rimane in attesa di una risposta dal server.


WiFiClient client = server.available();
if (client) {
currentTime = millis();
previousTime = currentTime;
Serial.println("Nuovo Client");
String currentLine = "";
while (client.connected() && currentTime - previousTime <= timeoutTime) {
currentTime = millis();
if (client.available()) {
char c = client.read();
Serial.write(c);
header += c;
if (c == '\n') {
if (currentLine.length() == 0) {
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();

Si procede ora al cambio dello stato dei singoli relè. Ognuno sarà poi essenziale al fine di permettere alla pagina web che creiamo, di cambiare anche lo stato dei pulsanti.


if (header.indexOf("GET /Relay01/on") >= 0) {
Serial.println("Attiva relè 1");
stato1 = "on";
digitalWrite(13, LOW);
}
else if (header.indexOf("GET /Relay01/off") >= 0) {
Serial.println("Spegni relè 1");
stato1 = "off";
digitalWrite(13, HIGH);
}
else if (header.indexOf("GET /Relay02/on") >= 0) {
Serial.println("Attiva relè 2");
stato2 = "on";
digitalWrite(12, LOW);
}
else if (header.indexOf("GET /Relay02/off") >= 0) {
Serial.println("Spegni relè 2");
stato2 = "off";
digitalWrite(12, HIGH);
}
else if (header.indexOf("GET /Relay03/on") >= 0) {
Serial.println("Attiva relè 3");
stato3 = "on";
digitalWrite(25, LOW);
}
else if (header.indexOf("GET /Relay03/off") >= 0) {
Serial.println("Spegni relè 3 ");
stato3 = "off";
digitalWrite(25, HIGH);
}
else if (header.indexOf("GET /Relay04/on") >= 0) {
Serial.println("Attiva relè 4");
stato4 = "on";
digitalWrite(18, LOW);
}
else if (header.indexOf("GET /Relay04/off") >= 0) {
Serial.println("Spegni relè 4 ");
stato4 = "off";
digitalWrite(18, HIGH);
}
else if (header.indexOf("GET /Relay05/on") >= 0) {
Serial.println("Attiva relè 5");
stato5 = "on";
digitalWrite(19, LOW);
}
else if (header.indexOf("GET /Relay05/off") >= 0) {
Serial.println("Spegni relè 5 ");
stato5 = "off";
digitalWrite(19, HIGH);
}

Creiamo ora la pagina web con i relativi pulsanti, poi stoppiamo la connessione tra client e server se non ci sono ulteriori richieste e si torna ad attendere eventuali connessioni.


client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"icon\" href=\"data:,\">");
client.println("<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cstyle%3Ehtml%20%7B%20font-family%3A%20Helvetica%3B%20display%3A%20inline-block%3B%20margin%3A%200px%20auto%3B%20text-align%3A%20center%3B%7D%22)%3B%0Aclient.println(%22.button%20%7B%20background-color%3A%20%234CAF50%3B%20border%3A%20groove%3B%20color%3A%20white%3B%20padding%3A%2016px%2040px%3B%22)%3B%0Aclient.println(%22text-decoration%3A%20none%3B%20font-size%3A%2030px%3B%20margin%3A%202px%3B%20cursor%3A%20pointer%3B%7D%22)%3B%0Aclient.println(%22.button2%20%7Bbackground-color%3A%20%23F14E4E%3B%7D%3C%2Fstyle%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;style&gt;" title="&lt;style&gt;" /></head>");
//Mostra titolo
client.println("<body style='background-color:darkslategray'><h1><font color='white'>Multipresa WiFi</font></h1>");

client.println("<p><font color='white'>Rele' 01</font></p>");
if (stato1=="off") {
client.println("<p><a href=\"/Relay01/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/Relay01/off\"><button class=\"button button2\">OFF</button></a></p>");
}

client.println("<p><font color='white'>Rele' 02</font></p>");
if (stato2=="off") {
client.println("<p><a href=\"/Relay02/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/Relay02/off\"><button class=\"button button2\">OFF</button></a></p>");
}

client.println("<p><font color='white'>Rele' 03</font></p>");
if (stato3=="off") {
client.println("<p><a href=\"/Relay03/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/Relay03/off\"><button class=\"button button2\">OFF</button></a></p>");
}

client.println("<p><font color='white'>Rele' 04</font></p>");
if (stato4=="off") {
client.println("<p><a href=\"/Relay04/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/Relay04/off\"><button class=\"button button2\">OFF</button></a></p>");
}

client.println("<p><font color='white'>Rele' 05</font></p>");
if (stato5=="off") {
client.println("<p><a href=\"/Relay05/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/Relay05/off\"><button class=\"button button2\">OFF</button></a></p>");
}
client.println("</body></html>");

client.println();

// Interrompiamo a questo punto il ciclo while
break;
} else { // se non c'è altro, ripuliamo la stringa
currentLine = "";
}
} else if (c != '\r') {
currentLine += c;
}
}
}

header = "";

client.stop();
Serial.println("Client disconnesso.");
Serial.println("");
}

Non ci resta che caricare lo sketch sulla ESP32 e verificare che tutti i collegamenti siano corretti. Diamo corrente all’insieme e accediamo da browser al DNS scelto e proviamo ad interfacciarsi con la nostra Multipresa WiFi realizzata con ESP32.