Archivos mensuales: agosto 2013

Arduino GSM Shield: Comunicando tu arduino con el mundo exterior

Si como yo, has estado jugando un poco con tu Arduino, tarde o temprano llega un momento donde es necesario conectarlo al mundo exterior. Lo mas usual es conectarlo mediante Ethernet o WiFi si te dá el presupuesto, para poder enviar información hacia el mundo exterior.

Pero estas no son las únicas opciones de comunicación. En esta ocasión, vamos a revisar el Shield GPRS/GSM EF-Com fabricado por la Elekfreaks, y distribuido por www.dx.com.

Este shield, permite que nuestro arduino opere como un teléfono GSM, obviamente debiendo programar todas las funciones del mismo. Dentro del hardware de este shield, podemos encontrar los siguientes dispositivos:

  • Modem GSM/GPRS basado en el chip SIM900
  • Conectores de entrada y salida de audio (para realizar o recibir llamadas)
  • Reloj RTC, con batería de respaldo
  • Varios pines de GPIO libres controlables  mediante comandos AT
  • Opción para conexión RS232 via hardware o software

Contenido del paquete

Al recibir el paquete, pude notar inicialmente, que el empaque era bastante grande para un shield de Arduino, por lo que definitivamente debía tener varios items en su interior. Dentro del paquete, al abrirlo pude encontrar:

  • Shield GSM / GPRS
  • Antena externa
  • Adaptador de 9V / 1A
  • Display Nokia 5100 con backlight Azul

DSC00285

 

DSC00286

 

DSC00291

 

El display es un extra inesperado. En el sitio web no indica que se incluye este display, pero el Shield tiene un header instalado propiamente para éste. Es un extra que da valor agregado al producto.

Operación

El adaptador de 9V es necesario, porque alimentando directamente al Arduino y al Shield desde el puerto USB, éste no alcanza a proveer la corriente necesaria para su operación. Según el fabricante, el módulo en picos de consumo de corriente, puede superar 1A facilmente.

Algo a tomar muy en cuenta, es la posición del display LCD en el shield. Lastimosamente no existen marcas del Pin 1 del header, y en el Wiki del fabricante, menciona que el LCD con backlight azul (existen 2 versiones, una con backlight azul y otra con backlight blanco) debe ir como se muestra en las fotos, con el display sobre el chip SIM900. Esta posición es incorrecta, ya que el display con backlight azul debe ir montado en la posición exterior del Shield. Esto lo veremos en las imágenes posteriores.

Programación

Como lo mencionabamos, el Shield GPRS funciona como un modem GSM serial, es decir, para su uso, únicamente requerimos los pines Rx, Tx y Gnd del puerto serie de nuestro arduino, o de un puerto serial por Software, en los pines que nosotros definamos

Tomando en cuenta esto, vamos a programar un pequeño Sketch, que ejecutará las siguientes tareas:

  1. Mostrará un mensaje de bienvenida en el LCD Nokia 5100
  2. Esperará un caracter en el puerto serial del Arduino
  3. Mediante un Puerto Serial de Software inicializará la comunicación con el Shield GSM
  4. Enviará un mensaje de texto (SMS) a un número colocado en el software

El código que vamos a usar en nuestro arduino es el siguiente:

#include <"lcd5110_graph.h">
#include <"softwareserial.h">

LCD5110 myGLCD(9,10,11,12,13);

extern uint8_t SmallFont[];

#define rxPin 2
#define txPin 3

SoftwareSerial mySerial(rxPin, txPin);

char *init1="AT+IPR=19200";  // configuracion del modulo para 19200bps
char *init2="AT+CMGF=1";  // configuracion para modo ascii 
unsigned char CR=13; // caracter de retorno de linea
void setup()
{
  myGLCD.InitLCD();
  myGLCD.setFont(SmallFont);

  mySerial.begin(19200);                 // Velocidad de conexion por defecto del Shield  
  Serial.begin(19200);                  // Velocidad del puerto serie
  Serial.println("Conexion Serial Ok.");

  myGLCD.clrScr();
  myGLCD.print("Prueba del", CENTER, 0);
  myGLCD.print("GPRS Shield   ", LEFT, 12);
  myGLCD.print("patolin.com   ", LEFT, 30);
  myGLCD.update();
}

void loop()
{
  // inicializamos el shield

      mySerial.write(init1);
      mySerial.write(CR);
      delay(1000);
      mySerial.write(init2);
      mySerial.write(CR);
      delay(1000);

  myGLCD.clrScr();
  myGLCD.print("SMS", CENTER, 0);
  myGLCD.print("Esperando", LEFT, 12);
  myGLCD.print("caracter al ", LEFT, 24);
  myGLCD.print("RS232", LEFT, 36);
  myGLCD.update();

  // esperamos un caracter cualquiera en el puerto serie

  if (Serial.available()) {
      if (mySerial.available()) Serial.write(mySerial.read());
      // limpiamos el buffer de lectura
      Serial.read();

      // enviamos el sms
      myGLCD.clrScr();
      myGLCD.print("SMS", CENTER, 0);
      myGLCD.print("Enviando....", LEFT, 12);
      myGLCD.update();

      mySerial.write("AT+CMGS=\"099XXXXXXX\""); // reemplace por el numero de celular de destino  
      mySerial.write(CR);
      delay(1000);
      mySerial.write("Prueba de SMS desde Arduino!");  
      mySerial.write(CR);
      delay(1000);
      mySerial.write(26);  // Ctrl+Z para finalizar el mensaje y enviar
      myGLCD.print("enviado!", LEFT, 30);
      myGLCD.update();

  }

}

