domingo, 29 de enero de 2012

Serial Communication with Arduino (English Version)

Abstract

One of the main advantages of a micro is the chance we have of communicating with it via serial port.

In this article, and next we will have an idea of ​​what we can do, and some of the tools I have found interesting to interact with a microcontrollers, involving internet ...

Unless a micro is programmed with a standalone implementation, ie, that its operation is limited to actions that do not depend on external interaction (beyond digital or analog inputs) is not necessary to implement the mechanisms that this article describes. It is true that many applications do not require microcontrollers to get outside the inner environment, but it is increasingly common to think of communication as a tool of interaction with applications designed for these environments. Consider the following example.
...
Arduino microcontroller communication type

If we have a house with panoramic windows (these that open by sliding horizontally), such that a person can enter smoothly through when opened, and we often like to go on vacation, we will have a security problem. The probability of breaking into our home at that time in the house alone is very high.

For someone who wants to design your security system, first of all probably think of placing motion sensors to trigger a very noisy alarm when an intrusion into the residence is detected.This may be a solution, but the alarm will alert only to the immediate surroundings of the house, and intruders.

But we can also think of a silent security system emiting an alarm message to the house's owner via the Internet, sending a text message alert to a receiving means, either email, client chat (IM) or twitter!.

Another example of remote communication is the possibility of creating a system that could  controls lights or appliances in our home. These can be automated from the microcontroller defining scheduled events for turning on or off lights, moving a sun-oriented solar cell efficiently, to power a window for the entry of light according to ambient brightness or just turn on air conditioning in our room near the hour of our arrival.

With this last example, what if we come home early?. We could communicate with our microcontroller using the cellular using our messenger by sending a message like the following:

AC: turn on

In this way, and through the proper software, this message can be received and executed online.

To perform tasks like explained above, we must start from the simple to the complex. The first thing to know is that with microcontrollers like the Arduino, pinguino, teensy, etc.. we can communicate to a server via serial port .

With arduino or teensy serial communication is established via USB interface from which we have to connect the microcontroller to the computer. Once serial port is initialized from the microcontroller environments, linux / unix directory is mapped to / dev / ttyXXXn that will give us the opportunity to send or receive information.

The following code, using Arduino, defines the sequential output of a message to our computer's serial port.

int i = 0;
void setup ()
{
   Serial.begin (9600);
}
void loop ()
{
   Serial.print ("test message");
   Serial.println (++ i);
   delay (1000);
}

In block setup () we initialize the serial port to 9600 baud with Serial.begin (9600). In the block loop () we send the message via serial port followed by a number sequencially updated by ++ i.

From the computer we will see this output if we properly interrogate the port mapping in /dev/ttyACMn.Where n> = 0.

For this example the port was mapped to / dev/ttyACM0. In my case I use ubuntu, but for any Linux / MAC should be very similar.

When the microcontroller is plugged into any USB port on our computer it can be accessed via command line from a terminal or through a program made for this purpose. A third option is to create our own program of reading and / or writing to the serial port. This last option is appropriate if we want to interact withthe microcontroller to get information or instruct it to perform any action.

For our simple example, we can initially examine the serial port using the tool that comes with the Arduino IDE or through gtkterminal or minicom.


From the microcontroller you can also read from the serial port so there is the posibility to make decisions and run actions according to the input.

The following program simply read the serial input and return the string obtained by detecting the end of line.

char character;
byte i = 0;
char string [100];
void setup ()
{
   Serial.begin (9600);
}
void loop ()
{
   if (Serial.available ())
   {
     caracter=Serial.read();
     if (character == 10)
     {
       string [i ++]=' \ 0 ';
       i = 0;
       Serial.println (string);
     }
     else
       string [i ++] = character;
   }
}

In setup() block we initialize the port, then in the loop()  block we check for the port buffer using Serial.available ().

If there are characters available Serial.read sequentially reads each one. If we detect the end of line caracter (10) we add it to the string and reset the counter, sending back the string to the port.

If the character received is not an end of line (10) then we attach it to the end of the string updating the counter.


Now let's see how to use the latter program to bring to power on or off to the air conditioning in the second example shown in this article.

# Include string.h 
# Define ON 1 
# Define OFF 0 
char caracter; 
byte i = 0; 
char string [100]; 
AC_Action void (int action) 
{   
   if (action == ON)   
   { 
     Serial.println ("Turning AC ON ...");
   / / Action to light
   / / Wait for result
       delay (500);
       Serial.println ("Air conditioning was activated ... Status OK");
   }   
   if (action == OFF)   
   {     
     Serial.println ("Turning OFF AC ...");
   / / Shutdown action
   / / Wait for result
       delay (500);
       Serial.println ("Air conditioning was deactivated ... Status OK");
   }
} 
void setup () 
{ 
   Serial.begin (9600); 
} 
void loop () 
{   
   if (Serial.available ())   
   {     
      caracter= Serial.read();
       if (caracter == 10)
       {
           string [i ++]=' \ 0 ';
           i = 0;
           if (strcmp (string, "AC: On"))
             AC_Action (ON);
           if (strcmp (string, "AC: OFF"))
             AC_Action (OFF);
       }
       else
         string [i + +] = caracter;
     }
}

We have created a procedure depending on the action parameter to turn on or off the air conditioning, assuming we have a device that controls the AC connected to the microcontroller. In our case the microcontroller, via serial port, return the message on and off accordingly.

