Feb 262017
 

Gli ESP8266 sono moduli che permettono di aggiungere facilmente funzionalità wifi ai nostri progetti ad un prezzo molto contenuto, decisamente inferiore a quello delle costose shield ethernet per Arduino e con un ingombro decisamente irrisorio. Il costo di 3-4 euro, ma lo si può trovare anche a meno nella grande distribuzione, rende questo modulo ideale per dare connettività ai nostri progetti senza impazzire con improbabili cablaggi lan in giro per la casa. Sarà più semplice creare reti di sensori wifi che dialogano fra di loro sfruttando la rete che gran parte di noi avrà già in casa o creandone una ad ok proprio con questi moduli.

I moduli ESP-01

Ecco qui come si presentano questi piccoli moduli. Ne esistono di vari tipi, questi che vedete nella foto sono fra i più comuni (ESP-01). L’antenna è stampata sul pcb, ci sono alcuni componenti e un connettore che ci permette il cablaggio elettrico vero e proprio. La comunicazione con Arduino o eventualmente con altre schede avviete con una semplice interfaccia seriale. Ciò ci fa capire a priori che il tipo di comunicazione non potrà essere ad alta velocità, non aspettiamoci i 100MB/s, la velocità non è certo lo scopo di questo piccolo modulo anche se a dirla tutta è in grado di connettersi a 65Mbps e la UART permetterebbe di raggiungere i 4.5Mbps. Oltre all’interfaccia seriale (TX ed RX) ci sono i pin di alimentazione a 3.3V / max 300mA, un pin di reset (RST) e due pin accessori contrassegnati con GPIO 0 e 2. Per ultimo il pin CH_PD. Nei prossimi paragrafi vedremo come collegare l’ESP8266 ad un convertitore USB <–> TTL, ad Arduino DUE ed Arduino UNO, più nel dettaglio vedremo che ci sono non poche problematiche da affrontare e che vedremo come affrontare.

Colleghiamo il modulo.

Per quanto riguarda l’alimentazione fate molta attenzione perchè il modulo, che da ora in poi abbrevierò con ESP, è alimentato a 3.3V. Il relativo pin di Arduino deve perciò essere connesso al pin di alimentazione dell’ESP e al CH_PD. Ma qui il primo problema. Su Arduino DUE tutto tranquillo, ma su Arduino UNO ecco che riscontriamo delle difficoltà in quanto il regolatore di tensione a 3.3V di Arduino UNO non regge i 200mA che questo modulo può arrivare ad assorbire durante il normale funzionamento per cui i malfunzionamenti sono garantiti anche se sono in molti a giurare che sulla loro scheda funziona ugualmente.

Lo stesso problema lo abbiamo con gli altri pin, infatti il voltaggio massimo è di 3.6V per cui non possiamo connetterli direttamente ad Arduino UNO anche se pure in questo caso ci sono molti blog che affermano funzionare ugualmente. Io non voglio dire che chi afferma ciò dica bugie, può essere che utilizzino qualche clone con regolatore di tensione potenziato e che la seriale a 5V alla fine non danneggi il modulo sul breve termine, ma il datasheet parla chiaro e dichiara 3V e 3.6V come valori di tensione minima e massima tollerate. Esistono in commercio appositi convertitori di segnale (shift level) con multipli ingressi / uscite che vi permettono questo tipo di commutazione fra i due tipi di segnale 3.3V /5V, in alternativa potete usare dei partitori di tensione, soluzione non certo elegante, che aumenta i consumi di corrente e che può generare errori di comunicazione ad elevati baud-rate ma che tutto sommato per rapidi test può andare anche bene. Più nel dettaglio dovreste usare il partitore fra il tx di Arduino e l’rx dell’ESP in quanto l’uscita a 5V di Arduino è incompatibile con l’ingresso a 3.3V dell’ESP. Nell’altra linea (tx) non è necessario nulla in quanto l’uscita tx del modulo a 3.3V funziona senza problemi all’ingresso rx di Arduino in quanto sono sufficienti 3V per fornire un “segnale alto”.

