In questo esempio IoT utilizzo il modulo ESP8266-12E per comandare da remoto, tramite WI-FI, dei relè, che a loro volta comandano un telecomando per cancello.
componenticomponenti
L'apertura del cancello è solo una delle tante applicazioni, in quanto avendo dei relè con contatto pulito, si può comandare qualsiasi altro apparecchio (lampade, stereo, tv, ...).
In questo esempio volevo mettere in evidenza come non sempre è necessario conoscere come funziona un cancello automatico o altro apparecchio, a volte si può aggirare il problema, in questo caso pilotandolo tramite il telecomando. Inoltre, questo approccio, evita di dover stendere dei fili per arrivare alla centralina del cancello non sempre possibile soprattutto quando si tratta di un cancello condominiale.
Lo stesso principio potrebbe essere utilizzato, ad esempio, per comandare l'accensione della TV collegando il circuito al pulsante di accensione di un telecomando ad infrarossi puntato verso la TV.
Premessa: come si vede dalla figura, perchè il tutto funzioni, l'ESP deve essere in una zona dove arriva il segnale WI-FI di casa e il telecomando deve essere ad una distanza tale per cui il sengale radio arrivi al cancello.
Se poi il WI-FI è raggiungibile anche all'esterno del cancello, sarà possibile con il cellulare pilotare l'apertura inserendo l'apposita url nel browser (vedi dopo).

