Nell'ambiente di Arduino c'è un esempio che farà lampeggiare il led del modulo ESP8266. Con questo esempio potremo verificare che tutto funzioni correttamente.
Aprire il programma di esempio da File | Esempi | ESP8266 | Blink
Inserire nella porta USB il convertitore con montato il modulo ESP8266 e inserito il jumper per avviare il bootloader (il led rosso acceso).
Selezionare la porta corretta dal menù Strumenti
Selezionare il comando Sketch | Carica (se non funziona estrarre e reinserire, a me ha funzionato al terzo tentativo)
Alla fine della programmazione il LED blu inizierà a lampeggiare.
Il modulo ESP8266 ha una porta seriale che sarà utile come interfaccia e debug.
Per usare la porta seriale basta chiamare la funzione di inizializzazione begin dell'oggetto Serial:
Serial.begin(115200);
e ogni volta che si vuole visualizzare un messaggio basta passare il testo alla funzione print o println sempre dell'oggetto Serial:
Serial.println("Qualcosa");
Per verificare che tutto funzioni bisogna aprire il monitor seriale prima di caricare il nostro nuovo sketch. Importante notare che siccome il nostro ESP è alimentato dallo stesso convertitore USB Seriale, ogni volta che estraiamo e reinseriamo il convertitore per spegnere e riaccendere il modulo potremmo dover chiudere e riaprire il monitor seriale.
Creare un nuovo programma (Sketch) e copiare il codice dell'esempio
Inserire nella porta USB il convertitore con montato il modulo ESP8266 e inserito il jumper per avviare il bootloader.
Selezionare la porta corretta dal menù Strumenti
Selezionare il comando Strumenti | Monitor seriale e indicate nella finestra la velocità che usa il vostro sketch
Selezionare il comando Sketch | Carica (se non funziona estrarre e reinserire, a me ha funzionato al terzo tentativo)
Alla fine della programmazione vedrete visualizzati tutti i messaggi che il vostro programma invierà alla seriale.
Con il modulo ESP8266 è possibile usare una eeprom virtuale. Bisogna ricordare che è possibile scrivere nella memoria non volatile un numero limitato di volte (centinaia di migliaia). Superato il limite non sarà più possibile usare il modulo.
Per usare la eeprom del modulo ESP bisogna includere il file eeprom.h e usare l'oggetto EEPROM. Non essendo una vera eeprom, con begin si crea semplicemente un array nella ram che verrà riempito con i valori presenti nell'area di memoria non volatile. Le operazioni di scrittura e lettura useranno questo array e solo chiamando EEPROM.commit() o EEPROM.end() si avrà il vero e proprio salvataggio dei dati nella memoria non volatile.
EEPROM.Begin(size) serve all'inizializzazione dell'oggetto. Con questa funzione bisogna indicare il numero di byte che si vuole memorizzare nella "eeprom". La dimensione deve essere compresa tra 4 e 4096 (usate multipli di 4).
EEPROM.write(indirizzo, valore) serve a scrivere un singolo byte nella memoria.
EEPROM.read(indirizzo) serve a leggere un singolo byte dalla memoria.
EEPROM.put(indirizzo, variabile) serve a scrivere un valore nella memoria. Questo valore occuperà tanti byte quanti ne richiede il tipo della variabile passata. Per esempio un int occuperà quattro byte, un bool ne occuperà uno, un doble otto, e così via.
EEPROM.get(indirizzo, valore) serve a leggere un valore dalla memoria precedentemente inserito con put().
EEPROM.commit() salva i dati.
EEPROM.end() salva i dati ed elimina l'array. Dopo questo comando non è più possibile usare la eeprom fino a quando non si riusi il comando begin().
Copiare il programma di esempio nell'IDE
Inserire nella porta USB il convertitore con montato il modulo ESP8266 e inserito il jumper per avviare il bootloader.
Selezionare la porta corretta dal menù Strumenti
Selezionare il comando Strumenti | Monitor seriale e indicate nella finestra la velocità che usa il vostro sketch
Selezionare il comando Sketch | Carica (se non funziona estrarre e reinserire, a me ha funzionato al terzo tentativo)
Alla fine della programmazione verrà avviato il programma e dopo dieci secondi verrà visualizzato il valore dell'indirizzo zero della eeprom.
Scollegate ora il modulo dalla porta USB per spegnere il microcontrollore ESP8266.
Togliete il jumper per far partire il nostro programma di esempio all'accensione.
Inserite il modulo nella porta USB e subito avviate il monitor seriale (abbiamo dieci secondi di tempo).
Dopo dieci secondi dall'accensione verrà visualizzato il valore dell'indirizzo zero della eeprom. Subito in questo indirizo il programma scriverà il valore + 10. Se ripetete più volte dal punto 7 vedrete aumentare di dieci il valore contenuto nella eeprom a conferma che la memorizzazione è mantenuta anche spegnendo il modulo.
Per collegarsi al WiFi di casa occorre semplicemente usare il comando WiFi.begin(ssid, password) che chiede il nome identificativo del WiFi e la relativa password. Dalle prove ho notato che nel caso in cui venga perso il collegamento, il modulo tenterà subito di effettuare un nuovo collegamento. Non è quindi necessario scrivere del codice per ripristinare il collegamento nel caso venga perso.
Copiare il programma di esempio
Scrivere il nome della vostra rete WiFi dove viene definita la costante ssid (esempio: const char* ssid = "Vodafone-6677655")
Scrivere la password della vostra rete WiFi dove viene definita la costante password (esempio: const char* password = "67FfrtGfT543De")
Inserire nella porta USB il convertitore con montato il modulo ESP8266 e inserito il jumper per avviare il bootloader.
Selezionare la porta corretta dal menù Strumenti
Selezionare il comando Strumenti | Monitor seriale e indicate nella finestra la velocità 115200 baud rate.
Selezionare il comando Sketch | Carica (se non funziona estrarre e reinserire, a me ha funzionato al terzo tentativo)
Alla fine della programmazione dopo dieci secondi verrà avviata la connessione alla rete WiFi con alcuni dati di diagnosi.
Con il piccolo EPS-01 possiamo creare un webserver a cui accedere tramite un qualsiasi browser. Il brower potrà cosi diventare una comoda interfaccia utente. Il problema è che io non so niente di html e soci. Quindi non farò altro che copiare quello che ho trovato in giro. Comunque qualcosa ho capito:
Per usare il web server includere e create un oggetto passando la porta a cui rispondere (i browser usano di default la porta 80)
#include <ESP8266WebServer.h>
ESP8266WebServer web_server(80);
poi nel void setup(void) si indica quali funzioni richiamare quando vengono aperte delle pagine dal browser:
web_server.onNotFound(funzione_pagina_non_trovata);
web_server.on("/", funzione_pagina_radice);
web_server.on("/pagina1", funzione_pagina_1);
e si avvia il server con:
web_server.begin();
infine nel void loop(void) si richiama il gestore del webserver:
web_server.handleClient();
Copiare il programma di esempio
Scrivere il nome della vostra rete WiFi dove viene definita la costante ssid (esempio: const char* ssid = "Vodafone-6677655")
Scrivere la password della vostra rete WiFi dove viene definita la costante password (esempio: const char* password = "67FfrtGfT543De")
Inserire nella porta USB il convertitore con montato il modulo ESP8266 e inserito il jumper per avviare il bootloader.
Selezionare la porta corretta dal menù Strumenti
Selezionare il comando Strumenti | Monitor seriale e indicate nella finestra la velocità 115200 baud rate.
Selezionare il comando Sketch | Carica (se non funziona estrarre e reinserire, a me ha funzionato al terzo tentativo)
Alla fine della programmazione, dopo dieci secondi, verrà avviata la connessione alla rete WiFi e verrà mostrato l'indirizzo IP del modulo.
Aprite il browser del computer e andate all'indirizzo appena visualizzato.
L'oggetto WebServer può anche fornirci tutti gli argomenti passati nella chiamata della pagina web.
Il seguente esempio visualizza sulla seriale tutte le informazioni di ogni richiesta. La visualizzazione è fatta dalla funzione che viene chiamata per tutte le richieste non previste grazie all'utilizzo della funzione onNotFound() dell'oggetto WebServer.
Copiare il programma di esempio
Scrivere il nome della vostra rete WiFi dove viene definita la costante ssid (esempio: const char* ssid = "Vodafone-6677655")
Scrivere la password della vostra rete WiFi dove viene definita la costante password (esempio: const char* password = "67FfrtGfT543De")
Inserire nella porta USB il convertitore con montato il modulo ESP8266 e inserito il jumper per avviare il bootloader.
Selezionare la porta corretta dal menù Strumenti
Selezionare il comando Strumenti | Monitor seriale e indicate nella finestra la velocità 115200 baud rate.
Selezionare il comando Sketch | Carica (se non funziona estrarre e reinserire, a me ha funzionato al terzo tentativo)
Alla fine della programmazione, dopo dieci secondi, verrà avviata la connessione alla rete WiFi e verrà mostrato l'indirizzo IP del modulo
Aprite il browser del computer e scrivere per esempio l'indirizzo "http://192.168.1.XX/?Cancello=1&Luce=OFF" sostituendo l'ip con quello giusto
Nel monitor seriale vedrete tutti i parametri ben ordinati
Per inserire del testo html nel codice bisogna rispettare tutte le regole del linguaggio C++, per esempio bisogna sostituire le virgolette con \". Esistono dei siti che fanno in automatico questa conversione ma è scomodo e il codice diventa illeggibile.
Per fortuna esiste una seconda possibilità. Si può scrive tutto il testo che si vuole senza formattazione tra le parentesi tonde della stringa strutturata così: R"rawliteral( )rawliteral":
Nota: PROGMEM dice al compilatore di mettere la stringa nella memoria flash al posto della limitata memoria RAM.
Usare l'indirizzo IP per accedere al nostro ESP è scomodo. Molto meglio usare un nome facile da ricordare. Per far questo bisogna dire al dispositivo che si vuole collegare qual'è il nome del nostro ESP. Pare ci siano diversi standard usati dai diversi sistemi operativi. Io ho letto in rete che il vecchio Windows usa NetBIOS, Windows 10 usa anche LLMNR poi c'è il multicast DNS o mDNS. Nell'esempio seguente ho provato a usarli tutti assieme. Purtroppo gli smartphone non integrano uno di questi sistemi e l'unico modo è usare l'indirizzo IP. A questo punto ci vuole un indirizzo IP fisso, che non cambi da solo. Ci sono due strade:
Assegnare al modulo ESP un indirizzo IP fisso che il DHCP del router non può assegnare ad altri dispositivi.
Configurare il DHCP del router in modo che riservi un indirizzo IP per il nostro modulo ESP.
Copiare il programma di esempio
Scrivere il nome della vostra rete WiFi dove viene definita la costante ssid (esempio: const char* ssid = "Vodafone-6677655")
Scrivere la password della vostra rete WiFi dove viene definita la costante password (esempio: const char* password = "67FfrtGfT543De")
Programmare il modulo ESP-01 come al solito
Aprite il browser del computer e scrivere l'indirizzo "http://esp01/"
Per prima cosa bisogna trovare il MAC del nostro modulo
Nelle impostazioni del DHCP bisogna riservare un indirizzo IP al MAC del nostro modulo
Riavviare il DHCP per evitare che l'indirizzo IP sia usato in modo dinamico
In questo esempio è possibile aggiungere un orologio sempre sincronizzato.
Per poter scaricare le previsioni meteo da wunderground.com bisogna registrarsi sul sito http://wunderground.com nella pagina del Log in. La registrazione e il servizio base sono gratuiti ma hanno come limitazione 500 richieste massime al giorno e 10 richieste massime al minuto. Pensando di lasciare acceso il dispositivo tutto il giorno si può fare una richiesta ogni tre minuti. Per avere la chiave d'accesso alle API del sito, bisogna registrare l'applicazione in https://www.wunderground.com/weather/api/ . Questa chiave andrà inserita nel progetto. Bisogna inoltre installare la libreria ArduinoJson (io ho usato la versione 5.13.1) dal menu sketch > gestione librerie.
Scaricare il programma di esempio: download
Scrivere il nome della vostra rete WiFi dove vengono definite le costanti ssid e password.
Scrivere le proprie coordinate dove vengono definite latitudine e longitudine.
Scrivere la propria chiave di accesso dove viene definita la costante WU_API_KEY;
Aprire il monitor seriale
Programmare il modulo ESP-01 come al solito
Quando ho visto che il server di wether underground forniva anche lo scostamento dell'ora rispetto il riferimento standard UTC ho pensato di fare un orologio che cambiasse tra ora solare o ora legale da solo.
Qui puoi scaricare un esempio di orologio sempre sincronizzato che stampa l'ora sulla seriale: download.
Qui puoi scaricare un esempio di orologio sempre sincronizzato con display OLED I2C: esempio_ora_oled.
Le mie librerie son qui: download.
Una delle cose più interessante del modulo ESP8266 è la capacità di trasformarsi in un access point. In pratica è possibile creare una propria rete WiFi a cui si può accedere con qualsiasi dispositivo. Questa capacità con la possibilità di creare un WebServer permette di usare il browser come interfaccia verso il modulo anche quando non siamo collegati alla rete locale di casa.
La disponibilità della EEPROM, il web server e l'access point permettono di costruire un'interfaccia utente dove inserire la configurazione del modulo ESP senza doverlo ogni volta collegare al computer.
Attratto da questa possibilità ho realizzato una classe che gestisce l'accensione dell'access point per la configurazione del modulo tramite browser.
L'oggetto MRWebSetup prova continuamente ad accedere alla rete WiFi di casa e se non ci riesce attiva l'access point in modo che con un qualsiasi dispositivo ci si possa comunque collegare al modulo per cambiare i dati della WiFi di casa. Anche dopo aver attivato l'access point tenta di collegarsi alla rete di casa, se ci riesce spegnerà l'access point.
Per usare la mia classe bisogna creare l'oggetto e chiamare begin con il nome della rete wifi e la relativa password. Queste informazioni devono essere recuperate dalla EEPROM.
Nel loop bisogna chiamare la funzione handleClient che gestisce le connessioni.
Se si desidera avere i messaggi di debug sulla seriale chiamare prima di tutto setupDiag pessandogli l'oggetto dove inviare i messaggi di debug.
Se non si vuole usare il nome di default della rete WiFi che viene accessa se fallisce il collegamento alla wifi di casa bisogna chiamare setupAP con il nome e la password della rete da creare.
Se si vuole la lista delle reti wifi disponibili bisogna passare il puntatore alla funzione onNewList() che sarà chiamata ogni volta che la lista sarà aggiornata.
La classe e un esempio lo trovi qui: MRWebSetup.
Altra cosa molto interessante è la programmazione via WiFi.
Devo ammettere che per me non è stato facile far funzionare questa cosa. Io non avevo mai la voce del menù con le porte di rete nell'IDE. Ho cercato tantissimo in rete. Ad un certo punto ho pensato anche che non fosse compatibile con il modulo ESP-01. Ogni tanto si parlava di installare Python ma non capivo cosa c'entrasse. Fino a quando ho trovato in rete una guida in cui c'era chiaramente scritto che serve installare Python. Così ho installato la versione 2.7.13 e finalmente funziona tutto.
Quindi il piccolo ESP-01 è compatibile, almeno la versione nera da 1M di flash.
Il programma deve ovviamente occupare meno del 50% della memoria disponibile.
Scegliendo la porta WiFi non è più disponibile il monitor seriale. Come alternativa io ho scelto il programma Hercules, leggero e semplice. Si seleziona la porta COM, il baud rate e un clic su Open.
Il computer deve essere collegato alla stessa LAN a cui è collegato il modulo.
Altra cosa fondamentale è chiudere l'IDE (tutte le istanze) e riaprirlo dopo aver programmato il modulo via seriale.
Ecco come fare:
Scaricare e installare Python versione 2.7
Avviare Arduino IDE
Aprire il programma di esempio da File | Esempi | ArduinoOTA | BasicOTA
Scrivere il nome della vostra rete WiFi dove viene definita la costante ssid (esempio: const char* ssid = "Vodafone-6677655")
Scrivere la password della vostra rete WiFi dove viene definita la costante password (esempio: const char* password = "67FfrtGfT543De")
Mettere come prima istruzione nel Setup() la linea delay(10000);
Inserire nella porta USB il modulo ESP8266.
Selezionare la porta corretta dal menù Strumenti
Programmare il modulo ESP-01 come al solito
Chiudere l'IDE
Scollegare il modulo, togliere il jumper e ricollegare il modulo alla porta USB
Avviare Hercules e collegarlo alla porta seriale del modulo.
Attendere qualche secondo in modo che il modulo si ricolleghi alla rete WiFi.
Avviare di nuovo l'IDE
Scegliere il comando Strumenti | Porta | Porta di rete...
Modificare lo sketch, per esempio, cambiando un testo inviato sulla seriale
Selezionare il comando Sketch | Carica
Se come me non riuscite a programmare senza vedere cosa succede l'uso della seriale per il debug è fondamentale. Ma come fare quando il modulo non è collegato al computer?
Per trasferire i programmi c'è l'OTA ma per il debug?
Io ho pensato di usare pacchetti UDP. Protocollo tanto semplice quanto efficace.
Il funzionamento di una comunicazione UDP è davvero semplice: ci si mette in ascolto di pacchetti su una porta TCP e si mandano pacchetti verso una porta dell'altro interlocutore identificato dal suo indirizzo IP.
Questa è l'istruzione per inizializzare l'UDP e mettersi in ascolto:
Udp.begin(portaLocare);
Queste sono le istruzioni da usare per inviare un pacchetto:
Udp.beginPacket(IPremoto, portaRemota);
Udp.write(Pacchetto);
Udp.endPacket();
Esempio
Qui puoi scaricare il mio sketch che comprende il debug su UDP e la libreria OTA e la possibilità di fare il setup del modulo da browser; download
Dopo mille tentativi ho dedotto che la libreria WiFiUdp è difettosa. I pacchetti con vengono spediti per intero e dopo ogni pacchetto bisogna mettere un ritardo di qualche millisecondo.
Per comandare il display OLED con chip SSD1306 bisogna installare due librerie: Adafruit SSD1306 e Adafruit GFX.
Installate le librerie bisogna impostare nel file Adafruit_SSD1306.h la risoluzione del display;
quindi rendete non commentata la linea #define SSD1306_128_64 e commentate la linea #define SSD1306_128_32.
È possibile cambiare i piedini usati per comunicare in I2C aggiungendo la seguente linea all'inizio della funzione setup: Wire.begin(SDA_PIN, SCL_PIN);
MQTT è un protocollo molto semplice che permette la comunicazioni tra dispositivi diversi. Questo protocollo si appoggia a un server che viene chiamato broker (intermediario). Per fortuna è possibile usare dei server che danno accesso gratuito con qualche limitazione. Quindi per prima cosa bisogna creare un account da un "broker".
Io ho provato io.adafruit ma anche CloudMQTT è molto usato. Dopo essersi registrati bisogna creare i feeds ovvero nomi dei segnali che si vogliono scambiare tra i dispositivi. Per esempio "TemperaturaSala", "CancelloAperto", "LuceScala", "SerraturaCancello", ecc.
Creati i feeds bisogna inserire i dati per far collegare il modulo ESP8266 al broker nel nostro programma. Con io.adafruit il nome utente è lo stesso usato per registrarsi, la porta è 1883 e la password o Key si trova cliccando su View AIO Key (con CloudMQTT bisogna invece trovare tutti i dati cliccando su DETAILS).
Per provare il funzionamento o controllare lo stato del nostro programma, dal sito di io.adafruit è disponibile una dashboards dove aggiungere pulsanti e indicatori collegati ai feeds.
Esistono diverse librerie per ESP8266 che implementano il protocollo MQTT. Ho scelto la libreria PubSubClient perché vedo che è molto usata.
Selezionare il comando Sketch | Include libreria | Gestione librerie.
Nella casella di ricerca scrivere MQTT.
Installare la libreria PubSubClient.
Il pin TX è la porta GPIO1
Il pin RX è la porta GPIO3
Alimentazione 3.3 V, assorbimento massimo 240 mA
Per espandere le uscite: PCF8574 o MCP23008
Istruzioni per file system e per far apparire il comando Data Upload nell'IDE: https://github.com/esp8266/Arduino/blob/master/doc/filesystem.rst
Istruzioni per l'uso delle GPIO: https://randomnerdtutorials.com/esp8266-pinout-reference-gpios/
Istruzione per l'uso dei pin del modulo ESP-01: https://www.instructables.com/How-to-use-the-ESP8266-01-pins/