Arduino: multithreading

Hoy hablaremos de un tema bastante importante en el mundo de los microcontroladores, así como en el de los microprocesadores: el multithreading, o multihilo, en castellano.

El multithreading en arduino no es posible. Pero como tenemos un buen reloj, en la mayoría de los casos, lo que si podemos hacer es que las subrutinas que queramos ejecutar en “paralelo” se ejecuten de manera concurrente, de modo que “parezca” que realmente estamos ejecutándolas simultáneamente o, como comentábamos, en multithreading.

En Arduino este problema lo asociamos a la expresión “delay vs millis”, es decir, tiempo de espera contra contador de tiempo, por decirlo de alguna manera. Si tenéis cierta experiencia en Arduino sabréis a lo que me refiero. Sino, os lo explico rápidamente.

Un caso de ejemplo muy práctico es el de hacer parpadear un LED cada cierto tiempo, mientras escaneas la entrada, ya sea una pulsación de un botón o un dato… El caso práctico nos dice que, lo sencillo, es hacer que el LED se encienda, esperamos cierto tiempo, lo apagamos y, posteriormente (ojo que hay una coma), realizamos el escaneo del dato de entrada. Bien, en este tiempo de parpadeo nos hemos visto obligados a parar el proceso loop() cierto tiempo (delay()) en pro de poder encender y apagar el LED a nuestro antojo. Si en ese tiempo, hemos tenido una pulsación del botón de entrada, es posible que la hayamos perdido, ya que teníamos el sistema parado!

He aquí el problema: para hacer el parpadeo hemos parado el proceso loop(), cosa que hace que Arduino se duerma durante x milisegundos… Teniendo en cuenta a la velocidad que corre actualmente una placa Arduino (unos 16MHz), podríamos haber tenido unos cuantos ciclos de loop ejecutándose por segundo en los que podríamos haber hecho otras muchas cosas. Pero no, nosotros lo teníamos dormido…

Os muestro el claro ejemplo, el archiconocido Blink:

void loop() {
    digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(1000);               // wait for a second
    digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
    delay(1000);               // wait for a second
}

Fijáos, hemos detenido el proceso loop durante 2000ms, 1000ms para encender y 1000ms para apagar…

La solución es usar la función millis() en vez de delay(). La idea, no parar la ejecución, e ir preguntando constantemente si se debe apagar o encender el LED en función de si ha pasado el tiempo establecido para cada caso. Y no hay que preocuparse por el constantemente (que suele dar miedo), ya que loop está funcionando, también, constantemente…

Os dejo un código que lo ilustra:

unsigned long previousMillis = 0;  // Tiempo anterior 0
unsigned long timeToAction = 1000; // Tiempo de espera entre acciones, 1000ms

void setup() {
    ...
}

void loop() {
    // Obtenemos el momento actual en ms
    unsigned long currentMillis = millis();

    // Si ha pasado el tiempo establecido, ejecutamos la acción
    if(currentMillis - previousMillis >= timeToAction) {
         // Encendemos o apagamos el LED 
         digitalWrite(led, digitalRead(led)^1); 

        // Almacenamos el último momento en que hemos actuado 
        previousMillis = currentMillis; 
    } 
}

Como vemos, no es una solución difícil de comprender:

  • A cada paso de loop(), obtenemos en tiempo actual de ejecución (función millis()) en la variable currentMillis
  • Comparamos el tiempo actual (currentMillis) con el anterior momento en el que hemos actuado (previusMillis) y, si su diferencia es igual o mayor al tiempo de acción (timeToAction), significa que ha pasado el tiempo establecido y por lo tanto realizamos la acción (encender o apagar el LED)

Poco mas que eso para ver que es posible encender y apagar el LED cada 1000ms sin necesidad de parar el proceso loop(), con lo que podemos hacer otras muchas cosas mientras.

Sólo una cosa a tener en cuenta y es que, aunque seguramente no seremos capaces de verlo a simple vista, a tiempos muy bajos es posible que no seamos realmente exactos en el tiempo de acción, dado que seguramente en el transcurso de ejecutar las sentencias de comparación, hayan pasado algunos pocos ms que quedan fuera del tiempo de ejecución. ¿Esto qué significa? Pues que seguramente en vez de apagar o encender el LED en el milisegundo 1000 lo hagamos en el 1005 o el 1010… Pero, ¿quién puede detectar ese error a simple vista? El ojo humano no… Otra historia es que nuestra aplicación haga uso de un conteo preciso de tiempo… Habría que tenerlo en cuenta, aunque como os comento, para la mayoría de casos, ese tiempo, es negligible…

Espero que haya sido de vuestro interés. En otra ocasión os mostraré cómo manejar tareas de manera concurrente, algo mas complejas.

Jordi

Share Button

HTML5: test de compatibilidad de navegadores

La pasada semana me vi un poco ofuscado, porque tenía que testear un proyecto el el que estoy enfrascado para que sea compatible en “todos” los navegadores. Cómo no, el problema me lo dio Internet Explorer. En especial la versión 8. Cómo se puede trabajar tan mal, oigan!!!

Bien, por mucho que te esmeres en hacer un CSS de calidad, que cumpla las normas, eficiente, AAA, etc etc etc… siempre habrá alguien que no te lo va a permitir (¿alguien ha dicho MSIE?).