The block loop () maintains the same pattern, except that when you match a specific string runs AC_Action function () passing the parameter set ON or OFF at the beginning of the program.

VIDEO: Serial Communication 3

The next step will be communicating ourselves from outside to PC using several means to interact with the microcontroller.

In future articles we will continue to explore possibilities for communication, interaction and execution.

Read More......

sábado, 21 de enero de 2012

Comunicación vía email con Arduino

Abstract

(go to English Version)

En el capítulo anterior vimos como comunicarnos con el micro a través del chat de msn. Muy útil si queremos ejecutar órdenes  desde un cliente móvil o desde otro PC a ciudades de distancia. ref: Comunicación con microControladores tipo Arduino. Enviando órdenes al micro a través del chat, email, pachube o twitter

En este capítulo exploraremos la forma de hacerlo por medio del correo electrónico, lo cual permite tanto enviar, como recibir información del micro por un medio utilizado muy comúnmente en la actualidad.

Código Arduino:  led-1.pde
Download: SCRIPT
VIDEO: Comunicación por email con Arduino

Comunicación con el Arduino vía correo Electrónico

Lo realmente interesante del email es la capacidad de darle formato a la información que podemos enviar desde el micro al PC y luego al usuario. De esta forma podemos crear reportes de muy buen aspecto para informar del status de, por ejemplo, los puntos de seguridad de una casa particular, establecimiento comercial, fábrica, oficina, etc.

Dentro de mi búsqueda por opciones que permitiesen esta capacidad, de manera simple, encontré un add-on de thunderbird llamado Mailbox-Alert. Este add-on se instala de forma muy sencilla (ver enlace) y permite configurar nuestro thunderbird para identificar mensajes entrantes, para luego ejecutar scripts creados por nosotros para ejecutar diferentes tareas.

La información contenida en este artículo no solo aplica para la comunicación con un microcontrolador, sino que puede ser empleada en diversas situaciones para automatizar tareas que requiramos. Por ejemplo, si necesitamos interrogar nuestro servidor por algún evento, o información de utilización del mismo.

Por lo pronto veamos como configurar nuestros componentes para activar la comunicación vía email. A continuación los pasos a seguir para ejecutar esta configuración:

  1. Programación del micro vía Arduino IDE
  2. Creación del script que enviará los comandos a través del puerto serial
  3. Configuración de Mail-Alert el cual enlaza una regla con el script que creamos ateriormente

El diagrama de flujo mostrado indica como un mensaje entrante es filtrado por thunderbird. En el caso que el subject del mensaje haga match con las condiciones indicadas en el filtro, este activará una regla definida en el add-on Mail-Alert la cual ejecutará el script que hace la interfaz con el puerto serial y hacia el micro. Este script también es capaz de responder al remitente del correo original con las acciones tomadas.

(1) Programación del micro

Al igual que el artículo anterior estaremos utilizando una configuración de 4 leds conectados al micro. El firmware (programa) que utilizaremos es el mismo que en el artículo anterior el cual puede ser bajado aquí.

(2) Script de interacción con Arduino en python

Hasta ahora hemos programados nuestros scripts con ksh, el cual puede ejecutarse desde cualquier linux. Para aumentar la portabilidad hemos creado para este ejemplo un script en python el cual es multiplataforma.

Este script recibe como parámetros el contenido del subject del correo entrante, el remitente de dicho correo y el puerto serial con el cual se estará interactuando.

Este script también tiene interacción con algún cliente de correo que tengan instalado en sus PCs. En mi caso utilizo ssmtp por su simplicidad y efectividad. Como yo utilizo Ubuntu como sistema operativo, ssmtp hace el trabajo muy bien y les indico un link en donde se puede obtener información de como instalarlo.


Nuestro script hace uso de ssmtp haciendo una llamada al sistema operativo utilizando la libreria subprocess, la cual permite hacer un fork de una llamada al sistema operativo para ejecutar un comando, y además podemos hacerle llegar los parámetros indicados. El siguiente extracto muestra la rutina para enviar el correo de vuelta al remitente.

def send_email(mensaje):
    try:
        ssmtp = subprocess.Popen(('/usr/sbin/ssmtp', destinatario), stdin=subprocess.PIPE)
    except OSError:
        print 'No se puedo iniciar sSMTP, por lo que el email no fue enviado'

    #pasamos el contenido del mail a traves del stdin
    ssmtp.communicate(cuerpo % (destinatario, remitente, mensaje))

    # Esperamos a que termine de enviar el correo
    ssmtp.wait()

Download: SCRIPT

(3) Configuración de Mail-Alert

Este paso es el que permite que todo funcione. Cuando llega un correo thunderbird a través de sus filtros permite redireccionar el mismo a una regla que definimos para Mail-Alert, el cual ejecutará el script que interactua con el Arduino.

(3.1) Creamos una regla en Mailbox-Alert
(3.2) Creamos un Filtro que direccione a la regla de Mailbox-Alert

Una vez configuradas todas las partes involucradas en el proceso podemos probar enviando un email a yadirganbot@gmail.com con las siguientes características.
  • El mensaje debe contener las instrucciones en el subject
  • El subject debe empezar con @;->
  • Se puede indicar más de un comando en el subject
  • Los comandos permitidos son:
    • ledon, ledoff (Enciende o apaga todos los leds)
    • ledNon, ledNoff: (1<N<4) (Enciende un led a la vez)
    • titilar (Ejecuta intermitencia de todos los leds)
    • secuencia1 (Ejecuta un led chaser de izquierda a derecha)
    • secuencia2 (Ejecuta un led chaser de derecha a izquierda)
    • pN, N>0 entero o decimal (indica una pausa en milisegundos)
    • xN, N>=1 (permite repetir un comando)