Il collegamento del modulo in questione con Arduino DUE è piuttosto semplice. Ripetiamo solo per comodità che dobbiamo collegare il pin VCC e CH_PD alla 3.3V. L’ RX di Arduino si collega al TX del modulo e viceversa il TX di Arduino all’RX di Arduino. Semplice è anche il collegamento della massa (GND) di Arduino a quella del modulo.  Fatti questi ultimi  cablaggi siamo già pronti a fare i primi esperimenti. Vi faccio notare che la stessa identica cosa può essere fatta senza Arduino utilizzando un qualunque convertitore USB-TTL purchè ci sia la possibilità di usare la 3.3V e con sufficiente corrente su tale linea. In questo modo possiamo infatti utilizzare la porta USB del PC per effettuare una connessione WiFi attraverso l’ESP senza passare per Arduino.

Purtoppo quanto vi ho detto sinora non è del tutto vero, o quantomeno non in tutte le situazioni. Ad esempio ho fatto le prime prove con il convertitore USB-TTL in mio possesso ed il modulo ha risposto ai primi comandi, ma l’output risultava in parte corrotto ed il funzionamento molto instabile. Ne riparlo più avanti, ma quel che volevo dire è che non è detto che il convertitore in vostro possesso sia adeguato per questo tipo di lavoro. Visto questo fallimento, ho provato con Arduino DUE connettendo i pin come descritto sopra ma senza alcun risultato. Tenete anche conto che Arduino deve venir programmato con uno sketch vuoto come quello che vi riporto qui sotto per non interferire sulla porta seriale :

void setup() 
{ 
 // no setup
}
void loop()
{ 
 // no code
}
In questo modo Arduino non interferisce con la porta seriale, almeno da un punto di vista software perciò i dati che inviamo attraverso la porta USB vengono ricevuti direttamente dall’ESP e viceversa, ma nel mio caso non ha funzionato ugualmente. Il problema è legato al collegamento fra il TX dell’ESP ed Arduino come si può apprezzare nell’immagine qui a sotto. Si nota chiaramente come il “segnale rosso” non ha la giusta escursione da 0 a 3.3V il che impedisce la corretta interpretazione del messaggio.
A parte questo fallimento, sorgerebbe un secondo problema, infatti quando caricate uno sketch su Arduino, vi sarà un conflitto con l’ESP a causa della condivisione dei pin rx / tx per cui il caricamento non andrà a buon fine e ogni volta dovete scollegare i pin rx/tx o l’alimentazione del modulo per risolvere il problema. Una soluzione elegante è sfruttare il fatto che Arduino DUE possiede più di una porta seriale, possiamo infatti collegare il modulo alla porta 1 sui pin RX1 e TX1 (19 e 18), poi carichiamo uno sketch che copia i dati ricevuti dalla UART sulla porta seriale 1 e viceversa copia i dati del modulo prelevati dalla porta 1 sulla classica UART. Nel fare questo possiamo utilizzare anche due differenti velocità di comunicazione, lasciando il classico default di 9600 sulla UART e la velocità supportata dal modulo sull’altra. Ma quale velocità? Dipende dalla versione del firmware e dal quarzo presente sul vostro modulo, i più recenti comunicano a 115.200, ma ci sono versioni più vecchie che funzionano a 57.600 o 9.600 per questo motivo dobbiamo fare un paio di tentativi per verificare il corretto funzionamento. Lo sketch da utilizzare è molto semplice:
void setup()
{
 Serial.begin(9600); 
 Serial1.begin(115200);
 delay(1000);
}
void loop()
{
 if(Serial1.available())
 {
 byte b=Serial1.read();
 Serial.write(b); 
 }
 if(Serial.available())
 {
  byte c=Serial.read();
  Serial1.write(c); 
 }
}