Maravillas no existen y, milagros, a Lourdes. Pero al menos podemos asegurarnos de que nuestro navegador cumpla con ciertos estándares.

Os dejo un enlace a la página: http://html5test.com/

Y unas capturas. Merece la pena echarle un vistazo.

HtmlTest

Pantalla inicial. Parámetros de nuestro navegador. En mi caso, Chrome 32 en Windows 7 (quizá el mejor de todos). También podemos ver navegadores para teléfonos móviles y tablets. Vamos, muy completito…

 

HtmlTest

Comparación entre navegadores. He aplicado los mas utilizados actualmente, incluyendo el nefasto MSIE8. Penoso…

Espero que os sea útil!

Jordi

Share Button

RasPi: Bluetooth en nuestra Pi

Muy buenas a tod@s,

En esta entrada de hoy voy a intentar aproximaros un poco al mundo de la comunicación inalámbrica, con la Raspberry Pi. En concreto, vamos a instalar un controlador de Bluetooth.

Últimamente estoy bastante metido en el campo de Arduino y la domótica o control de sensores, y tenía pensado hacer un radioenlace con un RF433Mhz, pero… qué queréis que os diga, es lento y necesitas estar muy cerca. Por contra, es muy barato… Así que esta semana decidí que iba a probar algún adaptador de BT para arduino. Y lo he encontrado, se trata de la familia HC-0X (en en otro post os pasaré a comentar, sin falta). En concreto he adquirido un par de HC-05 y otro Arduino Nano (aunque clónico), adicional (con este ya son 3 en la familia, es como un vicio!!!).

En este post os presento la manera de conectar un dongle o usb adaptador de BT a nuestra Pi. Ya os avanzo que, mientras estoy escribiendo este artículo, me doy cuenta que es todo un reto, dado que este adaptador ya tiene bastantes años, y últimamente la gente que trata Pi está muy meticulosa con las compatibilidades. Vamos a demostrar que eso no es necesario…

Bien, vamos al lío.

Adaptador utilizado

Sitemcom CN-502

Sitecom CN-502

Para este mini tutorial, como os comentaba, he utilizado un antiguo SITECOM CN-502. Es algo antiguo, pero funciona perfectamente. Cumple con las normas actuales, aunque no sea de los más rápidos. Con ello, conseguiremos el reto, que es demostraros como instalar “casi” cualquier adaptador de bluetooth en nuestra Pi.

Configuración

A continuación, tan sencillo como conectar el adaptador en el único puerto USB que me queda libre, lo que hacemos es encender la Pi (yo uso Raspbian) y esperar a que esté lista para entrar por ssh.

Miremos si nos lo ha detectado:

pi@raspberrypi ~ $ lsusb
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 148f:5370 Ralink Technology, Corp. RT5370 Wireless Adapter
Bus 001 Device 005: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)

En efecto, ahí lo tenéis, en la línea 6: Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)

Vamos a instalar los drivers necesarios. Como siempre, lo primero que tenemos que hacer es mantener nuestra Pi al día.

Actualicemos el sistema…

pi@raspberrypi ~ $ sudo apt-get update
pi@raspberrypi ~ $ sudo apt-get upgrade
pi@raspberrypi ~ $ sudo apt-get autoclean

Y ahora, ya podemos descargar un paquete de drivers general para Bluetooth (sed pacientes, hay mucho que descargar…):

pi@raspberrypi ~ $ sudo apt-get install bluez bluetooth bluez-utils blueman

Si todo ha ido correcto, ya tenemos los drivers instalados y listos para trabajar con ellos. En un principio no es necesario reiniciar la Pi, ya que es algo como plug&play, se inicia solo el servicio.

Emparejando dispositivos

Bien, después de la descarga, ya tendremos los drivers instalados. Ahora es el momento de buscar y emparejar dispositivos. Para ello, hacemos uso de la llamada a bluetooth, y buscaré mi Nexus 4…

Comprobemos si está arrancado el daemon de bluetooth:

pi@raspberrypi ~ $ /etc/init.d/bluetooth status
[ ok ] bluetooth is running.

Perfecto, está en funcionamiento. Este comando también nos permite administrar el daemon de bluetooth, dando posibilidades para arrancarlo (start), pararlo (stop), reiniciarlo (restart) y forzar un redescubrimiento de dispositivos cercanos (force-reload).

Ahora escaneamos en busca de dispositivos activos:

pi@raspberrypi ~ $ hcitool scan
Scanning ...
        XX:XX:XX:XX:XX:XX       Nexus 4 Jormc
        00:13:6C:9E:32:8F       n/a
        88:44:F6:5C:5C:44       Nokia 208
        B0:5C:E5:FD:99:47       Nokia 2720a-2
        B4:74:9F:8F:CE:D0       MRAA-PC

Y ahí está, el listado de dispositivos, con su respectiva mac y el nombre del dispositivo. El mío es el Nexus 4 Jormc. El resto es de otros usuarios.

