Archivi tag: esp8266

Esp8266 ed http, che fatica!

Operazioni di restauro della stazione meteo, allagata e poi ripristinata con un nuovo circuito stampato, qualche sensore nuovo, connettori stagni e fori di sfogo dell’umido. Una persona ragionevole pensa “il più è fatto” e “basta rimettere il software vecchio e tutto funzionerà come prima”. Nemmeno per sogno. Il software vecchio funziona, ma non carica i dati sul server.

Il caricamento dei dati sul server avviene attraverso un banalissimo script PHP che viene invocato da un GET HTTP, con tutta una serie di parametri, una cosa di questo tipo:
http://192.168.x.y/meteo/add.php?temperatura=19.48&umidita=77.29&pressione=995.74&dewpoint=15.40&direzione=234.45&velocita=7.22&pioggia=0&sensore=tetto

Sul server la cosa funziona così:
192.168.x.r – – [20/May/2018:19:38:36 +0200] “GET /meteo/add.php?temperatura=22.68&umidita=52.19&pressione=99696.80&dewpoint=12.38&direzione=234.45&velocita=1.03&pioggia=0&sensore=tetto HTTP/1.1” 400 0 “-” “-“

Tutto finisce con un “400, bad request”. Se la chiamata viene inviata da un browser (copia ed incolla della STESSA stringa), tutto funziona:
192.168.x.k – – [20/May/2018:19:38:43 +0200] “GET /meteo/add.php?temperatura=23.22&umidita=50.15&pressione=99699.11&dewpoint=12.27&direzione=165.76&velocita=6.91&pioggia=0&sensore=tetto HTTP/1.1” 200 453 “-” “Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36”

Ho cercato informazioni in rete ed ho visto che il protocollo HTTP, con il metodo GET, richiede che siano passati una serie di parametri al server:
GET
Host
User-Agent
Connection

Ottime informazioni si trovano su questo link. In pratica RFC che descrive il protocollo. Una prima versione del mio firmware inviava una stringa senza “user-agent”. Aggiunto questo parametro l’errore è rimasto. Il debug del problema lo ho effettuato con tcpdump sotto linux, impostando l’opzione “-vvv”, che analizza completamente il protocollo. Analizzando bene il traffico, ho notato che il campo host era valorizzato in modo errato. Come si evince dal RFC, la mancata valorizzazione del campo comporta un “bad request” da parte del serve. Ho modificato il codice impostando il campo “host” a “localhost” e tutto ha iniziato a funzionare. Vabbè, ho perso 3 giorni di tempo, sono stato due ore sul tetto ma ho imparato un sacco di cose! Di seguito l’analisi del protocollo fatta con tcpdump.

GET /meteo/add.php?temperatura=19.54&umidita=72.92&pressione=99537.58&dewpoint=14.55&direzione=94.69&velocita=0.00&pioggia=0&sensore=tetto HTTP/1.1
Host: localhost
User-Agent: wget/1.12
Connection: close

Questo invece il codice in ESP8266:

void http_client(){
Serial.println(“HTTP CLIENT: ———————————————————————–“);
Serial.print(“Host: “);
Serial.println(host);
Serial.print(“Port: “);
Serial.println(httpPort);
if (!WFclient.connect(host, httpPort)) {
Serial.println(“connection failed”);
++wrong;
error_flag=1;
return;
}
String agent = “wget/1.12”;
String hosth = “localhost”;
delay(100);
String url = “/meteo/add.php?”;
url += “temperatura=”;
url += temp;
url += “&umidita=”;
url += humi;
url += “&pressione=”;
url += pres;
url += “&dewpoint=”;
url += dewp;
url += “&direzione=”;
url += wdirection;
url += “&velocita=”;
url += wspeed;
url += “&pioggia=”;
url += pioggias;
url += “&sensore=”;
url += sensore;

Serial.print(“Requesting URL: “);
Serial.println(url);

WFclient.print(String(“GET “) + url + ” HTTP/1.1\r\n” + “Host: ” + hosth + “\r\n” + “User-Agent: ” + agent + “\r\n” + “Connection: close\r\n\r\n”);

unsigned long timeout = millis();
while (WFclient.available() == 0) {
if (millis() – timeout > 10000) {
Serial.println(“>>> Client Timeout !”);
WFclient.stop();
return;
}
}

E per adesso… funziona.

Esp8266 – No WiFi Connection

Dopo l’allagamento della mia stazione meteo, ho deciso di riprogettare tutto il sistema. Ho quindi realizzato un circuito stampato in modo da abbandonare per sempre la realizzazione filata su mille-fori. Il PCB lo ho disegnato con Eagle e realizzato presso Millennium Dataware, come sempre. Ho dovuto correggere qualche piccolo errore derivante dalla poca attenzione e massima fretta nello sbroglio delle piste, ma tutto ha funzionato bene. Almeno dal punto di vista elettrico.

Nel momento in cui sono andato a ricaricare il firmware sulla scheda mi aspettavo un funzionamento “alla prima botta”. Invece il dispositivo si è bloccato nella fase di connessione all’access point, restituendo codice di errore “6” da WiFi.Status(). In pratica: nessuna connessione. Malgrado questo io sul’AP ero in grado di vedere il modulo come “autorizzato” o connesso. Per sbrigliare meglio questa matassa ho deciso di utilizzare un AP realizzato con una RouterBoard Mikrotik, in modo da potere approfittare delle funzionalità di logging.

Il codice che gestisce la connessione verso l’AP è il seguente:

Serial.println("");
Serial.println("WIFI INIT");
Serial.println("");
WiFi.macAddress(MAC_array);
for (int i = 0; i < sizeof(MAC_array); ++i){
sprintf(MAC_char,"%s%02x:",MAC_char,MAC_array[i]);
}
Serial.print("Unit Mac Address is: ");
Serial.println(MAC_char);
Serial.println("");
Serial.print("Connecting to ");

Serial.println(ssid);

// IP,DNS,GATEWAY,SUBNET
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password); //Gestione della connessione ad un AP
WiFi.softAP(ssidSA, passwordSA, 1, 1); //Gestione del SoftAP e hidden SSID
WiFi.setOutputPower(0); // Impostazione della potenza di uscita

while (WiFi.status() != WL_CONNECTED) {
Serial.println(WiFi.status());
delay(1000);
Serial.print(".");
}

Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());

Cercando una possibile soluzione in rete mi sono imbattuto in questo post, in cui si legge:

WL_CONNECTED is only returned if the wifi interface has connected an has IP address
in DHCP mode this means you got the IP form the DHCP server. in Static mode you have set the IP yourself.

Detto fatto: ho configurato la mia MikroTik per lavorare come dhcp server e per effettuare il NAT della rete WiFi verso la rete di casa e… funziona!

Nota bene, in caso l’assegnazione dell’IP sia statica, il codice deve essere modificato in questo modo:

IPAddress host(192,168,**,**); //used for socket,mysql,mqtt 
IPAddress ip_wifi(192,168,**,**);
IPAddress dns_wifi(192,168,**,**);
IPAddress gw_wifi(192,168,**,**);
IPAddress subnet_wifi(255,255,**,**);

void setup() {
  Serial.println("");
  Serial.println("WIFI INIT");
  Serial.println("");
  //WiFi Management
  Serial.print("Connecting to ");
  Serial.println(ssid);
   
   WiFi.mode(WIFI_STA);
   WiFi.config(ip_wifi,dns_wifi,gw_wifi,subnet_wifi);  
   WiFi.begin(ssid, password);     
   WiFi.softAP(ssidSA, passwordSA, 1, 1); 
   WiFi.setOutputPower(0);        
   
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }

 

Un altro progettone!

Non sono un appassionato di meteorologia, sono semplicemente un “meteocurioso”. Mi piace conoscere la misura dei principali parametri meteorologici e poterne studiare la loro evoluzione nel tempo. Tanti anni fa avevo un quaderno in cui annotavo temperatura massima e minima del giorno. A dire il vero lo faceva mamma… io mi scordavo 2 volte su 3.