Faccio solo notare per chi ha un po’ meno dimestichezza, che la UART è collegata alla “programming port” e non alla “native port” per cui il cavo USB deve essere collegato alla prima delle due, quella più vicina al connettore di alimentazione. Nel mio caso ho settato la porta 1 a 115.200 bps e la UART a 9600. Con questa configurazione mi è funzionato tutto al primo colpo ma ammetto che la stabilità del sistema non si è dimostrata fra le migliori, il modulo infatti alterna periodi di funzionamento impeccabile a periodi di riavvio continuo con impossibilità di utilizzo del modulo stesso. Chi segue assiduamente questo blog avrà già intuito il motivo ed il rimedio per questo bizzarro comportamento, ma dato che non tutti ci saranno già arrivati, meglio spendere due parole in più. Sappiamo infatti che ogni integrato in base alle varie fasi di funzionamento presenta dei picchi di assorbimento, la corrente consumata non è perciò costante. Inoltre lo stesso funzionamento dell’integrato può creare dei disturbi sulla linea di alimentazione che si associano a quelli degli altri componenti, disturbi elettromagnetici esterni, etc. Tutto ciò fa si che la linea di alimentazione sia disturbata e possa essere, per piccoli istanti, insufficiente ad erogare la corrente necessaria. Per tale motivo servono dei “serbatoi” che cercano di ridurre i disturbi e forniscono un “surplus di potenza” quando serve. Per chi volesse approfondire ho trovato questo articolo in italiano che spiega in maniera dettagliata il problema. Questi serbatoi a cui mi riferivo sono chiaramente i condensatori, nello specifico dobbiamo utilizzarne uno classico ceramico da 0.1μF, detto di disaccopiamento, da porre il più vicino possibile al modulo ESP. Certo che se state usando una breadboard siete costretti o a saldarlo sul modulo o a metterlo sulla breadboard ad una certa distanza visti i jumpers di collegamento, cosa che in parte ne vanifica l’efficacia. Il secondo condensatore, di tipio elettrolitico, andrà sulla linea di alimentazione e serve appunto da serbatoio per gli “spunti di potenza”, io ne ho usato uno da 470μF. Con questi due condensatori l’instabilità del sistema è magicamente svanita e tutto ha funzionato senza più blocchi e reset improvvisi del modulo. Nella foto a lato potete vedere il modulo collegato al convertitore USB-TTL con fonte di alimentazione esterna e condensatori montati sulla breadboard. Giusto per completezza segnalo che in rete ho trovato più di una fonte che segnala moduli difettosi che si resettano continuamente e che hanno beneficiato della sostituzione del chip, cosa che sinceramente non è alla mia portata viste le minuscole dimensioni.

Comandi AT

Cominciamo quindi ad inviare i primi comandi AT, si, proprio quelli che coloro che hanno qualche annetto in più ricorderanno sicuramente in quanto ampiamente utilizzati per configurare i vecchi modem. Attualmente il tutto è normalmente sostituito da interfacce grafiche sempre più sofisticate, ma non pensiate che i comandi AT siano scomparsi del tutto. Il fatto che vengano usati semplici comandi AT ci permette di capire perchè possiamo usare un semplice convertitore USB-TTL ed un software che permetta di inviare semplici codici ascii, sono infatti comandi che possiamo scrivere con la tastiera senza troppe difficoltà.

Dobbiamo quindi aprire il monitor seriale per cominciare la comunicazione con ESP, come dicevo normalmente questo è preconfigurato a 115.200bps, ma in realtà dipende dalla versione di firmware che è installata sul vostro modulo per cui nel caso non funzionasse provate anche i 57.600 ed i 9.600 finchè non trovate la vostra configurazione. Fate attenzione che il modulo prevede la presenza dei caratteri <CR> (CarriageReturn) e <LF> (LineFeed) che nel monitor seriale dell’IDE è identificato come “Entrambi (NL & CR)” (lo trovate vicino al baud rate).
Provate perciò con il più semplice dei comandi, ossia AT, in risposta dovreste ottenere OK. Se avete fretta di provare, a questo indirizzo potete trovare la lista completa dei comandi AT supportati o se preferite qualcosa di più esaustivo potete guardare a questo link. Fate molta attenzione però che il fatto che vengano interpretati i comandi AT dipende unicamente dal fatto che di default è precaricato sull’ESP un firmware deputato a questo compito, ma esistono vari altri tipi di firmware installabili che stravolgono completamente il funzionamento dello stesso, o meglio il modo di interfacciarsi con esso.
Bene, allora proviamo un bel AT+GMR, la risposta del modulo sarà la versione del firmware caricata sull’ESP stesso, cosa che ci è utile perché ci permette di sapere se è l’ultima o abbiamo bisogno di un aggiornamento. Vi dico già da subito che l’aggiornamento del firmware richiede qualche complicazione in più per cui sarà oggetto di eventuali futuri articoli. Nel mio caso il modulo ha risposto:
 AT version:0.40.0.0(Aug  8 2015 14:45:58)
 SDK version:1.3.0
 Ai-Thinker Technology Co.,Ltd.
 Build:1.3.0.2 Sep 11 2015 11:48:04
 OK