Quello che serve per la realizzazione è:
  • ESP8266 con firmware NodeMCU (programmabile con l'IDE di Arduino)
  • Basetta di prototipazione e alimentazione per ESP8266
  • Alimentatore da 6 a 24 V cc da collegare alla basetta
  • Modulo 2 Relè
  • Telecomando cancello
componenticomponenti
La moneta da 1 euro è solo come paragone per valutare le dimensioni
Collegamenti circuitoCollegamenti circuito
I collegamenti sono semplici. L'ESP8266 va collegato al modulo relè tramite 4 fili:
  • bianco: alimentazione +5V
  • nero: GND
  • giallo: ESP pin D0 - relè IN1
  • arancio: ESP pin D1 - relè IN2
successivamente andrà preso il telecomando del cancello e andrà smontato per saldare due fili direttamente sul pulsante di apertura.
Nel mio caso ci sono 2 cacnelli, uno di ingresso e uno di uscita quindi nella foto compaiono 2 pulsanti collegati ognuno ad un relè.
ATTENZIONE: l'ESP è alimentato a 3,3V e NON a 5V, quindi, serve sempre un convertitore di tensione. Nell'esempio è la basetta che fa da convertitore e fornisce i 3,3V per l'ESP e i 5V per il modulo relè. Il telecomando è alimentato dalla sua batteria.
Perchè il codice seguente funzioni è necessario che l'ESP abbia montato il firmware NodeMCU.

Per programmare l'ESP utilizzo L'IDE di Arduino con le estensioni per l'ESP:
EditorEditor
Se collegando l'ESP alla USB il computer non la riconosce, prova ad alimentarla con un alimentatore esterno tramite la basetta o altro convertitore di tensione.

Il codice per comandare i relè tramite WI-FI è il seguente:
#include <ESP8266WiFi.h>

// definizione costanti
const char WiFiSSID[] = "ssid-xxx";
const char WiFiPSK[] = "password";
const int RELE1_PIN = 16; // D0 - GPI16
const int RELE2_PIN = 5; // D1 - GPIO5
const int DELAY_RELE = 700;  // ritardo in millisecondi
// IP statico
IPAddress ip(192, 168, 1, 50);
IPAddress gateway(192,168,1,254);
IPAddress subnet(255,255,255,0);

// inizializzazione server
WiFiServer server(80);

void initWiFi() {
  // tento di connetermi alla WI-FI
  Serial.println();
  Serial.println("Attempting to connect to: " + String(WiFiSSID) + " ...");
  //attendo la disponibilità del wifi
  while ( WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(1000);
  }
  // Mi connetto alla WIFI ( WPA/WPA2 )
  WiFi.begin(WiFiSSID, WiFiPSK);
  // setto l'IP statico
  WiFi.config(ip,gateway,subnet);
  Serial.println();
  Serial.print("WiFi connected IP:");
  Serial.print(WiFi.localIP());
}

void initServer(){
  // avvio il server
  server.begin();
  // visualizzo l'indirizzo IP
  Serial.println();
  Serial.print("Use this URL to connect: http://");
  Serial.print(WiFi.localIP());
  Serial.print("/rele/[1|2]");
  Serial.println();
}

void digitalWritePulse(int pin, int delayMilliseconds){
    digitalWrite(RELE1_PIN, LOW);
    delay(delayMilliseconds);
    digitalWrite(RELE1_PIN, HIGH);
}

void sendResponse(WiFiClient client, int result){
  // invio la risposta
  client.flush();
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println(""); // questo è indispensabile
  if(result == -1){
    client.print("ERROR");
    Serial.println("ERROR");
  } else {
    client.print(result);
    Serial.println(result);
  }
}

// inizio
void setup() {
  Serial.begin(9600);
  delay(10);
  // imposto le uscite
  pinMode(RELE1_PIN, OUTPUT);
  digitalWrite(RELE1_PIN, HIGH);
  pinMode(RELE2_PIN, OUTPUT);
  digitalWrite(RELE2_PIN, HIGH);

  initWiFi();
  initServer();
}

void loop() {
  // aspetto che un client si connetta
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
  // attendo che invii qualche dato
  while(!client.available()){
    delay(1);
  }
  // leggo la prima linea della richiesta (attenzione è CASE SENSITIVE)
  String request = client.readStringUntil('\r');
  Serial.println(request);

  // routing gestione url
  // verifico la url e attivo il relè per N secondi
  int releNumber = -1;
  if (request.indexOf("GET /rele/1 ") != -1) {
    digitalWritePulse(RELE1_PIN, DELAY_RELE);
    releNumber= 1;
  } else if (request.indexOf("GET /rele/2 ") != -1) {
    digitalWritePulse(RELE2_PIN, DELAY_RELE);
    releNumber = 2;
  } else if (request.indexOf("GET /rele/1/on ") != -1) {
    digitalWrite(RELE1_PIN, LOW);
    releNumber = 1;
  } else if (request.indexOf("GET /rele/1/off ") != -1) {
    digitalWrite(RELE1_PIN, HIGH);
    releNumber = 0;
  }  
  
  sendResponse(client, releNumber);
}
Vanno valorizzate le variabili WiFiSSID e WiFiPSK con i valori della tua rete. Poi va settato l'ip statico compatibile con il tuo indirizzamento (192.168.50), netmask e gateway.

Il tutto parte dal metodo setup che inizializza il WI-FI e gli I/O. Poi verrà chiamato in automatico il metodo loop ciclicamente che rimane in attesa di una url, fa il parsing e comanda le uscite.

Per pilotare i relè è sufficiente digitare nel browser un indirizzo formato come segue: http://<indirizzo ip>/rele/<numero rele>.
Quindi per pilotare il relè 1 con un impulso (la durata è nel codice, variabile DELAY_RELE) andrà digitato: http://192.168.1.50/rele/1 , mentre per il relè 2 diventa http://192.168.1.50/rele/2 .

Esiste anche la possibilità di pilotare il relè 1 in modalità bistabile e non ad impulso, questo torna utile nel caso si volesse pilotare una lampada
Per eccitare (attivare) il relè 1 la url diventa http://192.168.3.50/rele/1/on . Mentre per diseccitarlo (spegnerlo) devi digitare http://192.168.1.50/rele/1/off .
Le url sono case sensitive.
Sul telefono è possibile fare il "pin" della url sulla schermata home in modo da eseguire il comando con un semplice click sull'icona.

Posso anche pilotare i relè tramite script sia manualmente che schedularlo per essere eseguito ad una certa ora. Ad esempio per pilotare l'apertura del cancello da PowerShell:
(new-object System.Net.WebClient).DownloadString("http://192.168.1.50/rele/1")

Alcune considerazioni sulla sicurezza
Il progetto non implementa nessun meccanismo di sicurezza (leggi password, certificati, sso ...) quindi chiunque in possesso della url può comandare i relè (accesso anonimo). L'unico meccanismo di sicurezza è dato dall'SSID e dalla password/key di accesso alla rete WI-FI. Per questo motivo è sconsigliata la pubblicazione in internet tramite Dinamic DNS.