Objetivos
Material requerido.
Alternativamente puedes usar un Nodemcu V2 o un ESP32
Mas sobre WIFI y ESP8266
En las dos últimas sesiones hemos estado jugando con el módulo WIFI ESP8266. Le he encontrado muy simpático y capaz, especialmente dado su bajo precio.
Le hemos probado primero alimentado directamente desde el Arduino, lo que no es muy aconsejable dado que, especialmente en el arranque, puede demandar más intensidad de la que el pin de 3V puede proporcionar. Aunque al final se consigue que arranque, no suele ser sin varios intentos lo que resulta molesto y poco fiable.
En la siguiente sesión usamos una fuente de alimentación de protoboard para garantizar la alimentación correcta del módulo, lo que nos llevó a un arranque falible al 100% (Menos mal).
Pero aun así, seguíamos usando las señales de transmisión de Arduino a 5V sin adaptar a los 3,3 V que el fabricante recomienda. La experiencia es que resulta fiable y funciona bastante bien, con una molesta tendencia a colgarse con ciertos comandos, especialmente cuando se los volcábamos por programa.
Así que la solución definitiva pasaba por probar con todas las señales a 3.3V y la alimentación correcta del módulo (No veo otra solución que le vamos a hacer), y como por otro lado llevaba ya un tiempo queriendo probar mi flamante Arduino DUE y no encontraba excusa, mira por donde voy a matar dos pájaros de un tiro.
Como el DUE funciona nativo a 3.3V, nos viene de perlas porque, además, dispone de 3 puertas hardware de comunicaciones que pueden funcionar a 115200 baudios y así podemos probar el modulo con una velocidad de verdad.
Pues eso, que vamos a ver qué pasa, aquí tenéis el diagrama de conexión al DUE.
El programa de control
La idea es volcar por programa los comandos necesarios al DUE para programarlo desde el arranque. Ya en la sesión previa vimos la parte interesante de este programa y no creo que sea necesario insistir más en ello. Aquí tenemos el programa Prog_76_1
Hemos convertido el programa de volcado de comandos en una función, que incluye un array con las órdenes a enviar:
void SetUpWIFI() { String ordenes[]= { //"AT+RST", "AT+CWMODE=3", //"AT+CWQAP", //"AT"AT+CWLAP", "AT+CWJAP=\"charly\",\"contrase\"", "AT+CIFSR" , "AT+CIPMUX=1", "AT+CIPSERVER=1,80", "END" // Para reconocer el fin de los comandos AT }; int index = 0; while(ordenes[index] != "END") { Serial3.println(ordenes[index++]); while ( true) { String s = GetLineWIFI(); if ( s!= "") Serial.println(s); if ( s.startsWith("no change")) break; if ( s.startsWith("OK")) break; if ( s.startsWith("ready")) break; } Serial.println("...................."); } }
El Arduino DUE dispone de tres puertas hardware de comunicaciones que soportan sin problemas los 115.200 baudios y para ello no necesitamos ninguna librería. Por eso las inicializamos directamente, con Serial y Serial3:
void setup() { Serial.begin(19200); Serial3.begin(19200); delay(1500); // Para darnos tiempo a abrir la consola SetUpWIFI() ; // Envia los comandos AT }
Inicialmente las programamos a 19.200, que es la velocidad a la que está actualmente el módulo WIFI (y si ponemos aquí los 115200 baudios, va a ser difícil comunicar con el)
Creo que el resto del programa no tendrá ninguna dificultad para vosotros (Si estáis leyendo esto seguro que ya sois usuarios avanzados).
Ahora podemos volcar este programa Prog_76_1 y una finalizada, abrimos la consola Arduino para reprogramar la velocidad. Comprobad que os escucha y enviar la orden.
AT+CIOBAUD=? At+CIOBAUD? AT+CIOBAUD=115200
Si todo va bien perderemos la comunicación con el modulo, porque adaptará su velocidad a 115200 y nosotros debemos reprogramar el Arduino de modo acorde, igual que la velocidad de la consola.
Cambiad en el programa
Serial.begin(19200); Serial3.begin(19200);
Por esto otro
Serial.begin(115200); Serial3.begin(115200);
Y volcad el nuevo programa a Arduino. Cuando finalice, cambiad a 115.200 baudios la velocidad de la consola y ya está. Ejecutad de nuevo el programa para ver el resultado.
El resumen es que mejoran bastante los problemas de comunicación, pero sigo recibiendo bastantes interferencias en forma de basura en la puerta serie y además aunque mejora, no se elimina del todo la tendencia a colgarse con los comandos CWLAP y CWJAP,al volcarlos por programa, pero la verdad es que el DUE va como una seda.
No necesitamos cargar librerías, tenemos 3 puertas hardware de comunicaciones, un procesador de verdad a 32 bits y cantidad de memoria para nuestros programas. Casi me da pena volver al venerable Arduino UNO para los tutoriales.
Un servidor Web con el WIFI ESP8266
Vamos con el plato fuerte de la sesión. Voy a usar un Arduino DUE para este ejemplo pero sería de lo más sencillo convertirlo a un UNO. Bastaría con usar la librería SotwareSerial que usamos en las dos sesiones previas referentes al WIFI ESP8266. En un Mega, debería correr sin modificar, ya que es pin a pin compatible con el DUE.
Vamos a montar un pequeño ejemplo en el que nuestro Arduino DUE o Mega, presenten una página Web con las lecturas de las puertas analógicas.
Usaremos para ello el mismo montaje que en el ejemplo anterior y que repetimos aquí por comodidad de los más vagos (Entre los que me cuento sin rubor).
El programa de servidor WEB con WIFI ESP8266
Os dejo aquí el programa completo Prog_76_2 y pasamos a describir las partes más oscuras.
En primer lugar y como vimos en la sesión anterior, definimos un array de comandos para programar el modulo:
String ordenes[]= { //“AT+CWJAP=”redwifi”,”Contraseña” // A mi esto me da problemas "AT+CWMODE=3", "AT+CIFSR" , "AT+CIPMUX=1", "AT+CIPSERVER=1,80", "END" // Para reconocer el fin de los comandos AT };
En el setup programamos las puertas Serie y Serie3 a 115.200 baudios y después volcamos los comandos de la matriz, con un programa similar al anterior pero desde el setup.
void setup() { Serial3.begin(115200); Serial.begin(115200); delay (1000); // Para tener tiempo de arrancar la consola int index = 0; while(ordenes[index] != "END") { Serial3.println(ordenes[index++]); while ( true) { String s = GetLineWIFI(); if ( s!= "") Serial.println(s); if ( s.startsWith("no change")) break; if ( s.startsWith("OK")) break; if ( s.startsWith("ready")) break; } Serial.println("...................."); } }
Usaremos una versión modificada de GetLine() para leer el Serial3, llamada GetLineWIFI ()y que simplemente lee de esta puerta para recibir líneas completas.
Para poder enviar las líneas HTTP que conforman la página de presentación de datos, vamos a necesitar enviar varias líneas de texto, que como ya vimos antes deben hacerse con AT+CIPSEND que espera que le demos la longitud del texto, por lo que va a ser necesaria una función:
void http(String output) { Serial3.print("AT+CIPSEND=0,"); // AT+CIPSEND=0, num Serial3.println(output.length()); if (Serial3.find(">")) // Si recibimos la peticion del mensaje { Serial.println(output); Serial3.println(output); //Aqui va el string delay(10); while( Serial3.available() > 0) // Busca el OK en la respuesta { if ( Serial3.find("SEND OK") ) break; } } }
Como veréis, esta función http(), recibe un String y calcula su longitud para después mandar un comando CIPSEND con ella. Después busca recibir un carácter ‘>’ que nos devuelve el modulo para indicar que espera la recepción del String.
Si lo encuentra, le envía el String recibido a la puerta serie y al serial3 hacia el WIFI. Cuando termina busca el “SEND OK” y termina al recibirlo.
Para enviar la página web, hemos montado una pequeña función con los textos necesarios:
void webserver(void) { http("<!DOCTYPE HTML>"); http("<html>"); http("<head><title>LECTURAS ANALOGICAS.</title>"); http("<meta http-equiv=\"refresh\" content=\"15\"></head>"); // Refresco http("<body><h1> Situacion Ambiente</h1>"); for (int analogChannel = 0; analogChannel < 6; analogChannel++) { int sensorReading = analogRead(analogChannel); http(" analog input "); http( String(analogChannel)); http(" is "); http(String(sensorReading)); http("<br />"); } http("<p><em> La pagina se actualiza cada 15 segundos.</em></p></body></html>"); delay(1); Serial3.println("AT+CIPCLOSE=0"); }
Envía en primer lugar un típico encabezado HTML, con una instrucción para que se refresque cada 15 segundos y luego envía los textos que corresponden a las lecturas de las puertas analógicas con un bucle for.
Las últimas líneas son para cerrar la sesión IP con el navegador y dejarlo libre al servidor para una nueva conexión.
Y por último, el loop busca conexiones a través de la puerta WIFI (Serial3) y cuando las encuentra, invoca webserver().
Aquí os dejo un mini vídeo con el resultado:
Resumen de la sesión