Hasta hace no mucho incluir conectividad WiFi en Arduino salia bastante caro, entorno a los 40€, además de haber pocas opciones para escoger. Sin embargo en la actualidad los módulos WiFi han bajado de precio enormemente, como vimos hace un tiempo con el TLG10uA03 que salia por unos 10€, o desde hace unos meses mediante la familia de módulos ESP8266 que salen por unos 3€ dependiendo del modelo que escojamos.
Y es que desde la aparición del ESP8266 hace como medio año, ha sido espectacular la cantidad de proyectos con conectividad WiFi que han aparecido, ha sido tanto el revuelo que incluso extraoficialmente se le ha dado soporte para poder programar este módulo desde el IDE de Arduino, sin necesidad de un Arduino!
El modulo podemos encontrarlo con diferentes formatos, según lo queramos con pines o soldar directo en el PCB, o si lo queremos con antena integrada, externa o con ambas.
Características técnicas
Técnicamente todos tienen las mismas características, salvo porque algunos modelos pueden incluir pines GPIO o no, estos pines pueden sernos útiles si queremos programar el modulo para que realice tareas sin necesidad del Arduino.
Como se puede verse en la siguiente imagen, el primer módulo solo tiene los pines de alimentación y datos, sin embargo el segundo tiene muchos más pines (pads), estos son los pines GPIO.
En cuanto sus características resumidas son las siguientes (aquí las completas):
- Wi-Fi 2.4 GHz, 802.11 b/g/n, WPA/WPA2
- Integra pila de protocolos TCP/IP v4
- Potencia de salida de +20dBm en modo 802.11b
- Conexiones SDIO 2.0, SPI, UART, I2C
- Modulo sueño <10uA, Modo sueño leakage < 5uA
- Despierta y transmitir paquetes en <2 ms
- Consumo de energía de <1.0mW (DTIM3)
- Rango de temperatura de funcionamiento -40C ~ 125C
Alimentación
El modulo funciona con una tensión de 3.3V tanto para su alimentación como en sus pines de datos, usar una tensión mayor puede quemar o estropear el modulo. Además el consumo del módulo puede ser bastante elevado, sobre todo al arranque llegando a picos de 300mA, esto hace que no podamos alimentar el modulo directamente desde el pin de 3.3V de Arduino o corremos el riesgo de que no nos funcione bien el modulo o en el peor de los casos estropear la electrónica del Arduino.
Conexión con Arduino
Por lo general para hacer funcionar los módulos con un Arduino es necesario conectarlos de la siguiente manera:
1 2 3 4 5 6 7 |
ESP8266 Arduino Fuente alimentación ------------------------------------------- GND GND GND VCC 3,3V TX RX RX TX* CH_PD 3,3V |
El pin marcado con * no se puede conectar directamente, hay que usar un divisor de tensión como se muestra en la siguiente imagen:
Comunicación con Arduino
Para la comunicación entre Arduino y el ESP8266 se usa una conexión Serial/UART, por lo que podemos usar el modulo sin necesidad de librerías, aunque con ellas nuestro código quedara más limpio.
Antes de ponerlos a intentar mandar algo a internet, recomiendo trastear con el modulo. Para ello podemos usar un adaptador Serial-USB o el propio Arduino con un scketh especial que lo único que hace es de pasarela entre el Monitor Serial y el modulo, así todos los comandos que escribamos le llegaran al módulo, y todas sus respuestas a nosotros.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
// For Arduino Uno: #include <SoftwareSerial.h> SoftwareSerial wifi(2, 3); // RX | TX void setup() { Serial.begin(115200); wifi.begin(115200); } void loop() { if( wifi.available() ) Serial.print( (char)wifi.read() ); if( Serial.available() ) wifi.print( (char)Serial.read() ); } // For Arduino Leonardo: /* void setup() { Serial.begin(115200); //USB Serial1.begin(115200); //WIFI } void loop() { if( Serial1.available() ) Serial.print( (char)Serial1.read() ); if( Serial.available() ) Serial1.print( (char)Serial.read() ); } */ |
Si usamos un Arduino Uno, deberemos usar la parte de código superior, si usamos un Arduino Leonardo podemos usar la parte de código inferior.
Comandos AT
Para indicarle qué queremos hacer al ESP8266 debemos usar comandos AT, con ellos podemos saber si el conexionado es correcto, podemos saber la versión del firmware, podemos configurar el modulo, podemos realizar conexiones y enviar y recibir datos… con los comandos AT se hace todo.
Los comandos AT usables por nuestro modulo pueden variar según su versión del firmware, por lo general la siguiente lista suele funcionar, recomiendo ver la lista completa aquí.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
Comando Descripción --------------------------- AT Test conexión AT+RST Resetea el modulo AT+GMR Versión firmware AT+CWMODE Establece modo WiFi AT+CWJAP Conecta al router (modo 1 o 3) AT+CWLAP Muestra lista WiFis cercanos AT+CWQAP Se desconecta del WiFi AT+CWSAP Configura el modo AP (modo 2 y 3) AT+CWLIF Muestra IP asignada (modo 1 o 3) AT+CIFSR AT+CIPSTATUS Estado de conexión tcp/udp clients/servers AT+CIPSTART Conexión simple (+CIPMUX=0) AT+CIPSTART= ,, Conexión multiple (+CIPMUX=1) AT+CIPSTART= ,, AT+CIPCLOSE Cierra el socket AT+CIPSEND Envía datos por el socket |
Enviar datos a Thingspeak
Thingspeak es una página que nos permite enviar los datos de nuestros sensores para posteriormente visualizarlos mediante gráficas. Esto o algo incluso mejor podríamos montárnoslo en nuestro propio servidor, pero simplemente como prueba del módulo esta página nos viene perfecta.
El siguiente código se encarga de enviar los valores que queramos a Thingspeak, para ello comprueba si la conexión con el modulo está realizada, configura el WiFi e intenta enviar los datos. En realidad el código nos serviría para cualquier servidor, solo debemos indicarle la IP, el puerto, el servicio que recoge los valores y por último los valores que queramos enviar.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
// For Arduino Uno: #include <SoftwareSerial.h> #define SSID "Vilkin" #define PASS "bwEfuLL6Efu" #define IP "184.106.153.149" // thingspeak.com #define PORT "80" #define SERVICE "/update" #define KEY "QBKGQNF4A9QTCFSX" SoftwareSerial wifi(2, 3); // RX | TX String parameters = ""; void setup() { Serial.begin(115200); wifi.begin(115200); while(!Serial || !wifi); delay(2000); Serial.println("1.Programa iniciado"); Serial.println( connect() ? "2.Conectado" : "2.Error conexion" ); Serial.println( configure(SSID, PASS) ? "3.WiFi configurado" : "3.Error configuracion WiFi" ); Serial.println("4.Inicio envio de datos:"); } void loop() { if( millis() % 10000 == 0 ) { addParameter("key" , KEY ); // String addParameter("field1", millis() / 1000 ); // int addParameter("field2", millis() ); // unsigned long addParameter("field3", millis() / 0.288 ); // float Serial.println( send(IP, PORT, SERVICE) ? " Envio OK" : " Envio Error" ); } } boolean connect() { wifi.println("AT"); delay(5000); return wifi.find("OK") ? true : false; } boolean configure( String ssid, String pass ) { wifi.println("AT+CWMODE=3"); delay(2000); String cmd = "AT+CWJAP=\""; cmd += ssid; cmd += "\",\""; cmd += pass; cmd += "\""; wifi.println(cmd); delay(5000); return wifi.find("OK") ? true : false; } void addParameter( String name, int value ){ addParameter(name, String(value)); } void addParameter( String name, unsigned long value ){ addParameter(name, String(value)); } void addParameter( String name, float value ){ addParameter(name, String(value)); } void addParameter( String name, double value ){ addParameter(name, String(value)); } void addParameter( String name, String value ){ parameters += parameters.length() == 0 ? "?" : "&"; parameters += name; parameters += "="; parameters += value; } boolean send(String ip, String port, String service) { String cmd = "AT+CIPSTART=\"TCP\",\""; cmd += ip; cmd += "\","; cmd += port; wifi.println(cmd); delay(1000); if( wifi.find("Error") ) return false; cmd = "GET "; cmd += service; cmd += parameters; cmd += "\r\n"; wifi.print("AT+CIPSEND="); wifi.println(cmd.length()); wifi.print(wifi.find(">") ? cmd : "AT+CIPCLOSE\r\n"); parameters = ""; return wifi.find("OK") ? true : false; } // For Arduino Leonardo: /* #define SSID "Vilkin" #define PASS "bwEfuLL6Efu" #define IP "184.106.153.149" // thingspeak.com #define PORT "80" #define SERVICE "/update" #define KEY "QBKGQNF4A9QTCFSX" String parameters = ""; void setup() { Serial.begin(115200); //PC wifi.begin(115200); //WIFI while(!Serial || !wifi); delay(2000); Serial.println("1.Programa iniciado"); Serial.println( connect() ? "2.Conectado" : "2.Error conexion" ); Serial.println( configure(SSID, PASS) ? "3.WiFi configurado" : "3.Error configuracion WiFi" ); Serial.println("4.Inicio envio de datos:"); } void loop() { if( millis() % 10000 == 0 ) { addParameter("key" , KEY ); // String addParameter("field1", millis() / 1000 ); // int addParameter("field2", millis() ); // unsigned long addParameter("field3", millis() / 0.288 ); // float Serial.println( send(IP, PORT, SERVICE) ? " Envio OK" : " Envio Error" ); } } boolean connect() { wifi.println("AT"); delay(5000); return wifi.find("OK") ? true : false; } boolean configure( String ssid, String pass ) { wifi.println("AT+CWMODE=3"); delay(2000); String cmd = "AT+CWJAP=\""; cmd += ssid; cmd += "\",\""; cmd += pass; cmd += "\""; wifi.println(cmd); delay(5000); return wifi.find("OK") ? true : false; } void addParameter( String name, int value ){ addParameter(name, String(value)); } void addParameter( String name, unsigned long value ){ addParameter(name, String(value)); } void addParameter( String name, float value ){ addParameter(name, String(value)); } void addParameter( String name, double value ){ addParameter(name, String(value)); } void addParameter( String name, String value ){ parameters += parameters.length() == 0 ? "?" : "&"; parameters += name; parameters += "="; parameters += value; } boolean send(String ip, String port, String service) { String cmd = "AT+CIPSTART=\"TCP\",\""; cmd += ip; cmd += "\","; cmd += port; wifi.println(cmd); delay(1000); if( wifi.find("Error") ) return false; cmd = "GET "; cmd += service; cmd += parameters; cmd += "\r\n"; wifi.print("AT+CIPSEND="); wifi.println(cmd.length()); wifi.print(wifi.find(">") ? cmd : "AT+CIPCLOSE\r\n"); parameters = ""; return wifi.find("OK") ? true : false; } */ |
El resultado por pantalla que tendremos de la ejecución del código sería algo así:
1 2 3 4 5 6 7 |
1.Programa iniciado 2.Conectado 3.WiFi configurado 4.Inicio envio de datos: Envio OK Envio OK Envio OK |
El cogido no comprueba si la información ha llegado correctamente o no… Thingspeak devuelve un 1 si la información se guardó, o un 0 en caso contrario, pero como digo en este ejemplo no se comprueba si los datos se guardaron o no, solo si la llamada se pudo realizar o no.
Y este seria el resultado en la web:
Y por ahora eso es todo, en próximas entradas explicare como cambiar el firmware o como guardar datos en nuestro propio servidor. Tambien me gustaría probar a usarlo de forma autónoma, pero eso solo si saco tiempo 😉
Hola,
Como podria configurar los pines GPIO como I2C?
Saludos
Hola,
Programalo con el IDE de Arduino, deberías de poder usar el I2C sin tener que configurar nada.
Aunque no lo he probado aún, lo he usado siempre junto Arduino.
Saludos.
Si pero el problema es como decirle que pin es el SDA y el SCL no?
En Arduino no se especifica en el sketch, ya que al haber tantas placas seria imposible que un código fuera compatible para todas ellas, lo hace el IDE de Arduino de forma transparente incluyendo las especificaciones de cada micro.
Al agregar el nuevo tipo de placa «ESP8266» como board en el IDE debería de ir igual.
Ten en cuenta que todo lo que puedas o no hacer también dependerá del ESP8266 que uses, algunos tienen 2 o 3 pines GPIO y otros tienen hasta 12 pines, si tu ESP8266 no tiene los GPIO para I2C no podrás aprovecharlos.
Vale,
He visto algún programa en .lua que le indican que GPIO usar para un ESP8266-1, así que creo que puede funcionar con cualquiera.
Probare lo que dices en los diferentes ESP8266 que tengo, incluso tengo un Wemos D1 y un Lolin pero quisiera hacerlo funciona con un ESP8266-1
Ya diré si funciona.
Saludos y gracias.
Solucionado!!!
Tan facil como añadir en el setup
Wire.begin(0,2);
De este modo el GPIO 0 es SDA y el 2 SCL
Bueno es saberlo, a ver si me llega un ESP8266 con forma de Arduino que compre y hago algún tutorial de uso!
Saludos
El D1? yo tengo uno y es una pasada.
La nueva versión además lleva los pines del I2C en el mismo sitio que los UNO normales y creo que será aun mejor.
Exacto! Esa es la placa que me tiene que llegar 🙂