Bastante sencillo cierto? El código se explica solo. Basta con configurar la comunicación con el Shield a la misma velocidad (19200bps en este caso) y enviar los respectivos comandos. Al ser un modem GRPS, responde a una amplia variedad de comandos AT, que podemos revisarlos en este manual propio del fabricante.

Les dejo un video de la prueba de este código sobre mi Arduino.

Para concluir, las aplicaciones para este Shield son varias! Desde una alarma de seguridad de hogar con notificaciones por SMS, hasta un dispositivo remoto que pueda contestar llamadas y devolver información.

Para concluir, podemos resumir las características de este Shield, en las siguientes:

  • Shield GSM/GPRS Quad-Band 850/900/1800/1900 MHz, con el chip SIM900 GSM
  • Compatible con Arduino Uno / Mega
  • Voltaje de Operación 5Vcc
  • Socket plástico para el Chip GSM ubicado en la parte inferior del Shield
  • Antena externa, en L para mayor facilidad de ubicación
  • Adaptador de alimentación incluido
  • Jacks de Entrada y Salida de Audio, para la generación de llamadas telefónicas via celular
  • Reloj en tiempo real incluido
  • Display LCD Nokia 5100  incluido

Para los entusiastas de la electrónica y del Arduino, puedo comentarles que el precio de este Shield es un poco elevado. El costo es de USD. 57,70 incluido el envío desde China. Si descontamos el valor del LCD y del adaptador, podríamos llegar a los USD. 50,00 que sigue siendo algo elevado, tomando en cuenta el costo del Arduino. Pero si vamos a usar este Shield en una aplicación profesional, Si resulta muchísimo más barato que otras soluciones de comunicación GSM que existen en el mercado.

Les dejo algunos enlaces correspondientes a este producto. Espero les sean de interés

 

Poniendo a trabajar al Raspberry Pi

El famoso Raspberry Pi. La pequeña computadora de $35 que ha causado furor a nivel mundial, y ha inspirado algunos clones, unos mas potentes que otros, pero, como en todo en la vida, el que pega primero, pega dos veces!

Con el Raspberry han hecho de todo, desde encender y apagar un LED, hasta controlar una torre de telefonía celular (pasando por un sistema casero de vigilancia que funciona 24/7 en mi morada, jugar minecraft, servir tragos….. una larga lista); pero hay realmente pocas aplicaciones “económicamente rentables” que se hayan dado a conocer.

Lo que les voy a comentar no es una aplicación, sino una prueba de concepto, de cómo ésta pequeña tarjeta electrónica, puede realizar un trabajo pesado, con un bajisimo gasto energético. No voy a dar soluciones de código, no extensas explicaciones de como hacer A o B tarea en X lenguaje de programación, solamente voy a comentar mi experiencia con un trabajo “del mundo real” aplicando el Raspberry Pi para su solución.

Resulta que en un proyecto personal, se me encomendó la tarea de extraer determinada información de cierto website, para luego procesarla e indexarla. Para qué hacer esto? Pues el sitio web original no era muy amigable al usuario, y estaba realizado sin una plataforma de base de datos. Entonces la del proyecto quedó planteada de esta manera:

  1. Generar un índice del sitio web, con los links de todas las páginas que contenían la información requerida
  2. Navegar página por página del indice de links, recabando determinada información contenida dentro de cada link
  3. Almacenar la información extraida en una base de datos, para su posterior análisis
  4. Generación de un nuevo índice dinámico, usando la información almacenada en la base de datos.

No suena complicado (en teoría), pero el problema principal era la GRAN cantidad de trabajo. El sitio web antiguo contenia alrededor de 7000 subpáginas con información, y recopilar la misma manualmente era una tarea titánica, hubiera requerido una cantidad considerable de personal, y un tiempo bastante largo para concluirla. Es aquí donde después de echarle cerebro un rato decidí darle una solución viable al problema.

Antes de decidir que y como resolver el problema, decidí investigar un poco, y de paso, esta fué la oportunidad perfecta para programar en Python usando Linux. Este lenguaje brinda muchísimas facilidades en cuanto al procesamiento de páginas web, por lo que se convirtió en el “Weapon of Choice” del proyecto.

