Objetivos
Material requerido
[product id=»8820″] |
WIFI CC3000 |
Enviando y recibiendo datos por WIFI / TCPIP
El tema de las WIFI y de las posibilidades que ofrecen para nuestros proyectos es sin duda la estrella del interés de los Arduineros últimamente, lo que no es de extrañar ya que nos permiten enviar datos de modo inalámbrico al punto de acceso y de ahí a cualquier punto del globo.
Y parece que una de las cosas que más consultas de nuestros amables lectores generan, es la de como enviar datos de un sitio a otro y de cómo recibirlos de un modo practico.
Y como en esta casa nos gusta desmitificar las cosas, porque sabemos que no hay cosas difíciles (Observese que no digo creemos, digo sabemos) vamos a hacer algunos ejemplos a base de enviar y recibir mensajes vía TCPIP de un sitio a otro de modo que sirva como una guía básica de acciones posibles, que naturalmente, se puede complicar hasta el infinito, pero que de salida muestre algunas operaciones básicas.
Siguiendo el espíritu de la casa, procuraremos hacer ejemplos minimalistas, que ayuden a iniciarse a quien lo necesite, y al alcance de cualquiera que se haya hecho el curso de introducción de Prometec.net y tenga ganas.
Montando un echo server
Vamos a empezar por lo más fácil. Un programa que monta un servidor TCPIP en Arduino y escucha en una puerta definida, por ejemplo la 7, y que simplemente copia lo que le enviamos y lo devuelve a la entrada.
No ganaremos ningún premio por semejante proyecto, pero nos servirá para ilustrar, que el TCPIP no es muy diferente de la puerta Serial a la que estáis sobradamente acostumbrados con Arduino.
SI, hay más teoría, existen sockets, direcciones IPs, puertos y hasta múltiples servicios que pueden resultar abrumadores como DNS, DHCP, HHTP, FTP y otro sin número de ellos, pero aquí queremos centrarnos en los aspectos básicos, por lo que vamos a reducir el ruido hasta donde sea posible, para que veáis, que al final el TCPIP es una comunicación serie que puede aceptar múltiples canales concurrentes a la vez y por eso el aumento de la complejidad.
Vamos a partir del ejemplo que viene en la librería de Adafruit para rebotar lo que entra en el servidor desde por ejemplo un terminal con Putty que nos permite enviar un mensaje al servidor y ver la respuesta de vuelta.
Vamos con el programa de echo. La parte de la conexión a la WIFI empieza ser repetitiva así que la montamos sin más comentarios: Prog_114_1
include <Adafruit_CC3000.h> #include <SPI.h> #define ADAFRUIT_CC3000_IRQ 3 // MUST be an interrupt pin! #define ADAFRUIT_CC3000_VBAT 5 #define ADAFRUIT_CC3000_CS 10 // Adafruit_CC3000_Client client; Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,SPI_CLOCK_DIVIDER); // you can change this clock speed #define WLAN_SSID "charly" #define WLAN_PASS "contrase" #define WLAN_SECURITY WLAN_SEC_WPA2 #define LISTEN_PORT 7 // Puerto de escucha, Podeis modificarlo a vuestro gusto Adafruit_CC3000_Server echoServer(LISTEN_PORT);
Solo hay de nuevo las dos últimas líneas, que definen el Puerto de escucha TCPIP y abrimos un servidor en ese Puerto.
void setup(void) { Serial.begin(115200); Serial.print("Shield CC3000!"); Serial.println(" Inicializando..."); if (!cc3000.begin()) { Serial.println("Error"); while(1); } Serial.print("\nConectando a "); Serial.print(WLAN_SSID); if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) { Serial.println("Failed!"); while(1); } Serial.println("...OK!"); /* // Solo es necesario si antes no te has conectado Serial.println("Request DHCP"); while (!cc3000.checkDHCP()) delay(100); */ while (! displayConnectionDetails()) delay(1000); echoServer.begin(); // Empieza la escucha de posibles conexiones Serial.println("Esperando conexiones..."); }
De nuevo, pocas diferencias, con la excepción de que iniciamos el server con la anteúltima instrucción echoServer.begin(). Vamos con el programa principal
Adafruit_CC3000_ClientRef client = echoServer.available(); if (client) { if (client.available() > 0) // Comprobamos si hay algo que leer { uint8_t ch = client.read(); // Leemos un byte y lo rebotamos client.write(ch); } }
Creamos una instancia de un cliente que se conecta y esperamos hasta que hay algo disponible. En caso afirmativo, leemos un byte y lo volvemos a escribir al mismo cliente. No hay más.
Como veréis, no es muy diferente de lo que sería escuchar el puerto Serial y devolverle lo que escuchamos en él. Simplemente client está definido como una instancia de una clase diferente pero los métodos son similares y en la medida de lo posible se llaman igual.
Vamos a arrancar Putty para hacer la conexión:
Tenéis que poner la dirección IP de vuestro servidor y recordad que hemos definido el puerto 7 de escucha. Elegid el tipo de conexión Raw que es TCPIP puro.
[one-fourth] [/one-fourth][three-fourth last][margin value=»5″ /][fancy-ul style=»rounded-tick»]
[three-fourth last][margin value=»5″ /][fancy-ul style=»rounded-tick»]
- Como siempre, yo estoy usando Windows para escribir la sesion, pero si usais OSX, podeis usar el terminal de modo similar, y en Linux teneis varios terminales TTY disponibles.[/fancy-ul] [/three-fourth]
Cualquier cosa que ahora escribáis en la consola de Putty será rebotada por vuestro Arduino con lo que en la práctica tendréis un echo automático de lo que escribáis, de ahí el nombre del programa.
Enviando lecturas desde Arduino
Una vez que entendemos que enviar datos vía TCPIP no es diferente de establecer una comunicación serial (Aunque un pelín más complicada), podemos plantearnos abrir un servicio cliente TCPIP hacia vuestro PC y usar Putty o similar para recibir lo que nos envie Arduino.
La primera dificultad que tenemos que resolver es que Putty necesita iniciar la conexión el mismo, y por tanto tenemos que montar un servidor TCPIP en nuestro Arduino. No podemos poner Putty como servidor y llamar desde Arduino.
Por eso necesitamos montar el servidor y esperar a que Putty inicie la comunicación y abra un socket valido.
Podríamos pensar que una vez que abrimos el cliente en el ejemplo anterior el cliente queda disponible, pero no. El cliente desaparece cuando no hay nada mas que recibir y la cola se vacia.
Así que de momento vamos a asegurarnos que haya algo que recibir enviándolo desde Putty y no recogiéndolo (Un trabajo sucio, pero alguien tiene que hacerlo).
[one-fourth] [/one-fourth][three-fourth last][margin value=»5″ /][fancy-ul style=»rounded-tick»]
[three-fourth last][margin value=»5″ /][fancy-ul style=»rounded-tick»]
- No es un método muy elegante, pero es sencillo y eficaz, y no conozco suficientemente la librería CC3000 para encontrar otro modo sencillo de hacerlo.[/fancy-ul] [/three-fourth]
El programa sería algo así: Prog_114_2
Adafruit_CC3000_ClientRef client = echoServer.available(); if (client.available() > 0) { for (int i = 0; i <1000 ; i++) { client.print( millis()) ; client.print ('\t'); // Tabulador client.print(i) ; client.print ('\t'); // Tabulador client.println( analogRead(A0)) ; } delay (500); }
El resultado será el siguiente. Cuando Putty arranque, se conecta a nuestro servidor Arduino, pero mientras no envíe algo, no se establecerá la conexión.
Cunado enviemos cualquier cosa , la línea se abre y disponemos de un canal de comunicación valido que podemos usar para enviar a origen lecturas de nuestro Arduino con una señal de hora, y una lectura del puerto A0, por ejemplo.
[one-fourth] [/one-fourth][three-fourth last][margin value=»5″ /][fancy-ul style=»rounded-tick»]
[three-fourth last][margin value=»5″ /][fancy-ul style=»rounded-tick»]
- El tabulador se podría reemplazar por una coma más espacio como “, “porque siempre es más fácil importar con delimitadores claros a un Excel por poner un ejemplo.
- Además el texto delimitado por comas es tan frecuente que hasta existe un formato definido que se llama CSV (Comma separated values) y que cualquier programa que se precie es capaz de importar.[/fancy-ul] [/three-fourth]
Vale. Todo muy bonito en pantalla, me diréis, pero lo que yo quiero es poder tener esos datos en un fichero de texto para procesarlos posteriormente y no veo cómo sacarlos de ahí.
Hombres de poca fé. Nada más sencillo. Basta con activar el Logging en Putty, o en cualquier otro programa de terminal que estéis usando.
Para ello desde Putty acceder a la sección de Logging (Registro):
Seleccionad registrar todo, y asignad un nombre a los datos, en mi caso Registro, Putty añadirá la extensión .log al fichero y eso es todo. A partir de ahora todas las lecturas que enviemos desde Arduino a Putty quedaran reflejadas en el registro como un fichero de texto que es fácilmente importable a un Excel por ejemplo.
Importando a bases de datos más sofisticadas
El problema de registrar lecturas de unos sensores es una constante en los foros por la necesidad de proceso posterior de la información.
He visto en internet varios ejemplos de cómo enviar estos datos a BBDDs más sofisticadas como mySQL o Acces, pero el problema de esto es que resulta imprescindible que conozcáis a fondo los programas que vais a utilizar, lo que por regla general no solo complica el problema del registro, si no que habitualmente queda muy fuera del alcance de un aficionado Arduino promedio.
Además genera problemas propios para los novicios como pelear con la seguridad de mySql y cargar con la administración del servidor. Eso sin contar que además suele ser necesario hacer el interface con Perl, Python o PHP, lo que añade nuevas angustias al sufrido aficionado.
Si ya conocéis todo esto, adelante…. Pero si no, ni se os ocurra entrar en esta guerra porque las posibilidades de que salgáis trasquilados rayan la certeza y peor aún, os desanimará.
El sistema que hemos visto arriba, es menos elegante de lo que me gustaría y está muy lejos de ser perfecto, pero es el más sencillo que se me ha ocurrido y tiene la virtud de que lo puedes arrancar en minutos y os permite mantener el control de la aplicación sin depender de terceros.
Hay una opción intermedia que me gusta y que he estado peleando en los últimos días. Es el nuevo servicio de Google llamado Fusión Tables.
Básicamente nos permite crear BBDDs de acceso público o privado que visualizamos como tablas similares a Excel o a Google Docs, pero que nos permite leer las líneas mediante REST, del que no hemos hablado o JSON del que si hemos tenido más contacto.
De este modo, mediante un lenguaje sencillo y por medio de un navegador podemos leer filas o columnas (mediante querys http y Arduino) hacer consultas que cumplan ciertas condiciones e insertar o añadir nuevas filas.
Las Google Fusión Tables, son una solución ideal para los que queremos enviar a una BBDD en la Web información tabulada y por regla general simplemente insertar lecturas sucesivas con una marca de tiempo.
El problema es que aún es un servicio experimental, que han vuelto a cambiar las consultas y el lenguaje y que han montado un sistema estricto de seguridad con registros incluidos que hacen que por ahora quede fuera del alcance de los no profesionales.
Pero confío en que poco a poco el entorno se estabilice y se abra a pequeños usuarios, en la tradicional línea de Google. Si es así, Google Fusion Tables pueden ser una herramienta excepcional para los que tenemos interés en recabar datos en el campo e integrarlos en tablas en Internet a través de sencillos mensajes Http.
Resumen de la sesión