En este punto, algo muy interesante que podemos probar es a hacer un ping al dispositivo que nos interesa, vía mac (cosa extraña…). Y digo interesante, ya que si pensamos un poco mas allá, y en algún momento desarrolláis en c, shell o python, os puede resultar muy útil para saber si un dispositivo específico está vivo… Cuando tratemos, más adelante, cómo construir nuestra propia domótica con Arduino y Raspberry Pi, retomaremos este punto…

pi@raspberrypi ~ $ sudo l2ping -c 1 XX:XX:XX:XX:XX:XX
Ping: XX:XX:XX:XX:XX:XX from PI:PI:PI:PI:PI:PI (data size 44) ...
0 bytes from 98:D6:F7:38:7C:37 id 0 time 13.16ms
1 sent, 1 received, 0% loss

Ahí está, vivito y coleando el Nexus 4 (notad que no pongo mi mac real…). El comando lping2 es el encargado de ofrecernos información del dispositivo solicitado.

Bien, ahora ya podemos emparejarlos, y cerrar el enlace Bluetooth. Es importante comentaros que este desarrollo de instalación quedará reflejado en vuestro gestor de ventanas (al menos así lo hace Raspbian), por lo que esta instalación vía consola también afecta al entorno gráfico. Por lo tanto, si os dirigís a start >> preferences >> bluetooth manager, podréis acceder al nuevo gestor de dispositivos Bluetooth y desde allí, de manera gráfica, hacer lo que a continuación os comento, y empezar a trabajar con los dispositivos de manera normal.

Bien, ejecutad el siguiente comando, y observad qué sucede, tanto en la pantalla como en la pantalla del móvil o dispositivo que estáis emparejando (ojo! las XX son los dígitos de la mac de mi dispositivo, poned las vuestras). Cuando se os solicite, insertad el 0000 como pin por defecto:

pi@raspberrypi ~ $ sudo bluez-simple-agent hci0 XX:XX:XX:XX:XX:XX
RequestPinCode (/org/bluez/2265/hci0/dev_XX_XX_XX_XX_XX_XX)
Enter PIN Code: 0000
Release
New device (/org/bluez/2265/hci0/dev_XX_XX_XX_XX_XX_XX)

Y ya tenemos ambos dispositivos emparejados! No ha sido demasiado difícil, ¿verdad?

Podemos desemparejarlo mediante remove:

pi@raspberrypi ~ $ sudo bluez-test-device remove XX:XX:XX:XX:XX:XX

Ahora, marcamos el dispositivo como trusted (“seguro”). No es obligatorio, esto es para poder emparejarlos automáticamente sin que se nos vuelva a pedir el pin, en caso contrario, cada vez que los emparejemos será solicitado.

pi@raspberrypi ~ $ sudo bluez-test-device trusted 98:D6:F7:38:7C:37 yes

Notad el yes del final. Para revocar la seguridad, bastará indicar no. A partir de este momento ya los tenemos emparejados y con conexión segura (estable), por lo que si ambos tienen el Bluetooth encendido al arranque, se conectarán de manera automática. Para ver el estado del emparejamiento, basta con no escribir yes o no al final. El resultado, 1 indica conectado, 0 no.

Ahora sólo queda conectarnos:

pi@raspberrypi ~ $ sudo bluez-test-input connect 98:D6:F7:38:7C:37

Y si todo ha ido bien, podremos empezar a utilizar nuestros dispositivos emparejados.

Esto os puede servir para cualquier tipo d dispositivo, ya sea de audio, de entrada (teclado/ratón), móvil, etc…

Espero que os haya sido de interés.

Jordi

Share Button

Arduino: sensor de temperatura y humedad de bajo coste

En esta primera entrega de Arduino, he decidido presentaros un pequeño proyecto, muy simple (podríamos decír que se trata de un proyecto para principiantes) en el que veremos cómo capturar la temperatura y el nivel de humedad del ambiente a través de un sensor de bajo coste.

El sensor que utilizaremos es el DHT22, también conocido por AM2302 (podéis encontrar su datasheet en este enlace). Se trata de un sensor de bajo coste, pero con unas capacidades mas que aceptables para proyectos con Arduino, gracias a su sencillez de uso y montaje. El precio aproximado es de unos 6€, gastos de envío incluidos, y podréis encontrarlo en eBay sin problemas. Existen otros sensores de la misma familia, como por ejemplo el hermano menor, el DHT11, que son algo mas baratos (quizá cueste la mitad), y también de menores prestaciones, como por ejemplo menos sensibilidad y precisión. Cuando buscaba un sensor para este proyecto, solo pensaba en la temperatura, pero se me cruzo ante los ojos el 11 y, poco a poco fui tirando del hilo, hasta llegar al 22. Sin duda puedo adelantaros que merece la pena invertir un poco mas y comprar el 22, aunque para el propósito de este proyecto, y si vuestra finalidad es la mera instrucción en este campo de los sensores, quizá el hermano pequeño cumpla mas que de sobra con vuestras expectativas.

Bien, no entraré en mas detalles sobre este estupendo sensor, podéis encontrar más información al respecto por la web sin mayor problema. Simplemente comentaremos los principios básicos de su funcionalidad.

DHT22

 

Según el esquema anterior, el patillaje del DHT22 se observa desde la parte frontal, de modo que la patilla 1 (izquierda) es la alimentación, de 3,3V a 6V DC, la 2 es la patilla de datos, y la 4 es tierra. La 3 no se utiliza, por lo que puede quedar al aire sin problemas. En algunas webs he podido leer que es posible conectar el 3 a GND también.