Bene se siamo arrivati a questo punto siamo pronti per cominciare a divertirci. Proviamo a digitare:
AT+CWMODE?
Nel mio caso l’ESP mi risponde:
+CWMODE:2
Questa è la modalità di funzionamento del modulo che può essere una delle seguenti:
 1 Modalità "Stazione" (Client)
 2 Modalità AP (Access Point)
 3 Modalità mista.
Nel nostro caso è attiva la modalità 2, ossia “AP” e se guardiamo l’immagine qui a lato si nota infatti che è stata cretata una rete wifi AI_THINKER_04C60A correttamente identificata dal mio telefono. Ora proviamo a settare il modulo con la terza modalità:
AT+CWMODE=3
A questo punto il modulo può funzionare anche da client per cui possiamo usarlo per ricercare gli access point visibili in zona, per farlo basta un
AT+CWLAP
Nel mio caso (differente da quello della figura a lato), l’output è stato:
 +CWLAP:(3,"HTC",-47,"80:01:84:7d:96:2c",1,-16) 
 +CWLAP:(3,"ZiaRoby",-87,"9c:d3:6d:fa:91:ad",6,-29)
 +CWLAP:(4,"ZiaRoby",-76,"a0:f3:c1:63:a1:3e",6,-27)
 +CWLAP:(4,"Wind MF65 B89DBC",-90,"78:e8:b6:b8:9d:bd",11,-44)
Il primo parametro indica il tipo di protezione della rete:
 0 OPEN
 1 WEP
 2 WPA_PSK
 3 WPA2_PSK
 4 WPA_WPA2_PSK
Il secondo è l’SSID della rete, il terzo il mac address, poi il canale e per finire la potenza del segnale. Faccio notare che nella documentazione ufficiale il canale non è riportato.
A questo punto possiamo connetterci ad una delle reti, nel caso specifico userò la prima che è un hotspot temporaneo creato con il mio telefono:
AT+CWJAP=”HTC”,”smania2000″
Dove il primo parametro è l’SSID della rete (attenzione che la documentazione ufficiale riporta invece “username”), il secondo la password. Nel mio caso l’ESP mi ha risposto con
WIFI CONNECTED
e dopo alcuni secondi ha aggiunto
WIFI GOT IP
Nel caso invece qualcosa non vada a buon fine, la risposta è un malinconico:
FAIL

Possiamo verificare lo stato della connessione con AT+CIFSR. Nel mio caso la risposta è stata:

+CIFSR:APIP,”192.168.4.1″
+CIFSR:APMAC,”62:01:94:04:c6:0a”
+CIFSR:STAIP,”192.168.1.31″
+CIFSR:STAMAC,”60:01:94:04:c6:0a”

dove le prime due righe riportano ip e mac address dell’access point mentre le ultime due riportano l’indirizzo ip e mac del modulo ESP.

Ora con AT+CIPMUX=1 istruite l’ESP affinchè utilizzi connessioni multiple. Se per qualche motivo volete effettuare connessioni singole, impostate AT+CIPMUX=0. Non ci resta che chiedere al nostro ESP di configurarsi come server con l’istruzione AT+CIPSERVER=1,80 dove l’80 è il numero della porta su cui mettersi in ascolto e 1 indica la creazione del server (con zero avremmo chiesto la sua cancellazione anche se sinceramente a me restituisce sempre un messaggio di errore).

A questo punto abbiamo un server WIFI pronto ad ascoltare i nostri messaggi e dobbiamo verificare se il tutto funziona. Il modo più semplice è aprire un browser ed inserire l’indirizzo ip del modulo nella barra dell’indirizzo. In questo modo il modulo dovrebbe ricevere la richiesta http del browser che verrà visualizzata nell’output seriale.
Ho usato sempre il cellulare e la risposta che ho ottenuto è stata:

0,CONNECT
1,CONNECT

+IPD,0,437:GET / HTTP/1.1
Host: 192.168.1.31
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Save-Data: on
User-Agent: Mozilla/5.0 (Linux; Android 6.0.1; HTC One M8s Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.91 Mobile Safari/537.36
Accept: axplgqtgee:==41,CLOSED

Questo è un tutorial base per cui il nostro interesse primario è rivolto a far funzionare il modulo e non certo rispondere a richieste http inviate dal browser per cui non dobbiamo preoccuparci della risposta che abbiamo ottenuto, l’importante è averla ricevuta. Se tutto è andato a buon fine chiudiamo la trasmissione con l’istruzione AT+CIPCLOSE=0.

Ora che abbiamo visto come usare l’ESP come server, vediamo come fare per usarlo come client. Per farlo al posto del comando CIPSERVER utilizziamo il comando CIPSTART. Per fare il test ho attivato un web server sul PC è ho dato il comando AT+CIPSTART=”TCP”,”192.168.1.164″,80

e la risposta è stata:

CONNECT
OK

Bene, ora siamo connessi come client ad un server remoto e siamo pronti ad inviargli dei dati. Per farlo si utilizza l’istruzione  AT+CIPSEND=length of data, dove lenght of data rappresenta il numero di bytes che stiamo per inviare (fino a 2k). Dopodichè non resta che inviare i dati veri e propri.

AT+CIPSEND=3
Il modulo risponde con un > che indica che è pronto a ricevere i dati da inviare. Provo a scrivere CIAO

Risposta:
Recv 4 bytes
busy s…
busy s…
SEND OK

Chiaramente la procedura vista sinora è assai noiosa e difficile da ricordare, ma dobbiamo pensare che queste operazioni le dovrà eventualmente eseguire Arduino al posto nostro. Per semplificarmi la vita ho scritto un software (attualmente solo per Windows) che funge da monitor seriale e che ha alcuni pulsanti preconfigurati (ma modificabili) con i comandi visti sinora. Non dovete fare altro che premere i pulsanti per inviare il contenuto al vostro modulo, c’è anche la possibilità di non inviare il contenuto direttamente ma di permetterne la modifica manuale prima dell’invio definitivo. I pulsanti come detto sono anche modificabili e può essere salvato il loro contenuto su un file esterno per richiamarlo poi in successive sessioni di lavoro se occorresse. Se vi interessa lo trovate a questo indirizzo, è gratuito, potete usarlo anche per altri scopi e non mi invia il numero della vostra carta di credito :-).

UART Monitor (1)

Abbiamo visto praticamente tutti i principali comandi. Ne ho tralasciato uno che però in fase di test può essere utile. C’è infatti la possibilità di effettuare un ping con il modulo cosa che ci fa capire se lo stesso è in grado di comunicare con il dispositivo remoto. La sintassi è molto semplice:

AT+PING=”192.168.1.164″

La risposta nel mio caso è stata:
+11

che sono i millisecondi del ping. Si noti che anzichè l’indirizzo IP può essere specificato il nome di un domino, ad esempio AT+PING=”www.mcmajna.com”.

Facciamolo fare a lui

Bene, anche con il mio software vi sarete stancati di tutti questi comandi complicati da ricordare. Proviamo ad automatizzare il tutto e facciamo fare il “lavoro sporco” ad Arduino. Userò per primo arduino DUE in quanto ha più porte seriali native, ma lo stesso discorso vale per qualunque Arduino con più di una porta seriale, come ad esempio Arduino Mega2560; parleremo invece successivamente delle schede che non dispongono di porte seriali multiple, come ad esempio il più classico Arduino UNO.

void setup()
{
 Serial.begin(9600); 
 Serial1.begin(115200);

 sendData("AT+RST\r\n",2000); // reset
 sendData("AT+CWMODE=2\r\n",1000); // configura come access point
 sendData("AT+CIFSR\r\n",1000); // ottengo indirizzo ip
 sendData("AT+CIPMUX=1\r\n",1000); // connessioni multiple
 sendData("AT+CIPSERVER=1,80\r\n",1000); // avvio server sulla porta 80
}

