bclose

Usando el módulo WIFI ESP8266

Comunicación con PC mediante WIFI ESP8266

Objetivos

 

 
    • Usar el módulo WIFI ESP8266 para gobernar unos LEDs conectados a pines de Arduino.
    • Escribir un pequeño programa que vuelque comandos de configuración AT al módulo.
    • Probar la comunicación unidireccional con una página web.
    • Probar la comunicación bidireccional con un programa terminal como Putty.
 

Material requerido.

 

Mas sobre WIFI y ESP8266

 

En la última sesión vimos como conectar el módulo WIFI ESP8266 a nuestros Arduinos para conseguir una conexión WIFI barata y de pequeño tamaño, y además estuvimos familiarizándonos con los comandos AT más habituales para manejar el modulo.

En esta sesión, vamos a construir a partir de esos comandos algunos circuitos de prueba similares a los que hicimos con el shield Ethernet, para que veáis que es de lo más sencillo adaptar aquellos programas a este módulo WIFI.

Y el primer, y más sencillo programa a probar es el de manejar unos LEDs desde un navegador Web desde un PC o desde un móvil.

Vamos a utilizar un montaje similar al de la última sesión, para activar el servidor Web y pasarle parámetros mediante un navegador, de modo que nuestro programa busque la cadena “P13”, y si la encuentra invierta el valor del LED conectado al pin13 de Arduino.

Vamos a usar una fuente de alimentación externa de 3,3V para protoboard.


Esquema de protoboard

 

 
  • Por favor que no se os ocurra olvidaros de conectar la masa común entre la protoboard ( O el regulador que uséis) y la masa GND de Arduino. Ignorar esto puede ser muy perjudicial para la buena salud de vuestra electrónica.
  • Recordad que unir las masas, es lo único que nos garantiza un nivel cero de referencia, común. Si lo omitís, las diferencias de tensión entre el alimentador de vuestro Arduino y el de la protoboard, pueden ser más que suficientes para daros una sorpresa y chamuscar algo.
 

 

El programa de control

 

Ya estamos familiarizados con todos los conceptos que vamos a usar, así que empezaremos directamente. En primer lugar  nos interesa crear un sistema que nos permita reprogramar el módulo WIFI en los arranques.

Vamos a empezar creando un array con los comandos precisos:

String ordenes[]=
  {  "AT+CWMODE=3",
     "AT+CWQAP",
     "AT+CWJAP=\"charly\",\"contrase\"",
     "AT+CIFSR" ,
     "AT+CIPMUX=1",
     "AT+CIPSERVER=1,80",
     "END"                 // Para reconocer el fin de los comandos AT
  };

La idea es recorrer este array al reiniciar y enviar los diferentes comandos AT al módulo WIFI.

 
  • Fijaros que para poder enviar un comando String que contenga el carácter “, tenemos que precederlo por la barra ‘\’.
 
Y para poder enviar las órdenes de mando, podemos usar en el setup, el siguiente código:

     int index = 0;
     while(ordenes[index] != "END")
        {  WIFI1.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;
                  // if (millis()-T >10000) break; 
              }
          Serial.println("....................");
      }

Recorremos con index el array órdenes [] hasta que encontremos “END” y las enviamos al módulo con la línea:

{  WIFI1.println(ordenes[index++]);

Luego entramos en un while que lo único que hace es leer líneas completas de la respuesta del módulo y las imprime, hasta que recibe una de las claves de salida.

 
  • La mayor parte de los comandos AT, provocan una o más líneas de respuesta, que acaban con un sencillo OK, y por eso es una de las condiciones de salida.
  • Pero también hay ordenes AT, que devuelven “no change”o “ready”.
  • Si recibe FAIL, es que no ha sido capaz de programar correctamente el modulo y por tanto terminamos la ejecución del programa.
 

El problema es que con el montaje que hemos hecho, mis dos módulos parecen tener mucha tendencia a colgarse cuando les envío desde programa algunos comandos como AT+CWJAP y AT+CWLAP.

 
  • Esto es probablemente debido a que aunque el modulo parece soportar bien que RX y TX vayan a 5 Voltios pudiera, a pesar de todo, convenir usar un convertidor de nivel de tensión.
  • Arduino solo puede suministrar 50 mA en el pin de 3.3V y este módulo puede necesitar hasta 300 mA según el fabricante, por eso vamos a utilizar una fuente de alimentación externa. Alimentándolo con Arduino consigues que arranque una de cada 5 veces, pero siempre es preferible evitar el olor a quemado que es molesto.
  • Personalmente he experimentado bastantes problemas a la hora de arrancar el modulo, sin alimentación externa, y aunque al final se consigue a base de quitar y poner tensión repetidamente hasta que arranca. Una vez arrancado, en general va bastante bien pero al principio cuesta.
 

Así, que en lugar de volcar los comandos por programa, vamos a hacerlo manualmente, porque además el modulo tiene la buena costumbre de recordar la última conexión que hizo y restáurala al re arrancar, por lo que nos podemos ahorrar el reprogramar la conexión al WIFI.

El modulo recuerda también el modo de funcionamiento con AT+CWMODE=3, pero olvida  tranquilamente los comandos necesarios para montar el servidor web AT+CIPMUX=1″ y “AT+CIPSERVER=1,80”, así que esto sí que son necesarios enviar.

Para no complicar el programa de ejemplo, os recomiendo de momento conectar a mano al punto de acceso WIFI que tengáis, y programar a mano estos dos últimos comandos AT.

Cuando empecé con este programa quería que combinase tanto la capacidad de interpretar los comandos AT que enviamos, como la capacidad de recibir las respuestas del módulo, sin que ello suponga impedimento para poder revisar los mensajes entrantes para tomar las decisiones de gobernar señales en Arduino.

La forma que he encontrado ha sido algo como esto: Prog_75_1

#include <SoftwareSerial.h>
SoftwareSerial BT1(3, 2); // RX | TX
String W =" ";
char w ;

void setup()
   {  Serial.begin(19200);
      BT1.begin(19200);
      pinMode(13, OUTPUT);
   }

void loop()
   {  if (BT1.available())                // Lo que entra por WIFI à Serial
         { w = BT1.read() ;
           Serial.print(w);
           W = W + w ;                    // Vamos montando un String con lo que entra
         }
      if (Serial.available())             // Lo que entra por Serial à WIFI
         {  char s = Serial.read();
            BT1.print(s);
         }
      if ( w == '\n')                     // Sin han pulsado intro
         { if ( W.indexOf("P13") > 0 )    // Comprobamos si P13 esta incluido en el string
               { digitalWrite( 13, !digitalRead(13)) ;
                 Serial.println("Invirtiendo pin 13");
               }
           W = "" ;  w = ' ' ;                    // Limpiamos las variables
         }
  }

Este programa nos permite seguir enviando y recibiendo comandos AT manuales y ver la respuestas de vuelta, y además revisa la entrada buscando cadenas de texto completas que identifique una acción a realizar.

Si queremos manejar más de una señal, en digamos el pin 12, bastaría con añadir:

if ( W.indexOf("P12") > 0 )    // Comprobamos si P12 esta incluido en el string
    { digitalWrite( 12, !digitalRead(12)) ;
      Serial.println("Invirtiendo pin 12");
    }

Por ultimo os voy a poner un minivideo con el resultado, pero antes he enviado a mi modulo los siguientes comandos AT manualmente:

At+RST
AT+CWMODE=3
AT+CWJAP=”CHARLY”,”CONTRASE”      // Conectar al punto de acceso
AT+CIFSR                          // Para saber mi IP
AT+CIPMUX=1                       // Permitir multiples conexiones
AT+CIPSERVER=1,80                 // Arrancar el servidor web en el puerto 80

Aquí tenéis un minivideo con el resultado:

 

 

Enviando y recibiendo ordenes mediante WIFI

 

En el ejemplo anterior recibíamos órdenes desde un navegador pero no devolvíamos información al navegador. En esta sesión haremos un ejemplo de conexión desde un terminal como Putty y veremos la forma de enviar textos en ambas direcciones.

Aunque nosotros usaremos un terminal de PC para ilustrar el ejemplo, podríamos hacer exactamente lo mismo desde una tableta o móvil con un terminal que acepte conexiones TCPIP.

Asegúrate de volcar el programa Prog_75_1 a nuestro Arduino y abre la consola. Necesitamos dar algunos comandos manuales:

AT+CIFSR
AT+CIPMUX=1
AT+CIPSERVER=1,80
Inicalizacion

Asegúrate de poner la dirección IP de tu modulo y pulsa open. Veras que Arduino recibe un mensaje de Link:

Parametros basicos

Asegúrate de poner la dirección IP de tu modulo y pulsa open. Veras que Arduino recibe un mensaje de Link.

Estableciendo la conexion

Lo que escribas ahora en la consola del Putty pasara a la consola serie de Arduino

comunicando con Arduino
Cominicacion con Putty

Son mensajes que podemos reconocer con nuestro programa de recepción y se pueden usar para activar acciones en Arduino como ya hemos visto.

Para enviar mensajes desde Arduino a la consola de Putty debemos usar el comando:

AT+CIPSTART=0,"TCP","192.168.1.50",80

Que le indica a nuestro módulo WIFI que inicie una sesión TCPIP por el puerto 80 con la IP especificada que corresponde a mi Putty, vosotros deberéis poner la dirección de vuestro PC o tableta.

Nos devolverá el mensaje “Already connected” ( Ya conectado), indicando que la conexión ya está establecida.

putty_2

La conexión se inició automáticamente, cuando Putty se conectó al servidor y por eso nos podríamos haber ahorrado este comando, pero si somos nosotros quienes iniciamos la conexión debemos darlo irrevocablemente.

Y ahora para enviar mensajes a la consola de Putty usaremos

At+CIPSEND=0, N

Donde 0 es la sesión abierta en automático y N es la longitud del mensaje a enviar, y después podemos enviar el mensaje:

AT+CIPSTART

Y como la longitud del mensaje es de más de los 24 caracteres especificados, simplemente corta al llegar a los 24:

recepcion de mensajesAquí os dejo un pequeño video con la interacción que siempre es mas fácil de ver.

En la próxima sesión veremos cómo presentar una página web usando estos comandos AT.

 

 

Resumen de la sesión

 

 
    • Vimos cómo usar el módulo WIFI ESP8266 para modificar el estado de un LED en nuestro Arduino desde un navegador Web.
    • Seguimos probando comandos AT para el WIFI ESP8266
    • Vimos como conectar al servidor web a través de WIFI con un terminal serie y usarlo para establecer la comunicación bidireccional.

 

 

 

 

 

(192) Comments

  • hola admin
    { if ( W.indexOf(“P13”) > 0 ) en esta linea si quisiera poner el # 13 en una variable como podria hacerlo?

    • Pablo

    Hola. Tengo un grave problema.
    Sin saber anda de arduino he ido poco a poco aprendiendo con los tutoriales de esta página. Finalmente he conseguido hacer una estacion meteorologica con lcd tactil que pide datos por wifi a la plataforma Wunderground. Me ha costado un mes conseguirlo, porque la unica manera que he conseguido aprender de pedir datos es mediante comandos AT, y me costó mucho encontrar ejemplos en internet que trabajasen de esa manera, pues la mayoría se le instala una codigo tambien al módulo ESP ademas del que ejecuta el propio arduino, y eso yo no he conseguido entender como funciona. Cosas de la edad, quizas me queda muy grande ya.
    Bien, el case es que , como digo, mediante comandos AT sincronizo la hora interna del arduino, y hago 3 peticiones deferentes con varios datos a Wunderground que luego se parsean y se muestran en pantalla. Aqui mi problema:
    Quiero ampliar funciones, y sincronizar 3 datos de la estacion espacial internacional. Esos datos se obtienen directamente si se abre este link en un navegador:
    Localizacion actual: http://api.open-notify.org/iss-now.json
    Proximas pasadas sobre mi posicion: http://api.open-notify.org/iss-pass.json?lat=40.41711&lon=-3.70311
    Numero y nombre de personas actualmente en la ISS: http://api.open-notify.org/astros.json

    Segun el codigo que uso para hacer peticion, en el comando ” wifi.println(“AT+CIPSTART=\”TCP\”,\”138.68.39.196\”,80″); ” necesito la ip, que he conseguido haciendo un ping a api.open-notify.org
    Tengo el codigo original con la manera de hacer el parse para obtener los datos, y estoy modificando la manera de hacer la peticion segun la forma que yo se, mediante comandos AT, pero siempre me responde BUSY, servidor ocupado en esta linea: ” wifi.println(peticionHTTP); “. Ya no se qué mas cambiar para conseguir estos datos. Agradecería enormemente una ayuda pues llevo una semana obcecado con esto y ya empiezo a desesperarme. Os dejo el código de pruebas que estoy usando para la peticion de datos.
    Gracias por todos los tutos que hacéis, porque sin saber nada de programacion he conseguido muchas cosas gracias a lo que he aprendido con ellos.

    void loop() {

    //Nos conectamos con el servidor:

    wifi.println(“AT+CIPSTART=\”TCP\”,\”138.68.39.196\”,80″);
    if( wifi.find(“OK”))
    {
    String peticionHTTP= “GET /iss-now.json HTTP/1.1\r\nHost: api.open-notify.org\r\n\r\n”; //peticion 1
    // String peticionHTTP= “GET /iss-pass.json?lat=40.41711&lon=-3.70311 HTTP/1.1\r\nHost: api.open-notify.org\r\n\r\n”; //peticion 2
    // String peticionHTTP= “GET /astros.json HTTP/1.1\r\nHost: api.open-notify.org\r\n\r\n”; //peticion 3

    //Enviamos el tamaño en caracteres de la peticion http:
    wifi.print(“AT+CIPSEND=”);
    wifi.println(peticionHTTP.length());

    //esperamos a “>” para enviar la petcion http
    if(wifi.find(“>”)) // “>” indica que podemos enviar la peticion http
    {
    wifi.println(peticionHTTP);
    if( wifi.find(“SEND OK”))
    {
    Serial.print(“Peticion HTTP enviada: “);
    Serial.println(peticionHTTP);
    Serial.println(“Esperando respuesta…”);

    boolean fin_respuesta=false;
    long tiempo_inicio=millis();
    cadena=””;

    while(fin_respuesta==false)
    {
    while(wifi.available()>0)
    {
    char c=wifi.read();
    Serial.write(c);
    cadena.concat(c); //guardamos la respuesta en el string “cadena”
    }
    //finalizamos si la respuesta es mayor a 500 caracteres
    if(cadena.length()>500) //Pueden aumentar si tenen suficiente espacio en la memoria
    {
    Serial.println(“La respuesta a excedido el tamaño maximo”);

    wifi.println(“AT+CIPCLOSE”);
    if( wifi.find(“OK”))
    Serial.println(“Conexion finalizada”);
    fin_respuesta=true;
    }
    if((millis()-tiempo_inicio)>15000) //Finalizamos si ya han transcurrido 15 seg
    {
    Serial.println(“Tiempo de espera agotado”);
    wifi.println(“AT+CIPCLOSE”);
    if( wifi.find(“OK”))
    Serial.println(“Conexion finalizada”);
    fin_respuesta=true;
    }
    if(cadena.indexOf(“CLOSED”)>0) //si recibimos un CLOSED significa que ha finalizado la respuesta
    {
    Serial.println();
    Serial.println(“Cadena recibida correctamente, conexion finalizada”);
    fin_respuesta=true;
    }
    }

    }
    else
    {
    Serial.println(“No se ha podido enviar HTTP…..”);
    }
    }
    }
    else
    {
    Serial.println(“No se ha podido conectarse con el servidor”);
    }

    //——————————————————————————-

    delay(60000); //repetimos tras 1 minuto para probar fiabilidad del codigo.
    }

    • Hola Pablo, Espero que nos disculpes si no reviso tu programa porque no disponemos de tiempo para ello, pero me gustaria decirte que es mucho mas facil usar los comandos internos WIFI mediante la libreria arduino del esp8266 y te recomendaria que probases el nodemcu que equivale a un arduino con wifi.

      Tienes muchos ejemplos de programacion en nuestra pagina que estoy seguro te llamaran la atencion

    • Jorge A.

    Tengo un problema. El módulo funciona bien la primera vez. Luego, si lo reinicio o desconecto/conecto la energía al módulo no inicia. La única solución es volver a flashear.
    Por que sucede esto?

    Tiene alguna solución

    • Creo recordar que esto ocurria porque si programas el modulo sin poner algun pin a un valor entonces la configuraciion se carga en memoria ram pero se pierde al desconectar

      Hablo de memoria pero creo recordar que habia que poner el pin 0 a LOW o asi para que se conserve la programacion en la flash interna

  • Buenas tardes, me llamo María. Primero de todo, felicitaros por los tutoriales y códigos.
    Estoy realizando un proyecto y necesitaría ayuda sobre cómo conectar un módulo ESP8266 con un sensor de temperatura DHT11.
    Estoy iniciando en el tema y no tengo mucha idea, ¿sabéis dónde puedo encontrar algún código que me ayude?
    Muchas gracias.

  • Buen dia, muy excelentes tutoriales.
    Aunque tengo una duda, el while para recorrer el array y configurar el modulo Esp8266 en que parte del codigo se coloca? Dentro del setup, dentro del loop o fuera de ambos? Al igual que la funcion GetLineWIFI supongo que es fuera de todos estos como una funcion independiente al final del codigo.

    Quisiera crear un topico nuevo tambien, para poder compartir un proyecto y necesito ayuda ya que estoy estancado en el mismo por no poder enviar datos usando este modulo a una base de datos y almacene los mismos.

    Espero su pronta respuesta y saludos.

    • Hola Fran, no entiendo muy bien lo que me preguntas

    • Edu

    Buenos dias, me pasa una cosa curiosa, y es que solo puedo ver el texto a 115200, sy pongo otra configuracion no me muestra texto, y cuando quiero cambiarlo siempre me da error. He probado con todas y nada…
    alguna idea?

    • No estoy seguro de cual es tu problema Edu

    • Alfred

    Saludos, estoy aprendiendo sobre los módulos wifi mi consulta es los Arrays que se muestran al inicio ¿Donde se colocan? ¿Que debo hacer con ellos?

    • Los declararías como variables glopbles, es decir, antes del setup.

    • Felipe

    Hola, buena página, tengo una consulta sobre la automatización de los códigos AT. en el loop que los ejecuta aparece WIFI1 y GetLineWIFI(). Estos perteneces a alguna librería? ya que no me los reconoce. estpu probando con arduino uno. gracias

    • Hola Felipe, GetLineWifi es una pequeña funcion que escribimos para leer un puerto serie y que no s eporque no aparece en este listado pero que aqui tienes:
      String GetLineWIFI()
      { String S = “” ;
      if (Serial3.available())
      { char c = Serial3.read(); ;
      while ( c != ‘\n’ ) //Hasta que el caracter sea intro
      { S = S + c ;
      delay(25) ;
      c = Serial3.read();
      }
      return( S ) ;
      }
      }
      Tambien puedes descargarla del programa prog76_1 de esta sesion https://www.prometec.net/servidor-web-esp8266/

  • EXCELENTES códigos y tutoriales mi amigo.

  • Hola Chicos/as
    Estoy haciendo un servidor multi funcion con un arduino uno y un esp8266. Una de las funcionalidades que quería incorporar era la de poder encender un equipo por “Wake on Lan” desde el arduino, ya que mi router vodafone no lo permite.
    Estuve mirando un montón de sitios y encontré muchos códigos para programar directamente en el esp8266 pero ninguno para ser enviado via comando AT, así que me puse manos a la obra.
    Aquí os dejo la función sendMagicPacket dónde se ha de configurar la mac del equipo que queremos encender y asegurarnos que este soporta WOL desde la bios de la placa base.

    void sendMagicPacket(const int timeout, boolean debug){

    String response = “”;
    byte magic_packet[144] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
    byte mac[6] = { 0x00, 0x24, 0x1D, 0xD6, 0x2F, 0x58 };

    for (byte i = 6; i < 144; i++)
    {
    magic_packet[i] = mac[i%6];
    }

    for (byte i = 0; i millis())
    {
    while(wifi.available())
    {
    // The esp has data so display its output to the serial window
    char c = wifi.read(); // read the next character.
    response+=c;
    }
    }
    if(debug)
    {
    Serial.print(response);
    }
    return response;
    }

    // Y el uso sería algo así

    sendCommand(“AT+CIPSTART=4,\”UDP\”,\”192.168.0.255\”,9,9,0\r\n”,1000,DEBUG);
    for(int i = 0; i<10; i++) {
    sendCommand("AT+CIPSEND=4,102\r\n",1000,DEBUG); // Send 102 bytes to transmission num.4
    sendMagicPacket(1000,DEBUG);
    delay(1000);

    lcd.setCursor(0,2);
    lcd.print("Magic packet sent: ");
    lcd.print(i+1);
    }

    Isaac

    • Gracias por el aporte Isaac.

      • Gracias a vosotros por esta gran página.

    • Hola Isaac, Muchas gracias por el aporte. Si te apetece escribir una pequeña sesion sobre esto te la publicaremos encantados en la parte de los tutoriales. Animate que seras bienvenido

Give a Reply

WordPress Anti-Spam by WP-SpamShield

¡Ofertón!

Robot Rover 4×4

Ahora por sólo

50€ + IVA

¡Lo quiero!