Internamente monta un sensor polímero capacitivo para la humedad y el transistor DS18B20 para la temperatura, capaces de ofrecer lecturas digitales en el pin 2. La lectura es bastante precisa y no necesita calibración. Pero aún mejor, está preparado para ser conectado directamente a la alimentación y para obtener la señal directamente en un solo hilo, puesto que incluye una resistencia pull-up conectada desde el DATA hasta VDD, con lo que el conexionado es directo. Esto favorece el echo de poder utilizarlo en proyectos con Arduino de manera directa y muy sencilla.

A continuación os muestro el detalle de sus características:

  • Alimentación: de 3,3 a 6V DC
  • Rango de medida: 0 – 100% HR, -40 a 125ºC
  • Sample rate: 0.5Hz (1 lectura cada 2s mínimo)

Lectura de datos

Vamos al lío. A continuación os muestro la conexión básica. En esta primera versión la lectura de los datos la mostraremos por el canal serie, de modo que es fácilmente explotable:

Como véis, no es necesario ningún componente electrónico extra. Para este montaje hemos utilizado el Arduino (puede servir cualquir versión, dada la sencillez del esquema), una protoboard y el DHT22.

Conexionado:

  • Cableado rojo: alimentación +5V, del Arduino a la pata 1 del DHT22
  • Cableado negro: GND, del Arduino a la pata 4 del DHT22
  • Cableado naranja: DATA, del pin 2 (entrada / salida digital, interrupción externa) a la pata 2 del DHT22

Bien, una vez tenemos realizado el conexionado, vamos a ver cómo leemos las medidas del DHT22. Vamos a por el código.

Lectura de datos, explotación vía serie

El primer montaje que vamos a hacer es el mas simple y el primero que piensa uno en probar: lectura del dato, envío hacia la salida serie de Arduino (así podremos visualizarla desde el IDE fácilmente).

Utilizaremos la libería DHTMaster: https://github.com/markruys/arduino-DHT

Y este es el código, basado en el propio ejemplo de la librería:

#include "DHT.h"

DHT dht;

void setup() {
  setupSensor();
  setupSerial();
}

void loop() {
  // Tiempo de espera entre lecturas
  // El mínimo, 2 sgundos
  delay(dht.getMinimumSamplingPeriod());

  // Obtenemos los datos desde el sensor 
  // tras el tiempo de espera

  // Estado del sensor (OK/NOK)
  String estatus = dht.getStatusString();

  // Tanto por ciento de humedad
  float humidity = dht.getHumidity();

  // Temperatura en ºC
  float temperature = dht.getTemperature();

  // Temperatura en ºF
  float fTemperature = dht.toFahrenheit(temperature);

  // Escribimos a la salida serie
  writeToSerial(estatus,humidity,temperature,fTemperature);
}

void setupSensor() {
  // Inicializamos la lectura 
  // en el pin 2 de Arduino
  dht.setup(2);
}

void setupSerial() {
  // Inicializamos el canal serie
  // para escribir a 9600bps
  Serial.begin(9600);
  Serial.println("Estado\tHumedad (%)\tTemperatura (C)\t(F)");
}

void writeToSerial(String estatus, float humidity, float temperature, float fTemperature) {
  Serial.print(estatus);
  Serial.print("\t");
  Serial.print(humidity, 1);
  Serial.print("\t\t");
  Serial.print(temperature, 1);
  Serial.print("\t\t");
  Serial.print(fTemperature, 1);
  Serial.println();
}

A continuación os explico el programa. No voy a entrar en detalles de la librería, dado que podéis descargarla y consultarla. Desgraciadamente no es el objetivo de este post.

He intentado que el código sea autocontenido, pero a grandes rasgos, lo que hace es:

  • Inicializamos el pin de lectura del sensor, pin 2 del Arduino (la librería lo configura como trigger de interrupción y lectura digital) (línea 37)
  • Inicializamos la salida serie a 9600bps y escribimos una cabecera (líneas 43 y 44)
  • Una vez ya dentro del loop, realizamos una espera del mínimo de segundos posibles, 2, entre lectura y lectura (línea 13). Si lo deseáis, podéis indicar vosotros el tiempo que necesitéis, en milisegundos.
  • Obtenemos los datos enviados por el sensor cada 2 segundos, obteniendo en cada caso el dato deseado: estado de la lectura como OK/NOK (línea 19), % de humedad como float (línea 22), temperatura en ºC como float (línea 25) y finalmente la temperatura en ºF como float (línea 28)
  • A continuación, escribimos estos datos por el canal serie (línea 31)

Y con esto ya tenemos nuestra primera versión del sensor de humedad y temperatura.

Si compiláis el programa, y abrís el monitor serie del IDE, veréis que Arduino empieza a ponerse en marcha, y cada 2 segundos lanza los datos a la salida (notad que parpadea el led naranja de TX):

Esta es una captura de mi monitor serie. Como podéis observar, tengo una temperatura de 23ºC y una humedad de aproximadamente un 50%. ¿No está mal no? Tengo buena calefacción…