En este ejemplo vemos como enviamos una secuencia de comandos en el subject de un email cuyo destinatario es yadirganbot@gmail.com.

To: yadirganbot@gmail.com
Subject: @;-> x3 secuencia1 p.5 x3 secuencia2 p.5 titilar p.5 ledon p2 ledoff

Thunderbird a través del filtro creado detecta que la secuencia @;-> se encuentra en el subject del correo y lo envía a la regla creada en Mailbox-Alert. Por su parte Mailbox-Alert en su regla sabe que tiene que mostrar un pop-up indicando el remitente y el mensaje, además ejecutar el siguiente comando:

/home/ydirgan/SCRIPTS/mailboxAlert/led-1.py  %subject %sender /dev/ttyACM0

en el cual se le pasan como parámetros (%subject) el título del correo, el cual contiene los comandos. El remitente (%sender), y finalmente el puerto serial por donde el micro está conectado al PC.

El script led-1.py se ejecuta enviándole los comandos vía serial al micro, dejando huella en led-1.log y devolviendo el correo vía ssmtp al remitente.

En el video que verán a continuación se puede observar el ciclo de comunicación con el micro.







Read More......

domingo, 15 de enero de 2012

Comunicación con Arduino usando un cliente de mensajería

Abstract

(go to English Version)

En el artículo anterior vimos la teoría básica de como comunicarnos con el microcontrolador a través del puerto serial de nuestro PC. ref: Comunicación con microcontroladores tipo Arduino

En este artículo veremos lo básico para hacer que el micro responda a órdenes enviadas a través de un cliente de mensajería, correo electrónico, pachube o twitter.

Downloads: serialLed.pdeled1log.pyled-1.kshexternal
VIDEO: Paso a Paso

Sesión Interactiva: 
Agregar contacto vía messenger (msn) ydirganbot@hotmail.com y Verificar el broadcast del circuito montado para ver los leds AQUI.

Intrucción

Ya hemos visto como enviar o recibir información hacia y desde el micro utilizando el puerto serial. El paso a seguir es utilizar el micro para hacerlo reaccionar a órdenes enviadas a través de nuestro PC o analizar y reaccionar a información recibida del micro.

En una primera instancia estudiaremos la forma de hacer reaccionar al micro de acuerdo a las órdenes que le podamos enviar por el puerto serial. Inicialmente hicimos enviar directamente las órdenes a través del puerto utilizando la modalidad directa, pero la idea de fondo es poder utilizar alguna interfaz que nos haga el trabajo más sencillo.

Por ejemplo, trabajar con algún tipo de interfaz de comunicación, como un cliente de chat, correo electrónico, pachube o twitter, por nombrar los cuatro que vamos a explorar en este y los próximos 3 artículos.

Comunicación con el micro a través de messenger

Buscando extensamente en la Web por software gratuito para utilizar algún cliente de chat me encontré con centerIM. Esta aplicación es un cliente muy ligero de chat, el cual puede configurarse con una variedad de cuentas públicas como messenger, yahoo, etc.

REF1: CenterIM home
REF2: centerIM Installation

En la referencia anterior puede accederse la página del producto así como un muy buen artículo de como instalarlo en ubuntu.

La documentación que encuentran en la referencia 1 es muy amplia y con ella pueden configurar inicialmente el paquete. En mi caso yo lo configure con una cuenta que cree especialmente para este experimento.

Siendo un cliente de chat funciona como cualquier otro cliente de mensajería, pero con un adicional que encaja muy bien para nuestro objetivo. El centerIM permite programar scripts para ejecutar tareas de acuerdo al contenido de los mensajes entrantes. Con esta capacidad se pueden programar diferentes comportamientos de forma de enviar vía serial comandos al microcontrolador. Esto permite comunicarnos desde el messenger con el computador de la casa para por ejemplo ejecutar alguna tarea de activación de alarma, encender luces o apagarlas, etc.

Esta configuración se debe hacer a través de un script que debe copiarse en $HOME/.centerim y cuyo nombre debe ser external.

El formato del script external es muy simple.


%action         Acción a tomar de acuerdo a las siguientes condiciones

event           msg
# Reacciona solo a mensajes
proto           msn
# Solamente  para el protocolo messenger
status          online
# responde solo si el status de la cuenta es online
options         stdin stdout
# .. los comandos externos (abajo) leen de
# stdin, luego su salida stdout es enviada como una respuesta 
# a un usuario remoto
%exec
msg=`cat`
echo $(/home/ydirgan/.centerim/commTest.ksh "$msg")

%exec redirecciona el mensaje a un simple script que solo devuelve el mensaje por la misma vía.

#commTest.ksh
#!/usr/bin/ksh
msg=`echo $1 | tr a-z A-Z`;
printf "arduino-1 orden rebibida: $msg";

Al momento de recibir el mensaje, centerIM redirecciona la salida al script commTest.ksh, este recibe el mismo como un parámetro el cual lo convertimos en mayúsculas y lo devolvemos a centerIM por el stdout.

A partir de este simple ejemplo podemos modelar un pequeño script para encender/apagar 4 leds conectados a los pines digitales 0..3 de nuestro teensy.