Ai tempi della tesi di dottorato avevo rispolverato un paio di componenti molto interessanti per la misura della temperatura ed umidità e pressione ed umidità. Si tratta di SHT21 della Sensirion e del MPL115A della NXP. Due prodotti molto interessanti, piccoli e facili da leggere, soprattutto con una raspberrypi. All’epoca avevo anche realizzato un mini-sito nella raspberry per potere analizzare l’andamento dei parametri meteo e poterlo confrontare con la variazione delle grandezze elettriche che erano oggetto del mio studio.

A distanza di alcuni anni, ho notato in commercio due oggetti che hanno riacceso il “fuoco sacro” della sperimentazione:

  • ESP8266, un chip Wi-Fi a basso costo con un microcontrollore Arduino-compatibile integrato;
  • BME 280, un sensore Bosch capace di rilevare temperatura, umidità e pressione.

Ho deciso quindi di realizzare una stazione meteo, che non pretende di entrare in competizione con prodotti commerciali ma che può soddisfare la mia curiosità meteorologica. Il progetto prevede l’integrazione di numerosi sensori e componenti aggiuntivi:

  • schermo solare, realizzato con i sottovasi ed il tornio;
  • sensore di temperatura umidità e pressione;
  • sensore di direzione del vento;
  • sensore di velocità del vento;
  • sensore di presenza pioggia.

 

I dispositivi sono stati acquistati tutti su Aliexpress, attendendo i canonici 30,40,50 giorni per la consegna. Particolarmente positivo è stato il giudizio nei confronti dei sensori di direzione e velocità del vento: ben costruiti, con ottimi cuscinetti e connessioni stagne. Considerato il prezzo di acquisto il prodotto è davvero interessante.

ESP8266 si occupa di raccogliere tutti i dati, impacchettarli e consegnarli via metodo http post al server per il loro immagazzinamento nel database. Il database è MySQL in esecuzione sulla solita Cubieboard. I dati sono presentati attraverso una interfaccia web “triviale” ed è possibile anche tracciare dei grafici relativi all’andamento delle grandezze nell’arco di 24,48 ore o una settimana. Nello screenshot seguente si vede la tabella riepilogativa dei sensori presenti in cui sono riportate le principali grandezze misurate. Il sensore pioggia è in errore a causa di un malfunzionamento.

Questa immagine mostra i dettagli del sensore. Una tabella riepiloga massimi, minimi e valori medi delle grandezze misurate.

I grafici mostrano l’andamento nel tempo delle grandezze, sono realizzati con la libreria JpGraph.

I problemi da risolvere sono stati tantissimi, molti dovuti alla mia proverbiale incapacità di programmatore. Malgrado le difficoltà, il sistema è attualmente in produzione e funziona in maniera piuttosto stabile. Ho notato una certa imprecisione del sensore di pioggia, che mi era stata segnalata anche da un collega. Non mi sorprende, considerando il prezzo di acquisto del dispositivo. La maggiore difficoltà la ho avuta nel gestire lo stato della connessione di ESP8266: nella prima stesura del codice effettuavo un controllo di connessione solo in fase di “setup” del dispositivo. Con questo approccio errato, in caso di caduta della connessione Wi-Fi, le funzioni che cercano di scrivere su un socket rallentano o bloccano l’esecuzione del codice. L’inserimento di controlli sullo stato della connessione ed eventuale riconnessione, ha reso il funzionamento del sistema molto più stabile.

Ho sviluppato il sistema con l’IDE di Arduino. Non amo particolarmente questo sistema ma lo ritengo comodissimo per questo tipo di applicazioni ludico-ricreative. Sviluppare il progetto con il PIC sarebbe stato un pianto (per me…) integrare una chip Wi-Fi con stack tcp/ip sarebbe stato oneroso e, forse, inutile. Ben vengano queste agevolazioni quindi, soprattutto se sono ben consolidate ed affidabili.

Il codice è a disposizione su richiesta, appena avrò tempo di epurarlo dai dati personali sarà pubblicato sul sito nella sezione download.