Antes de finalizar este apartado, quiero recordaros que estamos haciendo uso de esta estupenda librería que nos permite olvidarnos de configurar el sensor, ya que lo hace de manera automática. Eso es un gran logro, ya que nos desinhibe totalmente de la capa de comunicación. También quiero comentaros que, como os decía al principio, podréis hacer uso de este código tanto para el DTH22 como para el DTH11, pero os informo que el tiempo mínimo de lectura del 11 es 1 segundo, en contra de los 2 del 22.

Mejora: salida a pantalla

Bien, lo majo de estas cosas es tener un aparatito que nos indique en cada instante toda esta información de manera más llamativa, más gráfica, si cabe. Es lo que os propongo a continuación. Vamos a mejorar la salida, enviando los datos a una pantalla LCD de 128×64 px. En mi caso se trata de una pantalla con chipset ST7920 y controlador serie de 3 hilos (VDD, GND y SDATA).

Como podéis observar, el pinout de mi pantalla no está muy bien definido. Eso es porque no dispongo del diseño de mi controlador serie en el Fritzing para dibujarlo. Para los interesados, os puedo decir que la compré por eBay y que es una SainSmart con controlador serie. Es la mas barata que pude encontrar y que fuera con controlador serie. Venía con una shield de expansión para Arduino UNO. Salió por unos 16€ gastos de envío incluidos.

El pinout es el siguiente:

  • Cable morado: pin 16, TX2 de Arduino, SID de la pantalla
  • Cable amarillo: pin 17, RX2 de Arduino, CS de la pantalla
  • Cable verde: pin 18, TX1 de Arduino, SCK de la pantalla