A continuación los pasos que deberemos seguir:
  1. Crear un script ara el micro que responda a las órdenes enviadas vía serial
  2. Crear un script de logging del puerto serial
  3. Crear el script que es llamado desde "external", el cual contiene la lógica de ejecución
  4. Crear el script "external" para centerIM
(1) Script para el Microcontrolador

Este script responde a los comandos recibidos por el puerto serial del teensy (micro como el arduino).

El script enciende o apaga un led en el pin n (1<=n<=4). Espera por un caracter que esté disponible en el puerto serial. 

entrada serial = 1: enciende el led 1
entrada serial = 2: apaga el led 1
entrada serial = 3: enciende el led 2
entrada serial = 4: apaga el led 2
entrada serial = 5: enciende el led 3
entrada serial = 6: apaga el led 3
entrada serial = 7: enciende el led 4
entrada serial = 8: apaga el led 4

Una vez que descarguemos el programa debemos cargarlo en el micro. Una vez cargado podemos probar su comportamiento interactuando directamente conb el puerto, como se puede apreciar en el video al final del artículo.

Download:
 serialLed.pde
(2) Script de logging

Este script tiene como objetivo copiar cada línea de salida de /dev/ttyACM0 a un archivo.log y deberemos ejecutarlo en background para que se mantenga recopilando la salida del puerto.

ydirgan@pragma-systems:~/SCRIPTS/centerIM$ led1log.py /dev/ttyACM0 &
Download: led1log.py
(3) Script con la lógica de ejecución


El tercer script permite ejecutar las secuencias de los comandos que requerimos enviarle al micro. Con las reducidas instrucciones que definimos en el micro podemos desde este script aumentar las funcionalidades.

En este programa podemos encender o apagar leds individuales, pero también podemos encenderlos todos, apagarlos todos, hacer que titilen o que ejecuten una secuencia. Todo esto utilizando las primitivas que hemos programado en el micro.

Además de las instrucciones propias de ejecución, se ha programado una ayuda que puede obtenerse al tipear HELP desde la ventana de chat, y su resultado será:

arduino-1: este es una maquina de estado finita que permite interactuar con un microcontrolador tipo Arduino. Su uso esta destinado solo como ejemplo. El microcontrolador repondera cuando reconozca la orden a ejecutar. Se tienen 4 led, para encender y apagar cada uno de ellos. Los comandos que puedes utilizar son: ledNon, en donde n es el numero del led (1<=N<=4). ledNoff, en donde n es el numero del led (1<=N<=4). ledon, todos los leds se encenderan. ledoff, todos los led se apagaran. tilitar, todos los led titilaran 20 veces. secuencia1, todos los led encienden en secuencia (tipo led chaser) de izquierda a derecha. secuencia2, todos los led encienden en secuencia (tipo led chaser) de derecha a izquierda. help, muestra esta ayuda.

Download: led-1.ksh
(4) Script external para centerIM
Por último el script que ejecuta centerIM cuando le enviamos un mensaje. Este será el que dispare la ejecución del script led-1.ksh, que enviará nuestros comandos vía serial. El micro los procesará y responderá de acuerdo a la secuencia de comandos.


Download: external

Finalmente ejecutamos centerim desde nuestro terminal para activar el robot.

El video para mostrar la secuencia de pasos es el siguiente:


Para probarlo solo habría que agregar a ydirganbot@hotmail.com al messenger. Este responderá cuando esté online.

Read More......

miércoles, 11 de enero de 2012

Comunicación Serial con Arduino

Abstract

(go to English Version)

Una de las principales ventajas de un micro es la posibilidad que tenemos de comunicarnos con el mismo vía puerto serial.

En este artículo y próximos tendremos un acercamiento a lo que podemos hacer, y algunas de las herramientas que he encontrado interesantes para interactuar con un microcontrolador, involucrando internet...

A menos que un micro se programe con una implementación standalone, es decir, que se su funcionamiento se circunscriba a acciones que no dependan de la interacción externa (más allá de sus entradas digitales o analógicas), no será necesario ejecutar los mecanismos que en este artículo se describen. Es cierto que muchas de las aplicaciones de los microcontroladores no requieren asomarse a su entorno, pero cada vez es más común pensar en la comunicación como herramienta de interacción con las aplicaciones que diseñamos para estos ambientes. Para muestra, veamos el siguiente ejemplo.
...
Comunicación con microControladores tipo Arduino

Si poseemos una casa con ventanas panorámicas (de estas que se abren deslizándolas horizontalmente), tal que una persona puede entrar sin inconvenientes a través del espacio disponible una vez abiertas, y nos gusta salir a menudo de vacaciones, tendremos un problema de seguridad. La probabilidad que irrumpan en nuestro hogar en esos momentos en que la casa está sola será muy alta.

Para alguien que quiera diseñar su sistema de seguridad, en primera instancia seguramente pensará en colocar sensores de movimiento o apertura para activar una alarma muy ruidosa al momento que haya una intrusión en la residencia. Esto puede ser una solución, pero la alarma alertará solo al entorno inmediato a la casa, y a los intrusos.

Ahora bien, también podemos pensar en un sistema de seguridad silencioso al entorno inmediato a la residencia, pero que a través de un sistema de comunicación al exterior vía internet, envíe un mensaje de texto con la alerta a algún medio de recepción, sea email, chat client (messenger) o a twitter!.