void loop()
{
//nel loop non faccio nulla
}

String sendData(String command, const int timeout)
{
  String response = "";
  Serial1.print(command); // invia il comando all' esp8266 usando la porta 1
  long int time = millis();
  while((time+timeout) > millis())
  {
    while(Serial1.available())
    {
      char k = Serial1.read(); // compongo la risposta con i caratteri ricevuti dall'ESP
      response+=k;
    }  
  }
  Serial.print(response);
  return response;
}

Rispetto a quanto detto sinora non c’è nulla di nuovo, semplicemente viene delegato il compito di inviare i vari comandi ad Arduino e ne vengono stampate le relative risposte attraverso il monitor seriale. La funzione che invia i vari comandi attende anche la risposta, la ricompone leggendo un carattere alla volta fino alla scadenza di un certo timeout e poi ritorna la risposta e la stampa attraverso la porta USB.

Una volta eseguito avviene il reset del modulo, e dopo tutte le informazioni di avvio che ci fornisce l’ESP, l’output sarà:

Ai-Thinker Technology Co.,Ltd.
 
 ready
 AT+CWMODE=2
 
 
 OK
 AT+CIFSR
 
 +CIFSR:APIP,"192.168.4.1"
 +CIFSR:APMAC,"62:01:94:04:bf:d9"
 
 OK
 AT+CIPMUX=1
 
 
 OK
 AT+CIPSERVER=1,80
 
 
 OK

E Arduino UNO?

E se non disponiamo della seconda porta seriale? Beh, anche se sinora qui sul blog non l’abbiamo mai usata, sicuramente siete al corrente che esiste una libreria che permette di trasformare altre coppie di pin in una nuova porta seriale. Ovviamente non essendoci uno specifico hardware di supporto sottostante non è propriamente identica  a quella nativa per cui ci sono delle limitazioni, fra queste il baud rate massimo raggiungibile (115200) e non tutti i pin possono essere usati, inoltre questi possono variare in base al tipo di Arduino. Non dobbiamo far altro che includere il file “SoftwareSerial.h”. Una volta fatto dobbiamo istanziare la nostra porta seriale, nell’esempio qui sotto l’ho chiamata SoftSerial ed ho assegnati i pin 8,9, rispettivamente Rx e Tx.

#include <SoftwareSerial.h>
SoftwareSerial SoftSerial(8, 9); // RX, TX

In questo modo abbiamo una nuova porta seriale sui pin 8 (RX) e 9 (TX) e non dobbiamo far altro che sostituire i precedenti riferimenti a Serial1 con SoftSerial. Riproviamo su Arduino DUE?. NO, non possiamo nenache volendo perchè questa libreria non è compatibile con Arduino DUE, non ha infatti molto senso usare una variante software della porta seriale quando ne abbiamo ben 4 hardware. E’ anche vero che ciò rende il nostro sketch incompatibile fra le diverse schede a meno che non si applichino delle compilazioni differenziali che tengono conto di queste differenze. Allora è proprio l’ora di passare ad Arduino UNO, oramai abbiamo tutti gli elementi necessari. Sappiamo che dobbiamo usare una porta software e che dobbiamo convertire i segnali a 5V in 3.3V. Ho fatto una prova con un partitore di tensione composto da un resistore da 1K ed uno da 2.2K. La tensione in uscita dal partitore è di 3.42 – 3.435V (misurata con l’oscilloscopio) per cui leggermente superiore ai 3.3V ma entro i 3.6V dichiarati come massimi dal datasheet. Il sistema sotto test aveva i condensatori che abbiamo visto prima e l’output che ho ottenuto è stato quello che vi riporto qui a lato. Come vedete l’output è in parte corrotto, MA ho usato l’uscita 3.3V di Arduino UNO che sappiamo non essere in grado di alimentare correttamente l’ESP per cui potrebbe essere quello il problema. C’è da dire  che l’ESP ha interpretato correttamente i comandi inviategli (vedi gli OK) ma l’output non risulta altrettanto valido. Allora ho riprovato l’alimentazione esterna per il modulo ed il risultano non è cambiato per cui non possiamo dare “la colpa” alla sola alimentazione. Prima che me lo chiediate, ho provato ad impostare anche la tensione esattamente a 3.3V tramite un potenziometro, sempre valutando il risultato con l’oscilloscopio, e non è cambiato nulla sia con alimentazione da parte di Arduino che con quella esterna. Sapete qual’è la cosa strana? Che il problema potrebbe celarsi nel partitore, ma quello lo abbiamo nella linea di comunicazione da Arduino verso l’ESP, ma questo dimostra di ricevere correttamente i comandi inviati. L’errore di interpretazione lo abbiamo in senso opposto dall’ESP verso Arduino dove usiamo direttamente la linea 3.3V dell’ESP e per la quale non dovrebbero sussistere problemi.