Al hablar de facilidades en el procesamiento de páginas web, existen funciones en Python, que nos permiten almacenar el contenido de una página entera, dentro de una variable, por ejemplo, si quisieramos pasar el codigo html de www.patolin.com a una variable, tendríamos el siguiente script:

import urllib2

url="http://www.patolin.com"
page=urllib2.urlopen(url)

Simple no? Con estas 3 líneas de código (que de hecho pueden ser 2 jejeje), logramos que todo el contenido de dicha web, se almacene en la variable “page”. Pero bueno, un punto menos del problema resuelto. Ahora, como buscamos información dentro del contenido de la variable “page”? Es aquí, donde con un poco de Google, encontré la librería BeautifulSoup, que permite analizar código HTML y separarlo según tags…. perfecto para el caso.

Las instrucciones para instalar esta librería se encuentran bien documentadas en el sitio web, así que no presentará ningún problema por si quieren probarla. Ahora, como funciona? muy simple! Miremos el siguiente código:

import urllib2
import BeautifulSoup
url="http://www.patolin.com"
page=urllib2.urlopen(url)
soup = BeautifulSoup(page.read())
titulos=soup.findAll('h2')
foreach titulo in titulos
    print titulo

Pues que hace este pequeño fragmento de código? Primero, como vimos anteriormente, nos captura el contenido de la url www.patolin.com, y lo almacena en la variable “page”, luego dicha variable, pasa a indexarse mediante la librería BeautifulSoup en la variable “soup”, realizamos una búsqueda de todos los tags “<h2>” que son los títulos de los posts de patolin.com. Finalmente, dado que los titulos se guardan en un array, imprimimos en pantalla título por título hasta llegar al final.

Como vemos, algo que quizás pueda resolverse en otros lenguajes más potentes, con algo más de programación, gracias a las librerias existentes se vuelve una tarea bastante trivial en Python. Con estas pocas líneas de código, hemos resuelto una gran parte del problema, ya que con este código, simplemente debemos crear 2 bucles:

  • Uno que revise el índice actual de la página y extraiga todos los links existentes
  • Otro que usando los links extraidos del punto anterior, extraiga el contenido de la página

El como hacer estas tareas, se los dejo de pregunta de examen, pero no es nada del otro mundo. Ahora nos falta el almacenado en la base de datos. Para esto, por conveniencia, vamos a usar MySql como base de datos destino, y como era de esperarse, Python tiene soporte para manejo de MySql integrado en su instalación.

Cargar datos en MySql, se vuelve algo tan simple como ejecutar los siguientes comandos en Python

 

import MySQLdb as mdb

try:
    con = mdb.connect('dbhost', 'usuario', 'clave', 'nombredb')
    cur = con.cursor()
    cur.execute("INSERT INTO datos (titulo, contenido) VALUES (%s, %s)", (varTitulo, varContenido, ))
except mdb.Error, e:
    print "Error %d: %s" % (e.args[0],e.args[1])
    sys.exit(1)
finally:
    if con:
        con.close()

 

En este ejemplo, de una tabla con las columnas “titulo” y “contenido”, basta con cargar los datos en las variables varTitulo, varContenido (ojo con la última coma), e iremos almacenando los datos en nuestra base MySql.

Con todos estos pedazos de código, basta con unirlos, y tenemos lista la aplicación que escanea el contenido de un website, lo procesa, y almacena en una base de datos. La visualización de los datos almacenados en el MySql queda para una sencilla página de PHP, que no viene al caso de este post.

Ahora, donde entra nuestro estimado Raspberry Pi? Pues como les decía, el proceso involucraba analizar 7000 páginas html, y la extracción de la información, incluido el tiempo de carga y almacenamiento en el Mysql (ojo, es una DB en línea, no local) hacía que en promedio demore de 15 a 20 segundos POR PÁGINA, lo que en tiempo total de procesamiento, aproximadamente iba a demorar 38 horas, lo que implicaba tener encendido el computador 38 horas, con el consiguiente consumo de energía.

Instalé el script generado y las librerías en mi Raspberry que está en mi casa, y funcionó correctamente, así que ejecutarlo desde ahí tendrá las siguientes ventajas:

  • El Raspberry Pi, de por sí pasa encendido 24/7, consumiento algo así como 5W, nada comparado con los 700W de mi desktop
  • La conexión a internet de mi casa pasa libre todo el día, desperdiciando un par de Mbps de velocidad
  • El proyecto no era de un apuro terrible, un día más o un día menos era aceptable

Y lo ejecutamos pues desde el Raspberry. Poco a poco la información se iba cargando en el MySql, y cerca de las 48 horas, finalizó. Si vamos al consumo energético, podemos comparar:

  • 700W * 35 horas = 24.5 kwh
  • 5W * 48 horas = 0.24 kwh

No hay por donde perderse. Con un consumo 100 veces menor se realizó la misma tarea usando el computador de bolsillo. El cliente contento, por ver su proyecto cumplido, yo contento por hacer algo bueno en Python, y el planeta contento por el ahorro de energía alcanzado.

🙂