Otro ejemplo de comunicación remota es, por ejemplo, la posibilidad de crear un sistema de control de luces y electrodomésticos en nuestro hogar. El mismo puede ser automatizado desde el micro definiendo un horario de ejecución de eventos para encender o apagar luces, mover una celda solar orientándola al sol de forma eficiente, motorizar una ventana para la entrada de luz de acuerdo a la luminosidad del entorno o simplemente encender el aire acondicionado de nuestra habitación cercano a la hora de nuestra llegada.

Con este último ejemplo, que tal si llegamos más temprano a casa?. Pudiéramos comunicarnos con nuestro micro utilizando nuestro celular inteligente a través de messenger enviando un mensaje como el siguiente:

AC: encender

De esta forma y a través del software adecuado, este mensaje puede ser recibido y ejecutado, en línea.

Como estos ejemplos, existen muchos más que solo la imaginación y la necesidad particular pueden producir.

Para realizar tareas como estas, debemos empezar de lo sencillo a lo complejo. Lo primero que debemos saber es que con los microcontroladores como el arduino, pinguino, teensy, etc. podemos comunicarnos a un servidor vía puerto serial.

Con arduino o teensy la comunicación serial se establece a través de la interfaz USB de la cual disponemos para conectar el micro al computador. Al inicializar el puerto serial desde el micro, en ambientes linux/unix se mapeará un directorio en /dev/ttyXXXn que permitirá enviar o recibir información.

El siguiente código define la salida secuencial de un mensaje al puerto serie de nuestro computador.

int i=0;
void setup()
{
  Serial.begin(9600);
}
void loop()
{
  Serial.print("mensaje de prueba: ");
  Serial.println(++i);
  delay(1000);
}

En el bloque setup() inicializamos el puerto serial a 9600 baudios con Serial.begin(9600). En el bloque loop() enviamos vía serial el mensaje seguido de un consecutivo el cual actualizamos secuencialmente con ++i.

Desde el computador podremos observar esta salida si interrogamos adecuadamente al puerto mapeado en /dev/ttyACMn. Donde n>=0.

Para este ejemplo el puerto fue mapeado contra /dev/ttyACM0. En mi caso utilizo ubuntu, pero para cualquier linux/MAC debe ser muy similar.

Cuando el micro es conectado a cualquier puerto USB de nuestro computador el mismo puede ser accedido vía línea de comando desde un terminal o a través de algún programa hecho para este fin. Una tercera opción es crear nuestro propio programa de lectura y/o escritura al puerto serial. Esta última opción es la adecuada si quisiéramos interactuar con el puerto para obtener información del puerto o instruir al micro a ejecutar alguna acción.

Para nuestro sencillo ejemplo podemos interrogar inicialmente al puerto utilizando el terminal serial que viene como herramienta del IDE de Arduino o a través de gtkterminal o minicom.

VIDEO: Comunicación Serial 1

Desde el micro podemos también leer desde el puerto serial y así poder tomar decisiones de que ejecutar de acuerdo a la entrada.

El siguiente programa permite simplemente leer la entrada serial y devolver la cadena de caracteres obtenida, detectando el fin de línea.

char caracter;
byte i=0;
char cadena[100];
void setup()
{
  Serial.begin(9600);
}
void loop()
{
  if (Serial.available())
  {
    caracter=Serial.read();
    if (caracter == 10)
    {
      cadena[i++]='\0';
      i=0;
      Serial.println(cadena);
    }
    else
      cadena[i++]=caracter;
  }
}

En el bloque setup() inicializamos el puerto, seguidamente en el bloque loop() chequeamos el buffer del puerto con Serial.available().

Si hay caracteres disponibles los leemos secuencialmente con Serial.read(). Si detectamos el fin de línea agregamos a la cadena de caracteres el caracter de fin de cadena y reseteamos el contador, enviando de vuelta la cadena de caracteres al puerto.

En caso que no sea un fin de linea (10) entonces vamos anexando a la cadena cada catacter recibido actualizando el indice i.

VIDEO: Comunicación Serial 2

Ahora veamos como utilizar este último programa para adecuarlo para accionar el encendido o el apagado el aire acondicionado del segundo ejemplo mostrado en este artículo.

#include string.h
#define ENCENDER 1
#define APAGAR 0
char caracter;
byte i=0;
char cadena[100];

