Objetivos

 

  • Desmitificar un poco el TCPIP.
  • Mostrar cómo usar TCPIP para enviar mensajes sencillos.
  • Usar estos mensajes para hacer un data Logger remoto a través de Internet.
  •  

    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.

  • De hecho no es casualidad que tanto la Clase Serial que conocéis, como la del TCPIP descienden y heredan muchas de sus características de la clase Stream, que es una clase básica de comunicaciones en serie, por obra y gracia de las maravillas de la programación orientada a objetos u OOP por sus siglas en ingles.[/fancy-ul] [/three-fourth]
  • 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:

    Estableciendo comunicacion IP

    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.


    Putty 2

    Salida de echo

     

    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.

    Recibiendo mensajes desde Arduino

    [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):

    Activando el registro de datos

     

    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.

  • Para quienes dominan Visual Basic de Microsoft, por ejemplo, es sencillo montar un programa que escuche en la puerta serie y haga un parsing de lo que entra para ir archivando en una BBDD los datos, pero si tenéis que aprender Visual Basic para esto os resultará avasallador.
  • Y lo mismo os pasará con mySql, PHP, o Perl. No os liéis no merece la pena salvo que seáis programadores profesionales. Todo es fácil y se puede aprender, pero la cuestión es si disponeis del tiempo necesario para ello.

    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.

  • Google Fusion Tables es mucho más que esto y puede convertirse en un agrgador de datos de fuentes dispersas de información en Internet, pero en este momento solo me interesa por su capacidad de comportarse como una base de datos mantenida por Google a la que podemos acceder vía web.

    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

     

  • Hemos Hemos visto que los mensajes a través de TCPIP no son muy diferentes de los que podemos enviar mediante el puerto Serial. comparte con él muchos métodos.
  • Hemos visto como registrar eso datos mediante un programa de terminal que guarde registro de los datos recibidos en un fichero de texto.
  • Es un principio, para montar programas que reporten lecturas de campo a un servidor en Internet.
  • Con esta idea, hemos montado un pequeño programa que envía datos vía TCPIP a un servidor remoto.
  • Deja una respuesta