Come vedete le cose non sono così semplici come appaiono nella stragrande maggioranza dei tutorial che trovate in rete dove tutto è sempre stranamente perfetto e funzionante sin dal primo tentativo, dico la verità che spesso mi chiedo in quanti abbiano veramente sperimentato ciò che descrivono nei loro articoli. Ma visto che voglio credere nella buona fede delle persone, potrei pensare che i vari tutorial sono stati pensati in gran parte sulle vecchie versioni del modulo, funzionanti ad un baudrate inferiore. Lo specifico malfunzionamento di questi ultimi passaggi potrebbero essere legati alla SoftwareSerial nella fase di ricezione a 115200bps, velocità che è dichiarata essere quella limite. Se così fosse l’utilizzo di un differente firmware con diversa velocità di comunicazione potrebbe risolvere il problema, ma lo scopriremo nei prossimi articoli. Giusto per togliere ogni dubbio ho utilizzato anche un modulino shift level al posto del partitore, sia con alimentazione interna che esterna e benchè rispetto le prime volte ci sia qualche errore in meno, l’output resta comunque alterato cosa che mi fa credere in maniera piuttosto fondata che la causa principale dell’output corrotto sia proprio la mancanza di una porta seriale hardware adeguata.

Ho fatto qualche altra prova: ad esempio usando il software iniziale provato su Arduino DUE ma modificato per la porta seriale virtuale come qui sotto:

#include <SoftwareSerial.h>
SoftwareSerial SoftSerial(8, 9); // RX, TX

void setup()
 {
 Serial.begin(9600); 
 SoftSerial.begin(115200);
 delay(1000);
}

void loop()

 {
 if(SoftSerial.available())
  {
   byte b=SoftSerial.read();
   Serial.write(b); 
  }
 if(Serial.available())
 {
   byte c=Serial.read();
   SoftSerial.write(c); 
 }
}

In questo caso con alimentazione dal solo Arduino (visto che il mio tentativo è far funzionare Arduino UNO senza ulteriori linee di alimentazione), condensatori montati e shift level in sede, ma anche in questo caso pur riuscendo l’ESP a ricevere correttamente i comandi inviatigli, fornisce un output corrotto. Ad esempio il comando AT+GMR mi restituisce:

AT version;0.40.0.0(Aug  8 2015 14;45:58)
SDI vY®®ZËKŠršr‚j
Ai-Thinker c¨ËŠHÕérÁª¢‚
K

anzichè

 AT version:0.40.0.0(Aug  8 2015 14:45:58)
 SDK version:1.3.0
 Ai-Thinker Technology Co.,Ltd.
 Build:1.3.0.2 Sep 11 2015 11:48:04
 OK

Ora, ripensiamo a quanto abbiamo fatto inizialmente con il convertitore USB <-> TTL e chiediamoci: perchè non usare l’unica porta nativa sia per comunicare con il pc che con il modulo ESP. Si può fare? Proviamo, ma attenzione che i cavi vanno invertiti perchè le diciture TX ed RX sono riferite alla porta USB quinti con TX si intende “trasmissione verso la porta USB” e non “trasmissione verso il pin” per cui la linea TX dell’ESP si connette alla TX di Arduino e lo stesso dicasi per la porta RX. Così facendo i comandi non giungono correttamente all’ESP che mi risponde con ERROR in quasi tutte le situazioni. Ma esatto, mi risponde, e anche quando effettua il reset dopo un certo tempo di inattività mi restituisce un output impeccabile, privo di caratteri spuri. A questo punto credo però di aver bruciato il secondo modulino shift level, sembra che siano sin troppo delicati per cui mi sono detto: ora basta, lasciamo stare tutti gli inutili tutorial che troviamo in rete e facciamo a modo mio. Allora, agli inizi abbiamo detto che la porta TX dell’ESP può essere connessa direttamente ad Arduino mentre la porta RX non può ricevere in modo diretto i segnali da Arduino in quanto è necessario convertire il livello 5V di Arduino al 3.3V dell’ESP. Come ho fatto? Ora mi mostro il lavoro sulla porta RX dell’ESP usando un semplice bjt ed alcuni resistori.