void AC_Action(int accion)
{
  

    if (accion == ENCENDER)  
    {
        Serial.println("Encendiendo el Aire Acondicionado Principal... ");
        //Accion de encender
        //esperar resultado
        delay(500);
        Serial.println("Aire Acondicionado Encendido... Status OK");
    }   
    if (accion == APAGAR)  
    {    
        Serial.println("Apagando el Aire Acondicionado Principal... ");
        //Accion de apagado
        //esperar resultado
        delay(500);
        Serial.println("Aire Acondicionado Apagado... Status OK");
    
}
void setup()
{

    Serial.begin(9600);
}
void loop()
{
  

    if (Serial.available())  
    {    
        caracter=Serial.read();
        if (caracter == 10)
        {
              cadena[i++]='\0';
              i=0;
              if (!strcmp(cadena,"AC: Encender"))
                AC_Action(ENCENDER);
              if (!strcmp(cadena,"AC: Apagar"))
                AC_Action(APAGAR); 
        
        else
          cadena[i++]=caracter; 
      }
}

Hemos creado una procedimiento que dependiendo del parámetro acción encenderá o apagará el aire acondicionado, asumiendo que tenemos un dispositivo conectado al micro capaz de hacerlo. En nuestro caso el micro devolverá vía serial el mensaje de encendido y apagado correspondiente.

El bloque loop() mantiene el mismo esquema, solo que cuando se hace match con una cadena específica se ejecuta la función AC_Action() pasándole el parámetro ENCENDER o APAGAR definidos al principio del programa.

VIDEO: Comunicación Serial 3

El próximo paso va a ser comunicarnos desde el exterior del PC a través de diferentes medios para poder interactuar con el micro.

En próximos artículos seguiremos explorando posibilidades de comunicación, interacción y ejecución.
Read More......

domingo, 19 de junio de 2011

Entrada Analógica (Analog Input)

Hoy nos dedicaremos a interactuar con una entrada analógica, la cual a diferencia de una entrada digital (entrega anterior) permite leer un rango de valores. Estos valores representan voltaje, pero dentro del microcontrolador pueden ser representados por un rango de valores enteros, los cuales pueden ir de 0 a 255 o de 0 a 1024, etc., esto depende del tipo de procesador que estemos utilizando... por eso es muy útil obtener las especificaciones del micro y las funciones asociadas (en el lenguaje que escogiéramos) a la lectura de un puerto analógico.

La idea de un puerto analógico es leer de un puerto diferentes valores, lo cual permite tomar decisiones más amplias o interactuar con rangos que permiten realizar tareas diferentes.

En lo personal, cuando pienso en una entrada digital pienso en un switch on/off, y cuando pienso en una entrada analógica pienso en un potenciómetro, o cualquier dispositivo cuya salida oscile entre 0V y 5V.

Estos dispositivos (ejemplo un lm35 - termómetro digital) alimentándolos con 5V, pueden entregar al puerto en donde se conecten un rango de valores de acuerdo a las características con las cuales el dispositivo está diseñado.

Por ejemplo, un potenciómetro permite entregar al micro un rango de voltaje que depende del voltaje con el cual esté alimentado. Un termómetro digital, entregará un voltaje de acuerdo a la alimentación del mismo y a las condiciones de temperatura a la cual esté expuesto. En cualquier caso, siempre se obtiene un voltaje asociado a la lectura del dispositivo, y a través de este voltaje podemos tomar decisiones y ejecutar tareas.

El siguiente circuito conecta 8 leds a la plataforma de prototipado pinguino en los pines 0-7, que son puertos digitales. Un potenciómetro es conectado a los puertos GND,VCC del micro y su salida la enviamos al puerto 13, el cual es analógico.


El código que utilizaremos permite utilizar los 8 leds como una barra de indicación. Cuando el potenciómetro está en el tope izquierdo, este entrega al puerto 13 cero voltios. Cuando el potenciómetro está en el tope derecho le entrega al puerto 5V.

El micro traduce este voltaje en un número entero que oscilará entre 0 y 1024, dependiendo del voltaje, el cual estará en un rango de oV a 5V.

Nuestra intención es que a medida que vamos rotando el potenciómetro a la derecha (0->5)V la barra de 8 leds debe ir iluminándose a la derecha hasta llegar a encender los 8 leds, justamente cuando el potenciómetro esté en el tope derecho. En la rotación contraria (5->0)V, los leds deben irse apagando uno a uno de derecha a izquierda hasta quedar todos apagados.

A continuación el codigo

// Ejemplo de utilización de lectura de potenciometro y encendido de leds
#include "ADlib/__map.c"

const int potPin=13;

void setup()
{
byte i;
for (i=0; i < 8; i++)
pinMode(i,OUTPUT);
pinMode(potPin,INPUT);
}

void apagarLeds()
{
byte i;
for (i=0; i<8; i++)
digitalWrite(i,LOW);
}

void encenderLeds(int count)
{
byte i;
for (i=0; i<count; i++)
digitalWrite(i,HIGH);
}

void loop()
{
apagarLeds();
encenderLeds(map(analogRead(potPin),0,1024,0,8));
delay(50);
}

Veamos como funciona esto. En primer lugar tenemos la declaración de una constante (potPin) que nos indica cual es el puerto que utilizaremos para leer el voltaje que nos entrega el potenciómetro.

Luego tenemos la función setup() para definir la modalidad de los puertos. Los puertos de entrada(0,7) los definimos como salidas en el ciclo for. Asimismo, el puerto 13 lo definimos como entrada con la función pinMode.

Hemos creado 2 funciones. apagarLeds() nos permite apagar todos los leds al tiempo utilizando un ciclo for con el siguiente rango (0<=i<8). Luego definimos una función que nos permite encender hasta el led definido por el parámetro count.

En el ciclo Loop(), vemos como apagamos los leds para luego encender hasta el led que nos devuelve la función map.

La función map es una función que nos permite convertir un rangoA en un rangoB. Esta función es estándar en arduino, pero no en pinguino, por lo que está programada y agregada al directorio de librerías de pinguino, y es por esta razón que la segunda línea existe.

#include "ADlib/__map.c"

En nuestro caso, la función mapea el rango (0,1024) al rango (0,8) utilizando como entrada lo que devuelve analogRead(potPin). Esta conversión es muy conveniente ya que directamente le pasamos un valor entre 0 y 8 a la función encenderLeds(). Este ciclo se repite infinitamente cada 50 milisegundos debido la función delay(50) que hemos colocado al final del loop.

// map function
// Alejandro-Dirgan 2011

#ifndef __MAP__
#define __MAP__

#define MAP 1

float map(int value, int fLow, int fHigh, int tLow, int tHigh)
{
return ((float )tHigh*(float )(value-fLow)+(float )tLow*(fHigh-value))/(float )(fHigh-fLow);
}

#endif

Veamos como funciona en la práctica.


Con las entradas analógicas se pueden hacer infinidad de cosas, solo la imaginación y los requerimientos lo dirán.

En la próxima entrega veremos las salidas analógicas.


Read More......

jueves, 16 de junio de 2011

Entrada Digital (Digital Input)

En el artículo anterior vimos como utilizar las salidas del microcontrolador para encender y apagar leds, utilizando valores lógicos altos y bajos (0,5V):(LOW;HIGH) con la función digitalWrite(). En este artículo utilizaremos los puertos para obtener información del entorno.

Generalmente cuando pensamos en una entrada digital, inmediatamente evocamos un switch ON/OFF. Cuando el swith está en off, no hay paso de energía y nuestro puerto, al cual está conectado el switch, se encontrará en un nivel bajo (LOW, 0v). Por el contrario, si el switch está en ON, el mismo permitirá el paso de energía y el puerto destino obtendrá un valor alto (HIGH, 5v). Esta lógica esta perfecta, pero veamos como podemos implementarla adecuadamente y veremos las variantes correspondientes.

Lo primero que debemos entender es como mantenemos un valor estable en un puerto de entrada. Como estamos hablando de una entrada digital, nuestra intención es determinar cuando la misma tiene un valor alto o bajo, y luego tomar una decisión al respecto, para por ejemplo encender un led, iniciar una secuencia de comandos, para activar un parámetro, etc.

En general, si no definimos una voltaje en una entrada digital esta podrá tener un valor flotante, lo cual debemos evitar. Requerimos tener un valor alto o un valor bajo, y esto se logra a través de las resistencias pull-up o pull-down.


En la figura de la derecha vemos como el terminal 1 del circuito lógico puede ser alimentado con un valor bajo (LOW, 0V) en el momento que el switch S1 es presionado.

Esto efectivamente sucede cuando el switch S1 se presiona, ya que hay un camino directo desde tierra a este terminal. Pero que pasa cuando S1 esta abierto?. El problema es que no podemos garantizar que valor lee el terminal 1 cuando esta condición prevalece.

En toda entrada lógica digital siempre debemos garantizar los dos valores a leer (alto y bajo), de forma que no haya ambigüedad.

Para ello existen dos modalidades, utilizando conceptos básicos de circuitos digitales: las resistencias pull-up y pull-down.

Veamos la siguiente figura:


En el circuito de la izquierda podemos observar que el terminal 1 esta conectado a través de una resistencia pull-up a Vcc (HIGH, 5V), cuando S1 está abierto. En este estado estamos garantizando un valor Alto cuando S1 no está presionado. Cuando S1 se presiona, el terminal 1 quedará conectado directamente a tierra, obteniendo un valor bajo (LOW, 0V). El valor de la resistencia puede conseguirse persiguiendo un valor bajo de corriente a circular entre VCC y Masa, utilizando V=I*R. La idea es dejar pasar menos de 1 mA para no dañar ni el circuito ni el cableado (en general el valor de esta resistencia está entre 10K y 47K).

En el circuito de la derecha estamos implementando una resistencia pull-Down a Tierra (LOW, 0V), garantizando 0V cuando S1 está abierto y 5V cuando S1 esta cerrado. De esta forma estamos garantizando en cualquier caso un valor predicho que podemos leer desde nuestro microcontrolador.

Como podemos observar, dependiendo que variante hayamos escogido, S1 puede representar un valor alto o bajo cuando está presionado, y viceversa. Depende de nuestra lógica y de como deseemos programar nuestro la escogencia de alguna de las modalidades descritas anteriormente.

OK. ya sabemos entonces como colocar un valor predecible en una entrada, ahora veamos como leerla y utilizarla para nuestros fines.

La figura muestra la conexión hecha para que el sketch que mostramos funcione adecuadamente.


El siguiente programa muestra

const int potPin=14, ledPin=12;

void setup()
{
pinMode(potPin,INPUT);
pinMode(ledPin,OUTPUT);
}

void loop()
{
if (analogRead(potPin))
digitalWrite(ledPin,LOW);
else
digitalWrite(ledPin,HIGH);

delay(50);
}

Objetivo:

Demostrar como leer una entrada digital y tomar una decisión de acuerdo a lo leído, para la ejecución de una acción.

Descripción:

(1) const int potPin=14, ledPin=12;

Definen constantes asociadas a el pin de entrada (14) y el pin de salida (12).

(2) Procedimiento setup()
{
pinMode(potPin,INPUT);
pinMode(ledPin,OUTPUT);
}

Definimos los pines como de entrada y salida en el procedimiento de setup.

(3) procedimiento loop()
{
if (analogRead(potPin))
digitalWrite(ledPin,LOW);
else
digitalWrite(ledPin,HIGH);

delay(50);
}

En el loop del programa, vemos una estructura de toma de decisiones.

if (analogRead(potPin))

analogRead es una función que permite obtener una lectura del pin potPin (14). En la estructura if lo único que requerimos es saber si esta lectura es mayor que cero (0), para apagar el led, o si la lectura es cero (0) (cuando se evalúa el else), para en encender el led.

Esta lógica aplica porque el circuito que montamos está basado en una resistencia pull-up.

Este ciclo se repite cada 50 milisegundos. Si el switch está abierto el if (analogRead(potPin)) nos retornará true, y apagaremos el led con digitalWrite(ledPin,LOW).

Por el contrario, si el switch está cerrado el potPin estará conectado directamente a tierra y se leerá un valor bajo (oV), lo que hace que en el ciclo del programa la instrucción asociada al else se ejecute: digitalWrite(ledPin,HIGH).

Es muy sencilla su programación. Luego compilamos el programa buscando que todo esté OK y reprogramamos el microcontrolador (en mi caso el pinguino) y dejamos que ejecute el programa.

En el video se puede observar que he agregado un display lcd 16x2 para mostrar si el valor de potPin es alto o bajo y para indicar que estamos ejecutando de acuerdo a estos valores.


Read More......

lunes, 6 de junio de 2011

Playing with LEDS

En la entrega anterior vimos como utilizar las salidas digitales. En este artículo solo quiero mostrar que lo que se puede hacer con las salidas digitales es directamente proporcional a lo que podemos hacer programando.

La inteligencia de estos dispositivos electrónicos es solo cuestión de imaginación y capacidad de programación.

En esta entrega quiero mostrarles como hacer un divertimento de iluminación de leds.

EL ESQUEMA

7 LEDs conectados a las salidas 0-6 del pinguino 2550.



EL CODIGO

Un simple programa que permite iluminar 7 leds. El código está definido con 6 procedimientos:

- ledOff(): Pone las salidas 0-6 en LOW
- secuencia1(): hace una secuencia del pin 0 al 6 con 10 ms de retardo
- secuencia2(): hace una secuencia del pin 6 al 0 con 10 ms de retardo
- secuencia3(): enciende los leds impares y hace flash en los pares
- secuencia4(): enciende los leds pares y hace flash en los impares
- secuencia5(): hace flash alternativo entre los leds pares e impares

//Playing with leds
byte const pines[]={0,1,2,3,4,5,6};
byte pausa1, pausa2;

void ledOff()
{
byte i;
for (i=1;i<7;i++)
digitalWrite(pines[i-1],LOW);

}

void setup()
{
byte i;
for (i=0;i<7;i++)
pinMode(pines[i],OUTPUT);
pausa1=10;
pausa2=50;
ledOff();
}

void secuencia1()
{
byte i;
ledOff();
for (i=1;i<7;i++)
{
digitalWrite(pines[i-1],HIGH);
delay(pausa1);
digitalWrite(pines[i-1],LOW);
delay(pausa1);
}
}

void secuencia2()
{
byte i;
ledOff();
for (i=7;i>=1;i--)
{
digitalWrite(pines[i-1],HIGH);
delay(pausa1);
digitalWrite(pines[i-1],LOW);
delay(pausa1);
}
}

void secuencia5()
{
byte i;
ledOff();
for (i=0;i<7;i++)
{
digitalWrite(pines[0],HIGH);
digitalWrite(pines[2],HIGH);
digitalWrite(pines[4],HIGH);
digitalWrite(pines[6],HIGH);
delay(pausa2);
digitalWrite(pines[0],LOW);
digitalWrite(pines[2],LOW);
digitalWrite(pines[4],LOW);
digitalWrite(pines[6],LOW);
delay(pausa2);
digitalWrite(pines[1],HIGH);
digitalWrite(pines[3],HIGH);
digitalWrite(pines[5],HIGH);
delay(pausa2);
digitalWrite(pines[1],LOW);
digitalWrite(pines[3],LOW);
digitalWrite(pines[5],LOW);
delay(pausa2);
}
}

void secuencia3()
{
byte i;
ledOff();
digitalWrite(pines[0],HIGH);
digitalWrite(pines[2],HIGH);
digitalWrite(pines[4],HIGH);
digitalWrite(pines[6],HIGH);
for (i=0;i<7;i++)
{
digitalWrite(pines[1],HIGH);
digitalWrite(pines[3],HIGH);
digitalWrite(pines[5],HIGH);
delay(pausa2);
digitalWrite(pines[1],LOW);
digitalWrite(pines[3],LOW);
digitalWrite(pines[5],LOW);
delay(pausa2);
}
digitalWrite(pines[0],LOW);
digitalWrite(pines[2],LOW);
digitalWrite(pines[4],LOW);
digitalWrite(pines[6],LOW);
}

void secuencia4()
{
byte i;
ledOff();
digitalWrite(pines[1],HIGH);
digitalWrite(pines[3],HIGH);
digitalWrite(pines[5],HIGH);
for (i=0;i<7;i++)
{
digitalWrite(pines[0],HIGH);
digitalWrite(pines[2],HIGH);
digitalWrite(pines[4],HIGH);
digitalWrite(pines[6],HIGH);
delay(pausa2);
digitalWrite(pines[0],LOW);
digitalWrite(pines[2],LOW);
digitalWrite(pines[4],LOW);
digitalWrite(pines[6],LOW);
delay(pausa2);
}
digitalWrite(pines[1],LOW);
digitalWrite(pines[3],LOW);
digitalWrite(pines[5],LOW);
}

void loop()
{
byte j;
for (j=0;j<7;j++)
secuencia1();
for (j=0;j<7;j++)
secuencia2();
secuencia3();
secuencia4();
secuencia5();
}

EL RESULTADO

El siguiente video muestra el resultado de cargar este programa en el pinguino y ejecutarlo conectado al breadboard con los 7 leds.



Read More......