La librería de control de pantalla es la estupenda u8glib (http://code.google.com/p/u8glib) que nos permite controlar infinidad de modelos de pantallas y chipsets, a demás de tener un gran juego de fuentes disponibles. Una vez mas, y debido a que no quiero extenderme demasiado, no puedo entrar en detalles, pero si la descargáis veréis que es muy fácil de importar en vuestro proyecto.

Este es el código:

 

#include "DHT.h"
#include "U8glib.h"

DHT dht;
U8GLIB_ST7920_128X64_4X u8g(18, 16, 17);

float maxTemperature;
float minTemperature;
float maxHumidity;
float minHumidity;

void setup() {
  setupVariables();
  setupSensor();
}

void loop() {
  delay(dht.getMinimumSamplingPeriod());

  String sensStatus = dht.getStatusString();
  float temperature = dht.getTemperature();
  float humidity = dht.getHumidity();

  calcMinMax(sensStatus, temperature, humidity);

  // picture loop
  u8g.firstPage();
  do {
    writeToLDCD(sensStatus, temperature, humidity);
  } while ( u8g.nextPage() );
}

void setupVariables(void) {
  maxTemperature = 0.0;
  minTemperature = 0.0;
  maxHumidity = 0.0;
  minHumidity = 0.0;
}

void setupSensor(void) {
  dht.setup(2); // data pin 2
}

void calcMinMax(String sensStatus, float temperature, float humidity) {
  if (maxTemperature < temperature) {
    maxTemperature = temperature;
  }

  if (minTemperature == 0.0) {
    minTemperature = temperature;  
  }

  if (minTemperature > temperature) {
    minTemperature = temperature;
  }

  if (maxHumidity < humidity) {
    maxHumidity = humidity;
  }

  if (minHumidity == 0) {
    minHumidity = humidity;  
  }

  if (minHumidity > humidity) {
    minHumidity = humidity;
  }
}

void writeToLDCD(String sensStatus, float temperature, float humidity) {
  // Parte superior
  u8g.setFont(u8g_font_fub20);
  u8g.setPrintPos(34, 25);
  u8g.print(temperature);

  u8g.setFont(u8g_font_helvR08);
  u8g.setPrintPos(107, 11);
  u8g.print("o");

  u8g.setFont(u8g_font_helvB12);
  u8g.setPrintPos(113, 17);
  u8g.print("C");

  // Humedad
  u8g.setFont(u8g_font_6x12);
  u8g.setPrintPos(66, 38);
  u8g.print(humidity);
  u8g.setPrintPos(98, 38);
  u8g.print("%");

  // Parte inferior
  u8g.setFont(u8g_font_baby);

  // Temp. máxima
  u8g.setPrintPos(5, 52);
  u8g.print("T. max: ");
  u8g.setPrintPos(35, 52);
  u8g.print(maxTemperature);

  // Temp. mínima
  u8g.setPrintPos(5, 62);
  u8g.print("T. min: ");
  u8g.setPrintPos(35, 62);
  u8g.print(minTemperature);

  // Humedad máxima
  u8g.setPrintPos(70, 52);
  u8g.print("H. max: ");
  u8g.setPrintPos(100, 52);
  u8g.print(maxHumidity);

  // Humedad mínima
  u8g.setPrintPos(70, 62);
  u8g.print("H. min: ");
  u8g.setPrintPos(100, 62);
  u8g.print(minHumidity);
}

El código, una vez mas, es bastante sencillo. La base es la misma que en el caso anterior: inicializamos el sensor y obtenemos los datos. Esta vez, en vez de llamar a la escritura por serie en el loop, lo que hacemos es llamar a una rutina que va rellenando el contenido de la pantalla. Lo mas difícil en esta mejora fue la de manipular las posiciones de las cadenas de texto a la hora de escribir por pantalla. Es un tanto tosco, pero con unas cuantas horas se pudo hacer y obtener unos resultados bastante llamativos.

También se han añadido 4 variables mas que nos permiten almacenar las temperaturas máxima y mínima de histórico, así como los porcentajes de humedad, máximos y mínimos. A cada paso de loop, escribimos por pantalla y actualizamos dichos valores.

Os dejo una imagen del proyecto final, en pleno funcionamiento:

IMG_20131201_212631

IMG_20131201_214341

IMG_20131201_214351

Espero que os haya parecido interesante.

Jordi

Share Button

RasPI: Bot Twitter

Hoy en día es extraño aquél que no dispone de una cuenta de Twitter. Esta red social se ha convertido en el máximo exponente de las comunicaciones. Se emiten millones de mensajes cada segundo, se habla de millones de temas al mismo tiempo, se genera spam, publicidad, cualquier cosa que sea publicable es digna de ser escrita a través de Twitter. Y no en vano se ha convertido en el mejor sistema de mensajería corta en la actualidad.

Muchos diréis “para qué quieres conectar la Pi a Twitter”… Bien, es difícil de explicar, simplemente lo voy a hacer, porque me ha parecido interesante ver como hay cientos de Pi’s en todo el mundo transmitiendo el mismo mensaje:

Mensaje de ejemplo

Si hacéis un par de búsquedas en Twitter por #RaspberryPi o #temperature, no es raro encontrarte con cosas de estas… Bien, si miramos un poco más allá, es solo el principio de un sistema autónomo de información o publicación de datos de manera automática. Imaginad, poder consultar el estado de un depósito, información del espacio libre de un párking público o, símplemente, una nueva vñia de publicación de noticias… Cualquier cosa que te puedas imaginar, y gestionada por un sistema de bajo coste y buen rendimiento.

El procedimiento es sencillo, instalaremos Python en nuestro sistema y un cliente o gestor de publicaciones en Twitter a través de esta tecnología. ¿Por qué? Porque Python es sencillo de usar, liviano y extremadamente extendido en el mundo Linux y Pi.

Partiremos de la premisa de que disponéis de Python en vuestra Pi (sino, podéis consultar mi anterior post: RasPi: Instalación de Python

Comencemos.

Actualizar el sistema

Como siempre, antes de seguir, debemos actualizar nuestro sistema:

pi@raspberrypi ~ $ sudo apt-get update
pi@raspberrypi ~ $ sudo apt-get upgrade

Así nos aseguramos de que nuestro sistema está al día.

Instalación de Twython

A continuación instalamos Twython (http://twython.readthedocs.org/en/latest/), un cliente de Twitter en modo consola y escrito en Python:

pi@raspberry ~ $ sudo pip install twython

tras esto, ya tenemos disponible nuestro cliente de Twitter mediante Python.

Configuración de Twython

Para poder utlizar Twython es necesario asociar nuestra cuenta de Twitter con una aplicación externa. Esta aplicación es la encargada de redirigir el flujo de twits hacia Twitter. Accede a esta url: https://dev.twitter.com/apps y accede mediante la cuenta que usarás con Twython.

https://dev.twitter.com/apps

https://dev.twitter.com/apps

Accedemos y clicamos en el botón “Create a new application”, tras lo cuál obtendremos la siguiente pantalla:

https://dev.twitter.com/apps/new

https://dev.twitter.com/apps/new

Informad los siguientes datos con algo parecido:

  • Name: RasPi Bot
  • Description: Cliente Twitter autónomo para raspberry Pi vía Twython
  • Website: www.TUWEB.com (aquí debes indicar una url en la que debe estar publicada la política de uso de tu aplicación, es obligatorio…)
  • Callback URL: no es necesario, es la url dónde se nos redirigirá una vez iniciada sesión… no es muy útil en nuestro caso…

Bien, una vez rellenados, aceptad las políticas de uso y rellenad el captcha…

https://dev.twitter.com/apps/new

https://dev.twitter.com/apps/new

Y tras la creación, obtenemos los resultados que a continuación os muestro:

Aplicación creada

Tomad buena nota de los resultados, ya que los necesitaremos para configurar nuestro cliente posteriormente…

Sólo nos queda una cosa que cambiar, y es el modo de acceso que tendremos a la aplicación. Dado que lo que deseamos es que nuestra Pi pueda escribir twits, hemos de cambiar los permisos, indicando lectura / escritura. Para ello, id a la parte superior de esa pantalla, clickad en Settings y, en el apartado de Application Type, marcad Read and Write:

Modo lectura / escritura

Ahora ya está todo configurado. Bajad hasta abajo de la pantalla y clickad sobre Update this Twitter application’s settings.

Bien, y de nuevo en la pestaña Details, bajamos a bajo del todo y clickamos sobre Create my access token, que lo que hará será activar finalmente nuestra aplicación:

Create access token

El resultado lo necesitamos en el siguiente punto. Veréis que indica que hay que esperar unos minutos antes de que se publique el token. Bien, recordad pasar de nuevo por esta página mas tarde, ya que necesitaremos esta información en breve…

Acess token

Creación del script Python

Una vez que tenemos dada de alta nuestra aplicación y asociada a nuestra cuenta de Twitter, es el momento de hacer uso de la misma. Para ello, generaremos un script muy sencillo en Python que hará uso de la librería de Twython. De este modo, lo que haremos será loguearnos en el sistema de Twitter, mediante los datos que hemos generado anteriormente, y enviaremos un mensaje de prueba desde consola.

Empecemos por crear el script:

pi@raspberrypi ~ $ mkdir TwitterBot
pi@raspberrypi ~ $ cd TwitterBot
pi@raspberrypi ~/TwitterBot $ nano TwitterBot.py

Y añadimos el siguiente contenido:

#!/usr/bin/env python
import sys
from twython import Twython
CONSUMER_KEY = 'XXXX'
CONSUMER_SECRET = 'XXXX'
ACCESS_KEY = 'XXXX'
ACCESS_SECRET = 'XXXX'

api = Twython(CONSUMER_KEY,CONSUMER_SECRET,ACCESS_KEY,ACCESS_SECRET) 

api.update_status(status=sys.argv[1])

Ahora es el momento de utilizar cada uno de los datos generados en la primera parte de este mini tutorial:

  • CONSUMER_KEY: Consumer key generada en la aplicación Twitter
  • CONSUMER_SECRET: Consumer secret generada en la aplicación Twitter
  • ACCESS_KEY: Access token generado en el último paso
  • ACCESS_SECRET: Access token secret generado en el último paso

Test de funcionamiento

Tras esto, ya podemos realizar la primera prueba.

pi@raspberrypi ~ $ python TwitterBot.py 'Hello World from #RaspberryPi via @jormcpi'

Y vemos que… 🙂

Tuit de test

Como podemos ver, el tuit ha sido publicado correctamente. Cabe destacar que es muy recomendable no abusar del uso de la cuenta desde la aplicación, ya que Twitter puede decidir que se está usando un Bot real (que es cierto) y cancelarla, por no cumplir con los requisitos necesarios para poder hacer uso de la misma (ser una persona física).

A partir de aquí dejo a la elección e imaginación de cada uno el hacer uso de este recurso de la mejor manera que crea conveniente. En futuras entradas os explicaré cómo publicar el estado de nuestra Pi de manera autónoma y con una cadencia temporal definida. Para ir abriendo boca, os dejo como ejercicio pensar en la relación que se puede hacer entre la llamada a este sencillo script compaginado con el uso de Cron, llamadas a sistema, etc…

Espero que os haya servido de ayuda y entretenimiento. Cualquier duda, ya sabéis.

Suerte!

Jordi

Share Button

Related Images:

RasPi: Instalación de Python

Python es uno de los lenguajes de programación más extendidos en el mundo de la Raspberry Pi. Permite de manera muy sencilla y directa acceder a los recursos del sistema y realizar tareas complejas con poco trabajo. Actualmente es uno de los principales lenguajes de programación interpretados y mas extendidos, gracias a su poco peso y complejidad.

La web oficial de Python es http://www.python.org/.

Bien, vamos al lío.

Actualizar el sistema

Como siempre, antes de seguir, debemos actualizar nuestro sistema:

pi@raspberrypi ~ $ sudo apt-get update
pi@raspberrypi ~ $ sudo apt-get upgrade

Así nos aseguramos de que nuestro sistema está al día.

Instalación

Instalamos un sistema de herramientas que nos ayudarán a realizar una instalación de Python rápida y sencilla: Python Setup Tools  (https://pypi.python.org/pypi/setuptools):

pi@raspberrypi ~ $ sudo apt-get install python-setuptools

Posteriormente, instalamos Python (Pip) desde la PyPI, Pyhton Package Index, mediante las Setup Tools:

pi@raspberry ~ $ sudo easy_install pip

Ahora ya tenemos el sistema actualizado y la última versión de Python instalada.

Para hacer un test rápido podemos escribir algo como:

pi@raspberrypi ~ $ python
Python 2.7.3 (default, Jan 13 2013, 11:20:46)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print 'Hola Mundo'
Hola Mundo
>>>

Bien, un bonito print del archi conocido Hello World…

 

Disfrutadlo.

Jordi

Share Button

Related Images:

RasPi: Java y Tomcat en RaspberryPi

Bueno, tras un largo tiempo de inactividad, volvemos a la carga.

Esta vez vamos a ver cómo descargar, instalar y utilizar Java y Tomcat en nuestra RaspberryPi. El tema “rendimiento” ya es otro cantar, y yo no voy a entrar en ese tema. Si sigues este mini tutorial, podrás comprobarlo por ti mismo…

NOTA: parece ser que las últimas versiones de Raspbian ya incluyen el JDK. Yo por si acaso, os explico cómo descargarlo e instalarlo de manera muy sencilla.

Al lío.

Descarga e instalación simple de JDK 7

Nada del otro mundo. Como en otras ocasiones, antes de nada actualizamos nuestro sistema:

pi@raspberrypi ~ $ sudo apt-get update
pi@raspberrypi ~ $ sudo apt-get upgrade

Tras esto ya tenemos el sistema al día. Ahora vamos a por el JDK…

pi@raspberrypi ~ $ sudo apt-get install oracle-java7-jdk

Sed pacientes… tras un ratito, la pi nos indicará que ya ha finalizado la descarga y tendremos JAVA en nuestro sistema, sin mayor problema.

Para probar, ya sabéis:

pi@raspberrypi ~ $ java -version
java version "1.7.0_40"
Java(TM) SE Runtime Environment (build 1.7.0_40-b43)
Java HotSpot(TM) Client VM (build 24.0-b56, mixed mode)

Bien, como véis ya tenemos la 1.7 instalada.

Descarga e instalación de Tomcat

Apache tomat (aquí) no se encuentra en los repositorios de apt-get. Por ese motivo, debemos descargarlo desde alguno de sus servidores o mirrors. En este caso, yo lo he hecho de este modo:

pi@raspberrypi ~ $ wget http://apache.rediris.es/tomcat/tomcat-7/v7.0.47/bin/apache-tomcat-7.0.47.tar.gz
--2013-11-18 20:50:58--  http://apache.rediris.es/tomcat/tomcat-7/v7.0.47/bin/apache-tomcat-7.0.47.tar.gz
Resolviendo apache.rediris.es (apache.rediris.es)... 130.206.1.5
Conectando con apache.rediris.es (apache.rediris.es)[130.206.1.5]:80... conectado.
Petición HTTP enviada, esperando respuesta... 200 OK
Longitud: 8234674 (7,9M) [application/x-gzip]
Grabando a: apache-tomcat-7.0.47.tar.gz

100%[==========================================================================================================================>] 8.234.674    837K/s   en 11s

2013-11-18 20:51:09 (720 KB/s) - apache-tomcat-7.0.47.tar.gz

Bien, ya tenemos Tomcat. Vamos a descomprimirlo…

pi@raspberrypi ~ $ tar xzf apache-tomcat-7.0.28.tar.gz

Y ahora a configurar el usuario system para poder ejecutar Tomcat, con password raspberrypi:

pi@raspberrypi ~ $ cd apache-tomcat-7.0.47/conf
pi@raspberrypi ~ $ vim tomcat-users.xml

Y añadimos una línea de usuario:

<user username="system" password="raspberry" roles="manager-gui"/>

Ya solo nos queda arrancar tomat:

pi@raspberrypi ~ $ cd apache-tomcat-7.0.47/bin/
pi@raspberrypi ~/apache-tomcat-7.0.47/bin $ ./startup.sh
Using CATALINA_BASE:   /home/pi/apache-tomcat-7.0.47
Using CATALINA_HOME:   /home/pi/apache-tomcat-7.0.47
Using CATALINA_TMPDIR: /home/pi/apache-tomcat-7.0.47/temp
Using JRE_HOME:        /usr
Using CLASSPATH:       /home/pi/apache-tomcat-7.0.47/bin/bootstrap.jar:/home/pi/apache-tomcat-7.0.47/bin/tomcat-juli.jar

Bien, ya véis el resultado… Ya sabéis lo que significa… 😉

Captura Tomcat

Captura Tomcat

 

Pues nada, suerte!!!

Jordi

Share Button

Vídeo: Funifira 2013 (Gelida)

El siguiente vídeo os muestra cómo se coordina y se monta un encuentro de módulos escala N, según normativa de Plataforma-N.

El vídeo es una sucesión de fotos y vídeos grabados por mí en la pasada Funifira de Gelida, durante los días 9 a 11 de noviembre.

Espero que sea de vuestro agrado.

Jordi

 

Share Button

Vídeo: TALGADA 2013

Os dejo un vídeo que he editado con las fotografías tomadas el pasado 26/10/2013 en l’Associació d’Amics del Ferrorcarril de Montcada i Reixac.

Espero que os guste.

 

Jordi

Share Button

Oracle: otorgar permisos a un usuario sobre un schema específico

Recientemente me he encontrado con la necesidad de tener que acceder a un schema “ajeno” desde un usuario en Oracle. El problema es que no me pasaron los scripts que otorgaban los privilegios apropiados para ello… Como se trataba de un trabajo de desarrollo y prueba en local, decidí “saltarme” las normas y entrar a lo duro en el schema ajeno.

Os explico cómo, no es demasiado difícil, y no es necesario ser sysdba para conseguirlo: el usuario propietario del schema al que se desea acceder otorga los privilegios deseados al otro usuario, símplemente. La única necesidad, y esa si es importante, es que el usuario del schema que se va a compartir, debe tener suficientes privilegios para otorgarlos.

Veamos el código (debe ejecutarlo el usuario propietario del schema que se desea compartir):

BEGIN
    FOR t IN (SELECT * FROM user_tables) 
    LOOP   
        EXECUTE IMMEDIATE 'GRANT SELECT ON ' || t.table_name || ' TO DEST_USER';    
    END LOOP;
END;

Rápidamente, lo que este código hace es, mediante un bucle, recorre todas las tablas del usuario que comparte el schema y otorga los privilegios seleccionados (en este caso solo SELECT) a cada tabla para el usuario DEST_USER (sustituir por el nombre del usuario al que deseamos otorgar los permisos).

Y esto es todo.

Espero haberos sido de ayuda.

Jordi

Share Button