Innanzitutto ricordo di programmare Arduino con uno sketch vuoto in modo da non interferire con la porta seriale, così possiamo agire direttamente dal monitor seriale per interfacciarci con il modulo. Lo schema di collegamento è estremamente semplice e lo trovate qui sotto:

Seguite lo schema assieme a me. A sinistra vediamo l’uscita 5V di Arduino (porta RX) che raggiunge la base del transistor attraverso un resistore da 4.7K. Quindi quando il segnale è alto il transistor viene messo in conduzione. Sarà quindi semplice intuire che al collettore (in alto) entrerà la tensione a 3.3V e che questa, quando il segnale alla base è “alto”, fluirà verso l’emettitore (in basso). Questo a sua volta si connette alla porta RX dell’ESP. In parallelo è collegato anche un resistore di 680Ω connesso a massa, questo perchè in sua assenza al passaggio del segnale da “alto a basso”, questo non scende abbastanza velocemente e non viene correttamente interpretato come zero con le disastrose conseguenze del caso. Bene, con questo semplicissimo stratagemma tutto funziona alla perfezione, senza necessità di usare porte software o shif registers. Nell’immagine qui sopra potete vedere il grafico prodotto dall’oscilloscopio. Non è molto dettagliato in quanto ho un oscilloscopio usb molto economico, ma si nota in maniera abbastanza chiara la corrispondenza temporale fra i due segnali  a 5 e 3.3V.

A questo punto sono riuscito ad utilizzare Arduino UNO senza fonti di alimentazioni 3.3V esterne, senza usare librerie software ne veri e propri shift-level, il tutto perfettamente funzionante.

Considerazioni

In questo articolo vi ho descritto la mia prima esperienza con questo modulo. Abbiamo testato il funzionamento base e visto come usare i principali  comandi AT. Anche se non ho ancora provato a sostituire il firmware di questi moduli nel momento in cui vi scrivo, sarà sicuramente il prossimo passo da fare. Perchè dico questo? Lo dico perchè le risposte fornite dal modulo sono stringhe troppo complesse per Arduino, andare ad analizzare delle stringhe di cui non conosciamo il contenuto a priori è troppo dispendioso per un controllore come l’ATMega328, è decisamente necessario provare qualcosa di più semplice. I comandi AT hanno il grosso vantaggio di essere gestibili da “esseri umani” per cui con un semplice monitor seriale siamo in grado di instaurare una comunicazione con un dispositivo remoto. Finchè si tratta di inviare dei comandi la cosa si rileva semplice anche per Arduino, ma quando dobbiamo riceverli o dobbiamo interpretare le risposte ricevute, le cose si fanno piuttosto complesse. Esistono diversi firmware pronti all’uso, ma sicuramente per chi utilizza già Arduino e qundi è famigliare con l’ambiente Wiring, sarà felice di sapere che è stato fatto il porting anche per questi moduli per cui è possibili utilizzarli come se fossero un “Arduino secondario”, anche se per certi versi direi primario vista la netta superiorità in termini di potenza e memoria rispetto ad Arduino UNO. Ma vedremo nel prossimo articolo come fare. Altre considerazioni? Si! E’ piccolo, guardatelo nella foto qui vicino rispetto ad una monetina da 20 centesimi, fattore decisamente molto importante nelle applicazioni in cui dobbiamo dare connettività wifi in poco spazio. L’ultima considerazione riguarda invece la stabilità: qui la bontà dell’alimentazione è fondamentale per avere un sistema stabile per cui non scordatelo….MAI.

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva

Salva