Mostrando entradas con la etiqueta Lab Computo Integrado. Mostrar todas las entradas
Mostrando entradas con la etiqueta Lab Computo Integrado. Mostrar todas las entradas

miércoles, 9 de mayo de 2012

Arduino - Conexión Serial

Gracias a la inspiración de mi compañero David Sosa, me dio una fuerte sensación de intentar realizar una conexión serial con mi Arduino UNO de alguna manera. Inicialmente creía que la única forma de hacerlo era mediante Processing(lenguaje de programación y entorno de desarrollo integrado de código abierto basado en Java), pero al investigar me di cuenta que existían múltiples formas de realizarlo, y la que me parecio más interesante fue usando pySerial, una librería de python.


En este post veremos un ejemplo de uso de pySerial de forma básica con un script sencillo, para después ir mejorandolo hasta ser usado desde un sitio web usando CGI.


Conexión Serial


Se utiliza para la comunicación entre la placa Arduino y un ordenador u otros dispositivos. Todas las placas Arduino tienen al menos un puerto serie (también conocido como UART o USART): Serial. Se comunica a través de los pines digitales 0 (RX) y 1 (TX), así como con el ordenador mediante USB. Por lo tanto, si utilizas estas funciones, no puedes usar los pines 0 y 1 como entrada o salida digital.


Demostración


En las primeras demostraciones se utilizará un simple LED para visualizar como se controla su encendido y apagado mediante una comunicación serial. Las conexiones son como se aprecia en la imágen:




Conexión mediante Serial Monitor


Para poder realizar una conexión serial con el Arduino UNO, primero es necesario programarlo para que inicie una conexión serial y este listo para recibir los datos desde la computadora. Para esto podemos usar el ejemplo que tiene por default Arduino(con unas pequeñas modificaciones), con el código siguiente:


const int ledPin = 13; // the pin that the LED is attached to
int incomingByte;      // a variable to read incoming serial data into

void setup() {
  // initialize serial communication:
  Serial.begin(9600);
  // initialize the LED pin as an output:
    Serial.println("Hello world!");

  pinMode(ledPin, OUTPUT);
}

void loop() {
  // see if there's incoming serial data:
  if (Serial.available() > 0) {
    // read the oldest byte in the serial buffer:
    incomingByte = Serial.read();
    // if it's a capital H (ASCII 72), turn on the LED:
    if (incomingByte == 'H') {
      digitalWrite(ledPin, HIGH);
        Serial.println("Encendiendo LED");
    } 
    // if it's an L (ASCII 76) turn off the LED:
    if (incomingByte == 'L') {
      digitalWrite(ledPin, LOW);
      Serial.println("Apagando LED");
    }
  }
}


El código es bastante sencillo, define una constante que será usada para definir el pin donde conectaremos el LED que se encenderá y apagará. Y además un byte para almacenar el byte que se recibe en el buffer serial.

Se inicializa la conexión serial, y también se define el pin 13 como salida en el setup(). Después en el loop() se verifica que haya tráfico serial entrante y se lee el byte más viejo del buffer, almacenandolo en la variable incomingByte(es int, y almacenará el número ASCII del carácter que se envió). Se compará el valor recibido con 'H' para saber si encender el LED, o 'L' para apagarlo, y además se envía a la computadora mediante el puerto serial un mensaje para cada caso.


Ahora para probar el funcionamiento de la comunicación serial, podemos usar el Serial Monitor, una herramienta del IDE de Arduino para enviar datos mediante el puerto serial(Tools>Serial Monitor).
En ella simplemente ingresamos una 'H' para encender el LED, y una 'L' para apagarlo:



Conexión mediante un script con pySerial


La siguiente tarea es realizar el mismo procedimiento pero mediante pySerial.


Qué es pySerial?


La biblioteca pySerial provee muchos módulos con los cuales se puede tener casi total control del puerto Serial de una computadora. Ya que las computadoras pueden tener más de un puerto Serial configurado, pySerial utiliza números del 0 al 255 para cada uno de los puertos, de tal forma que se pueda invocar cada puerto de manera individual y que se asegure la compatibilidad con muchas plataformas.


Esta biblioteca tiene una gran gama de aplicaciones, qeu van desde la comunicacion con dispositivos móviles como celulares y miniordenadores, hasta el control de plantas industriales automatizadas. Las funciones que este módulo provee, posibilitant, por ejemplo, establecer comunicacion con los bancos o registros de memorias de muchos dispositivos y poder manejar sus datos. En el área de la robotica, actualmente muchas plantas automatizadas en las que se utilizan robots o maquinaria industrial, utilizan el protocolo RS-232 y puerto seriales para poder comunicarse con dichos dispositivos, y por ejemplo, enviar instrucciones de funcionamiento o recibir la retroalimentacion de estos dispositivos, estableciendo una comunicacion bilateral o Full-duplex. Todo esto se realiza a través del puerto Serial y pySerial tiene la capacidad de realizar esto

Para instalar pySerial, podemos hacer una de varias cosas:

1. Instalarlo desde el código fuente. Para esto descargamos el código de: http://pypi.python.org/pypi/pyserial , extraemos los archivos, entramos a la carpeta y corremos el comando:
python setup.py install
2. Si contamos con pip, podemos simplemente correr el comando:
pip pyserial
3. O si contamos con easy_install:
easy_install -U pyserial
Ya instalado podemos escribir un pequeño script para mandar el estado del LED mediante la línea de comandos, como el siguiente:

#!/usr/bin/python                                                                                                       
import serial, time, sys
#Correr: 
#./arduino_serial.py "Estado del LED" "Puerto Serial"
#Ejemplo:
#./arduino_serial.py H ttyACM1

#Intentamos recoger los argumentos de la linea de comandos
try:
 puerto = sys.argv[2]
 estado = sys.argv[1]
#Si no podemos, damos un mensaje de error y salimos
except IndexError:
 print "Error al ingresar los argumentos.\nDebe ser: python arduino_serial.py 'Estado del LED' 'Puerto Serial'"
 sys.exit()
#Intentamos abrir la comunicacion serial y realizar algunas
#operaciones en ella
try:
 ser = serial.Serial('/dev/%s'%sys.argv[2], 9600, timeout = 1)
 time.sleep(2)
 message = ser.read(100)
 print message
 ser.write('%s'%sys.argv[1])
 message = ser.read(100)
 print message
#Si no podemos, mostramos un mensaje de error
except serial.SerialException as e:
 print "%s"%e

El código es igualmente simple. Tomamos desde la línea de comando dos argumentos, uno: el estado que deseamos dar al LED del arduino, y dos: el puerto serial con el que nos vamos a comunicar(este lo podemos encontrar en el IDE de Arduino en la pestaña Tools>Serial Ports.


Con el string del puerto serial inicializamos la conexión con dicho puerto serial, dando un timeout de 1 segundo. Ahora es importante también dar un retraso de dos segundos, debido a que al conectar el puerto serial, el Arduino se resetea, lo que significa que si no ponemos este delay, el reseteo interferirá con nuestro intento de envíar el caractér 'H' o 'L' al Arduino, y no ocurrirá nada.


Volviendo al código, leemos lo que el arduino envío inicialmente al correr y lo almacenamos en una variable para luego imprimirla. Escribimos el estado que se ingreso en la línea de comando por el puerto serial para cambiar el estado del LED, y de nuevo leemos un mensaje que haya enviado el led, confirmando el cambio de estado.


El resultado en la línea de comando es el siguiente:




Conexión mediante un script CGI y pySerial 


Para concluir, haremos algo similar a lo anterior, pero ahora mediante un formulario web, utilizando python y CGI.


¿Qué es CGI?


El CGI (Por sus siglas en inglés “Common Gateway Interface” es de las primeras formas de programación web dinámica.
En sí, es un método para la transmisión de información hacia un compilador instalado en el servidor. Su función principal es la de añadir una mayor interacción a los documentos web que por medio del HTML se presentan de forma estática.
Entonces usando CGI, hice un pequeño y simple formulario web, el cual simplemente cuenta con dos botones de radio, para poder seleccionar entre los dos estados del LED, y un botón para confirmar la selección.
Inicialmente este método no funcionaba, ya que era necesario dar permisos al archivo para poder abrir una comunicación serial, esto lo arregle de la siguiente forma(no es la recomendada, pero igualmente funciona):
chmod o+rw /dev/ttyACM1
(Nota: Hay que cambiar ACM1 por el respectivo puerto serial, de nuevo, este puede ser encontrado al buscar en la pestaña Tools>Serial Port del IDE de Arduino)
Con esto podemos utilizar el formulario web para enviar los estados por el puerto serial, el script de python es el siguiente:
#!/usr/bin/python                                                                                                       
import serial,time,cgi, sys
print "Content-type: text/html\n"
print "<html><head><meta http-equiv='refresh' content='0;url=http://localhost/'/><title>LED Test</title></head><body><p>\n"
datos = cgi.FieldStorage()
if datos.has_key("estado") \
    and datos["estado"].value != "":
try:
 ser = serial.Serial('/dev/ttyACM1', 9600)
 time.sleep(2)
 ser.write("%s"%datos["estado"].value)
 ser.close()

except serial.SerialException as e:
 print "no device connected - printing to terminal only "%s 
 sys.exit()
print "</p></body></html>"


Sin entrar mucho en detalles, el código lee todo el contenido del cgi, busca si existe la llave "estado", correspondiente a los radio button, y si estos no estan vacios(se selecciono alguno), intenta iniciar la conexión serial y manda el estado seleccionado al arduino. 


Para hacer funcionar esto, es necesario tener instalado apache, y mover el código a /usr/lib/cgi-bin, además de colocar el respectivo index.html en /var/www, que se puede descargar de aquí:


La página es muy simple, y se ve así:


Los archivos, tanto el html como el .py pueden descargarse de AQUÍ.

Imágen del circuito:



Lo mismo pero ahora con un Display

Ahora para mostrar el control de algunas salidas más, utilizaré los pines 13-10 para dar una salida BCD,  que represente los números del 0 al 9, para poder mostrarlos en un display BCD a 7 segmentos.

Para hacer esto hay que reprogramar el Arduino, usando el siguiente código:

const int A = 13;
const int B = 12;
const int C = 11;
const int D = 10;

int incomingByte; 

void setup() {
  // initialize serial communication:
  Serial.begin(9600);
  // initialize the LED pin as an output:
  Serial.println("Hello world!");

  pinMode(A, OUTPUT);
  pinMode(B, OUTPUT);
  pinMode(C, OUTPUT);
  pinMode(D, OUTPUT);
}

void loop() {
  // see if there's incoming serial data:
  if (Serial.available() > 0) {
    // read the oldest byte in the serial buffer:
    incomingByte = Serial.read();
    
    switch(incomingByte){
     case '1':
       digitalWrite(A, HIGH);
       digitalWrite(B, LOW);
       digitalWrite(C, LOW);
       digitalWrite(D, LOW);
      break;
     
     case '2':
       digitalWrite(A, LOW);
       digitalWrite(B, HIGH);
       digitalWrite(C, LOW);
       digitalWrite(D, LOW);
      break;
     
     case '3':
       digitalWrite(A, HIGH);
       digitalWrite(B, HIGH);
       digitalWrite(C, LOW);
       digitalWrite(D, LOW);
      break;
     
     case '4':
       digitalWrite(A, LOW);
       digitalWrite(B, LOW);
       digitalWrite(C, HIGH);
       digitalWrite(D, LOW);
      break;
     
     case '5':
       digitalWrite(A, HIGH);
       digitalWrite(B, LOW);
       digitalWrite(C, HIGH);
       digitalWrite(D, LOW);
      break;
     
     case '6':
       digitalWrite(A, LOW);
       digitalWrite(B, HIGH);
       digitalWrite(C, HIGH);
       digitalWrite(D, LOW);
      break;
     
     case '7':
       digitalWrite(A, HIGH);
       digitalWrite(B, HIGH);
       digitalWrite(C, HIGH);
       digitalWrite(D, LOW);
      break;
     
     case '8':
       digitalWrite(A, LOW);
       digitalWrite(B, LOW);
       digitalWrite(C, LOW);
       digitalWrite(D, HIGH);
      break;
     
     case '9':
       digitalWrite(A, HIGH);
       digitalWrite(B, LOW);
       digitalWrite(C, LOW);
       digitalWrite(D, HIGH);
      break;
     
     case '0':
      digitalWrite(A, LOW);
       digitalWrite(B, LOW);
       digitalWrite(C, LOW);
       digitalWrite(D, LOW);
      break;
    }
  }
}

Este código es similar al anterior, en el sentido que leerá un byte mediante la conexión serial, y dependiendo de que caracter sea, mostrará una salida diferente. Pero ahora se darán múltiples salidas con las combinaciones binarias del número correspondiente al caracter. Para controlarlo mediante el Serial Monitor y el script sencillo en python, se pueden usar los códigos anteriores, pero para manipularlo mediante CGI, se requiren algunos cambios, para lo cual añadi una página en el apartado http://localhost/display, donde aparece una ventana como la siguiente:

Los archivos pueden descargarse AQUÍ.

Los cambios son mínimos, simplemente cambie los radio buttons por una lista desplegable con los números del 0 al 9 en el html, y el identificador de ésta en el .py y el html.


Referencias:

Arduino - Manejo de Interrupciones

Interrupciones

Una interrupción es una señal de un dispositivo conectado a una computadora o a un programa dentro de la computadora que causa que el programa principal se detenga y se realice algo más.

Después de que la señal de interrupción es capturada, la computadora reasume a correr el programa que estaba corriendo o inicia a correr otro programa. Basicamente, una sola computadora puede realizar solo una instrucción en un tiempo. Pero debido a que puede ser interrumpida, puede tomar turnos entre los programas o instrucciones que realiza. Esto se conoce como multitasking.

Un sistema operativo usualmente tiene algún código llamado interrupt handler. El interrupt handler da prioridades a las interrupciones y las guarda en una cola si más de una esta esperando a ser atendida. El sistema operativo tiene también otro programa llamado Scheduler, que se encarga de decidir cual programa recibe el control.

En general, hay dos tipos de interrupciones, de hardware y software. Una interrupción de software ocurre cuandouna aplicación termina o solicita ciertos servicios del sistema operativo. La interrupción de hardware ocurre cuando, por ejemplo, una operación de entrada o salida es completada como leer datos desde una memoria.

Podemos preguntarnos, que hay de diferente entre usar una entrada digital a realizar una interrupción. Simplemente, cuando se usa una entrada digital, tipicamente se lee el valor de dicha entrada realizando una instrucción, y después actuando dependiendo del valor con algún tipo de lógica. Dependiendo de la complejidad de la rutina, y la duración del cambo de estado en la entrada, es bastante posible no ver ocurrir el cambio en la entrada

Usando una interrupción, el código es literalmente interrumpido, y forzado a ramificarse y hacer otra ejecución, entonces el cambio de estado en la entrada no se pierde.

¿Cuál es el Beneficio?


Las interrupciones pueden ayudar a resolver problemas de timing que pueden ocurrir en la configuración del código o hardware.

Interrupciones en Arduino

EL procesador de cualquier Arduino tiene dos tipos de interrupciones, externas(external) y de cambio de pines(pin change). El Arduino uno cuenta con solo dos pins de interrupciones externas: INT0 e INT1, y estan asignadas a los pines 2 y 3. Estas interrupciones pueden ser puestas a activarse en subidas o bajadas de señal, o en bajo nivel. Las activaciones son interpretadas por el  hardware, y las interrupciones son muy rápidas. E

Por otro lado, las interrupciones de cambio de pin pueden ser activadas en muchos más pines. Para los Arduinos basados en ATmega168/328, pueden ser activados cualquiera de los 20 pines d eseñal del Arduino. Igualmente pueden ser activados en subidas o bajadas de señal, así que depende del código el establecer los pines que recibiran las interrupciones para determinar que paso, y manejarlo apropiadamente.

Demostración

Para demostrar la diferencia entre el usar las interrupciones y no usarlas, explicaré un ejemplo sencillo utilizando un led, un par de resistencias y un push button.

Para el ejemplo utilizaré mi Arduino Uno, y los pines digitales 2 y 4 como salida para controlar un LED, siguiendo el siguiente esquema:
(Nota: Aunque en la imagen dice Arduino Duemilanove, las conexiones son las mismas para el Arduino Uno, y cualquier Arduino con el  ATmega168/328)
Sin interrupciones

El código para esta demostración es el siguiente:

int pbIn = 2;          // Digital input on pin 2
int ledOut = 4;        // The output LED pin
int state = LOW;       // The input state

void setup()
{
  // Set up the digital Pin 2 to an Input and Pin 4 to an Output
  pinMode(pbIn, INPUT);
  pinMode(ledOut, OUTPUT);
}

void loop()
{
  state = digitalRead(pbIn);      //Read the button

  digitalWrite(ledOut, state);    //write the LED state

  //Simulate a long running process or complex task
  for (int i = 0; i < 100; i++)
  {
     // do nothing but waste some time
     delay(10);
  }
}

Como se puede observar es un código sencillo. Definimos el pin 2 como entrada y el 4 como salida, y una variable para controlar en que estado esta actualmente el botón. Lo interesante es que para poder comparar eficientemente la interrupción con éste código, agregamos un for que se repite 100 veces, dando un delay de 10 milisegundos cada vez.

Esto causará salidas impredecibles en el LED debido a que el for(que simula un proceso tardado) esta en un punto indeterminado en relación a cuando el botón es presonado. Algunas veces el LED cambia de estado inmediatamente, otras veces nada pasa, y otras veces es necesario mantener el botón presionado por un mayor tiempo para que el estado cambie y sea reconocido.

Usando Interrupciones

Ahora, modificando el código para agregar interrupciones, el LED cambia de estado cuando sea que el botón sea presionado, aunque el código sigue corriendo el mismo for tardado. El código es el siguiente:

int pbIn = 0;                  // Interrupt 0 is on DIGITAL PIN 2!
int ledOut = 4;                // The output LED pin
volatile int state = LOW;      // The input state toggle

void setup()
{
  // Set up the digital pin 2 to an Interrupt and Pin 4 to an Output
  pinMode(ledOut, OUTPUT);

  //Attach the interrupt to the input pin and monitor for ANY Change
  attachInterrupt(pbIn, stateChange, CHANGE);
}

void loop()
{
  //Simulate a long running process or complex task
  for (int i = 0; i < 100; i++)
  {
    // do nothing but waste some time
    delay(10);
  }
}

void stateChange()
{
  state = !state;
  digitalWrite(ledOut, state);
}

La palabra clave volatile es agregada a la variable state, esto causa que el compilador use la RAM en vez de un registro de almacenamiento. Esto es así debido a que el registro de almacenamiento puede ser temporalmente impreciso si es modificado por areas diferences a las del hilo principal. En el Arduino, esto se relaciona con el código que es activado por las interrupciones.

El método attachInterrupt(parámetro1, parámetro2, parámetro3) requiere lo siguiente:

  • parámetro1: A que interrupción se escuchará. Este es el número de la interrupción, no el número del pin digital.
  • parámetro2: A que función llamar, este debe ser un método que no tome parámetros y no retorne valores.
  • parámetro3: Que condición vigilar.
El arduino puede escuchar 4 tipos de condiciones(parámetro 3). Estos son:
  • LOW: La entrada esta en un estado LOW (0).
  • RISING: El estado de la entrada cambia de LOW a HIGH(0 a 1).
  • FALLING: El estado de la entrada cambia de HIGH a LOW(1 a 0).
  • CHANGE: El estado de la entrada cambia de HIGH a LOW, o de LOW a HIGH, es decir ha cambiado su estado.
Arduino tiene la habilidad de temporalmente ignorar todas las interrupciones. Esto es deseable en el caso en el que se tenga un código sensible que debe ser ejecutado sin interrupción. En este caso, se debe realizar un llamado al método noInterrupts(). Entonces ya que termine el código sensible, las interrupciones pueden reiniciarse con el método interrupts().

Las interrupciones también pueden ser cambiadas en cualquier momento usando el método attachInterrupt(). Tan pronto como esto sea hecho, si hay alguna otra interrupción asociada con el pin, será removida.

Además las interrupciones pueden también ser removidas usando el método detachInterrupt( número de la interrupción). 

Referencias:



  • http://www.codeproject.com/Articles/61023/Arduino-Platform-Interrupts-Introduction
  • http://arduino.cc/playground/Code/Interrupts
  • http://whatis.techtarget.com/definition/0,,sid9_gci212374,00.html
  • Arduino - Manejo de Memoria

    La memoria es una parte importante de cualquier microcontrolador. En ella podemos almacenar variables que no deseemos que se borren al reiniciar o apagar el dispositivo, lo cual dependiendo del sistema, puede ser la parte principal del funcionamiento de dicho dispositivo.

    Existen 3 fuentes de memoria en el microcontrolador utilizado por la placa Arduino:

    Memoria Flash
    La memoria Flash (espacio del programa) es donde Arduino almacena el sketch. Un sketch es el nombre que usa Arduino para un programa. Es la unidad de código que se sube y ejecuta en la placa Arduino.

    Esta memoria es no volátil, si Arduino deja de ser alimentado eléctricamente los datos que haya en esta memoria permanecerán.

    SRAM (Static Random Access Memory)

    Donde los sketches almacena y manipulan variables al ejecutarse. La información guardada en esta memoria será eliminada cuando Arduino pierda la alimentación. Esta memoria es de uso exclusivo para el programa en ejecución.

    La memoria SRAM de Arduino es muy pequeña, por lo que debemos optimizar nuestros programas al máximo y no abusar de variables de tipo char muy grandes. Hay que tener en cuenta que cada carácter de una variable char utiliza un byte. En el microcontrolador ATmega 168 el tamaño de la memoria SRAM es de 1024 bytes, para el caso de un chip ATmega328 (como el que incorpora Arduino UNO) el tamaño es de 2KB (2048 bytes).

    Si la SRAM se queda sin espacio, el programa de Arduino fallará de forma imprevista, aunque se compile y se suba a Arduino correctamente la aplicación no se ejecutará o se ejecutara de manera extraña.

    EEPROM

    EEPROM es un espacio de memoria que puede ser utilizada por los programadores para almacenar información de largo plazo. Este tipo de memoria es no volátil, por lo que los datos guardados en ella permanecerán aunque Arduino pierda la alimentación. Esta memoria puede ser usada para guardar valores si es necesario.Hay que tener en cuenta que el tamaño de la memoria EEPROM interna de Arduino es "pequeño" pero Arduino admite añadir módulos de memoria EEPROM externa de mayor tamaño.

    El Arduino Uno que yo tengo, contiene las siguientes especificaciones de memoria:
    • Flash Memory 32 KB (ATmega328) of which 0.5 KB used by bootloader
    • SRAM 2 KB (ATmega328)
    • EEPROM 1 KB (ATmega328)
    Manipulación de la EEPROM

    El microcontrolador en el Arduino tiene una memoria EEPROM como ya habíamos visto. Para poder manejarla, existe la librería EEPROM que permite leer y escribir bytes en ella.

    Las dos funciones principales son read() y write().
    • read(): 
      • Descripción: Lee un byte desde la memoria EEPROM. 
      • Sintaxis: EEPROM.read(address)
      • Parámetros:
        • address: La localización de donde se leerá, iniciando desde 0(int).
      • Retorna: El valor guardado en esa localización(byte)
    • write()
      • Descripción: Escribe un byte en la memoria EEPROM.
      • Sintaxis: EEPROM.write(address, value)
      • Parámetros:
        • address: la localización en donde se escribirá, iniciando desde 0(int)
        • value: el valor a escribir, de 0 a 255(byte)
      • Retorna: nada
      • Nota: Escritura en la memoria EEPROM toma 3.3 milisegundos en completarse. La memoria EEPROM tiene una vida específífica de 100, 000 escrituras o ciclos de borrado, así que se debe ser cuidadoso en como se escribe en ella.
    Código de Escritura:

    #include<eeprom.h>
    
    void setup()
    {
      for (int i = 0; i < 512; i++)
        EEPROM.write(i, i);
    }
    
    void loop()
    {
    }
    

    El código es el que viene por ejemplo en la página de Arduino. No hay mucho que explicar, simplemente escribimos valores enteros desde 0 al 511 en la memoria EEPROM una sola vez, como se puede observar, ya que no colocamos código dentro de loop().

    Código de Lectura:

    #include<eeprom.h>
    
    int a = 0;
    int value;
    
    void setup()
    {
      Serial.begin(9600);
    }
    
    void loop()
    {
      value = EEPROM.read(a);
    
      Serial.print(a);
      Serial.print("\t");
      Serial.print(value);
      Serial.println();
    
      a = a + 1;
    
      if (a == 512)
        a = 0;
    
      delay(500);
    }

    Ahora para poder verificar que lo anterior funciono, programamos este código para poder leer los datos que fueron almacenados anteriormente de la memoria EEPROM. El código inicializa una conexión serial, y lee los valores almacenados en la memoria, para después imprimirlos y visualizarlos en la computadora.

    El resultado es el siguiente:


    (Y continua imprimiendo todos los valores que se leen de la memoria EEPROM)


    Ampliando la memoria

    Dependiendo del uso que se vaya a dar para el Arduino, las memorias Flash, SRAM y EEPROM pueden resultar muy limitadas. Es decir, si queremos capturar vídeo o fotos de alguna manera y guardarla en las memorias del Arduino, de nada nos serviría utilizarlas, ya que estos archivos pesan mucho más de lo que soportan. Para esto existen alternativas de expansión, agregando una memoria EEPROM externa o con módulos para tarjeta SD.
    • EEPROM externa

    Una posibilidad para ampliar la capacidad de memoria de Arduino es usar memoria EEPROM externa, adquiriendo este tipo de memoria (que no es muy cara) podremos disponer de más memoria EEPROM para nuestro programa. Este tipo de memoria es no volátil. Por ejemplo, una EEPROM 24LC64 puede costar unos 4 euros y tiene 64K de tamaño: 

    Obviamente, este tipo de memorias EEPROM no tienen un gran tamaño, por ello, no serán útiles para proyectos con grandes requerimientos de espacio.
    • Módulo SD
    Si se requiere desarrollar un proyecto hardware con Arduino que tenga grandes requerimientos de espacio (Megas, Gigas), por ejemplo si queremos trabajar con audio, vídeo, fotos, almacenamiento de datos, etc., la mejor opción es utilizar algún tipo de medio de almacenamiento removible. La mayoría de los microcontroladores tienen una capacidad de memoria interna extremadamente limitada, como ya hemos comentado.

    Para conseguir este almacenamiento extra utilizaremos las tarjetas flash (SD, microSD). Estás tarjetas permiten almacenar varios GBytes de datos en un espacio muy reducido.
    Para conectarla al Arduino, podemos usar un módulo SD como el siguiente:

    Sistemas Operativos Integrados

    Para conocer un poco más sobre el funcionamiento de los Embedded Operating Systems, me di a la tarea de investigar sobre ellos, y buscar algunos ejemplos interesantes para poder vincularlos a sus aplicaciones. 


    En este post se hablará sobre los sistemas operativos integrados, que son, como funcionan, y algunos ejemplos de ellos.


    Sistema Operativo Integrado

    Un sistema operativo integrado es un sistema operativo para sistemas integrados de computadora. Estos sistemas están diseñados para ser compactos, eficientes, y confiables, olvidando muchas funciones que los sistemas operativos no integrados proporcionan, ya que no serán usadas por las aplicaciones especializadas que corren. Son también frecuentemente llamados sistemas operativos de tiempo real(Real Time Operating System).
    Una diferencia importante entre los sistemas operativos integrados y los de escritorio es que la aplicación, incluyendo el sistema operativo, esta usualmente vinculada estáticamente junto a una sola imagen ejecutable.
    También, al contrario de los sistemas operativos de escritorio, los sistemas operativos integrados no cargan y ejecutan aplicaciones. Esto significa que el sistema solo puede correr una sola aplicación.

    Entonces, un sistema operativo integrado realiza un propósito muy específico a la exclusión de otras funciones. Estos sistemas son encontrados típicamente en equipo independiente como las máquinas ATM o sistemas de navegación. Un sistema operativo integrado normalmente corre una pieza específica de programación, como el sistema de dirección de un cohete y nada más.
    Un sistema operativo integrado la mayoría de veces es una parte de un sistema integrado más grande. Estos sistemas son de propósito reducido y función fija. Este tipo de sistemas se centra en chips microcontroladores. Estos chips funcionan como una pequeña computadora, tomando información, procesandola y entonces produciendo una salida de información. A diferencia de una computadora normal, un típico microcontrolador solo puede hacer una sola cosa. 

    Generalmente, para que un sistema integrado pueda garantizar un sistema operativo necesita por lo menos una de dos cosas: complejidad o interactividad. Un sistema complejo necesita tomar información de diferentes fuentes, realizar múltiples operaciones o producir diferentes salidas de información basado en la situación. En esencia debe de poder realizar múltiples tareas.


    El otro requerimiento común es la interactividad. Si un usuario tiene que interactuar con la operación, especialmente si la operación depende de tiempo, usualmente tendrá un sistema operativo integrado. Ya que el controlador estándar simplemente toma y envía datos, cualquier momento que un usuario necesita interactuar con la información un sistema mas complejo es necesario.

    Algunos Sistemas Operativos Integrados

    • Embedded Linux
    Embedded Linux es el uso de Linux en sistemas integrados, como teléfonos celulares, PDAs, reproductores mp3, y otros dispositivos de consumidor, equipo de redes, control de maquinara, automatización industrial, equipo de navegación e instrumentos médicos.
    El sistema operativo con Embedded Linux más conocido, es probablemente Android.
    Las ventajas de Embedded Linux sobre otros sistemas operativos integrados incluyen que existen múltiples proveedores de software, desarrollo y soporte; no hay cargos por licencias, cuenta con un kernel estable, y su habilidad de leer, modificar y redistribuir el código fuente. 

    Las desventajas incluyen una huella de memoria comparativamente grande(el kernel y el sistema de archivos root), la obligación de GPL para compartir las modificaciones, complejidades del acceso a memoria del modo usuario y el modo kernel, y el complejo framework de drivers de dispositivos.

    • Windows CE
    Microsoft Windows CE, conocido también como WIndows Embedded Compact o Windows Embedded CE,  es un sistema operativo desarrollado por Microsoft para sistemas integrados. WIndows CE es un kernel y sistema operativo distinto, en vez de una versión ligera del Windows de escritorio. La versón actual de WIndows Embedded Compact soporta Intel x86 y es compatible con procesadores MIPS y ARM.
    Windows CE esta optimizado para dispositivos que tienen almacenamiento escaso. Un kernel de Windows CE puede correr en un megabyte de memoria. Los dispositivos son frecuentemente configurados sin un almacenamiento de disco, y pueden ser configurados como sistemas cerrados que no permiten extensiones de los usuarios. 

    Muchas plataformas han estado basadas en el núcleo de Windows CE, incluyendo el AutoPC, PocketPC 2002, Windows Mobile 2003, Windows Mobile 203 SE, Windows Mobile 5.0, Windows Mobile 6, Zune, Windows Phone
    y demás.

    Una característica distintiva de Windows CE comparandolo con otros stemas operativos es que una gran parte de Windows CE esta disponible en forma de código fuente. Primero, el código fuente fue ofrecido a diversos vendedores, para que pudieran ajustarlo a su hardware. Sin embargo, algunos compontentes importantes que no requieren adaptación a específicos ambientes de hardware siguen siendo distribuidos en forma binaria solamente.

    • VxWorks
    VxWorks es un sistema operativo de tiempo real que puede ser usado en sistemas integrados. VxWorks puede ser personalizado fácilmente y puede correr en la mayorá de los procesadores diseñados para la computación distribuida.

    VxWorks es usada para control de redes y dispositivos de comunicación, pruebas y equipo de medición, periféricos de computadora, sistemas automotivos, aviónicos, equipo y productos de consumo diverso. El sistema operativo incluye un kernel para multitasking preventivo, respuesta a interruptores, comunicación de interprocesos y sistema afiliado.

    • μClinux 
    μClinux era una bifurcación del kernel de Linux para microcontroladores(en sistemas integrados) sin unidad de manejo de memora(MMU). 

    La diferencia principal entre μClinux y otros sistemas Linux es la falta de manejo de memoria. En Linux, el manejo de memora es logrado mediante el uso de memoria virtual. μClinux fue creado para sistemas que no soportan memoria virtual. Entonces, es normal escuchar el término NOMMU cuando se habla de μClinux.

    Sin la memoria virtual, cada proceso debe estar localizado en un lugar en memoria donde pueda ser ejecutado. En el caso más simple, esta área de memoria debe ser contigua. Generalmente no puede ser expandida debido a qu epuede haber otros procesos encima. Esto snigifca que un proceso en μClinux no puede incrementar el tmaaño de su memoria disponible mientras esta corriendo, algo que un proceso tradicional de LInux podría hacer.

    Sin la memoria virtual, swawp es efectivamente imposible, aunque esta limitación es raramente un problema en los sistemas que corren μClinux, ya que por lo general no cuentan con suficiente memoria para hacer que el swap valga la pena. 

    Ports:
      • DSLinux:
    DS Linux es un port del sistema operativo Linux para el Nintendo DS. DSLinux corre una versión modificada de μClinux. Esta basada en uCLinux 2.6.14. Solo corre en modo de texto y nano-x que es mostrado usando un driver de consola personalizado. Un teclado es mostrado en la pantalla touch del Nintendo DS para permitir la entrada de información.
    DSLinux es compilado usando un compilador cruzado basado en GCC para procesadores ARM. DSLinux es en teória capaz de correr cualquier aplicación que tenga una interfaz de usuario basada en framebuffer.
    Con la excepción del micrófono(que funciona, pero el driver esta incompleto), todo el hardware dentro del Nintendo DS incluyendo el adaptador inalámbrico esta soportado por DSLinux. El firmware del Nintendo DS puede ser leido desde /dev/firmware, pero el soporte para escritura dejado fuera por motivos de seguridad.
    DSLinux soporta guardar archivos en una variedad de dispositivos de hardware agregados, ninguno de los cuales es oficialmente aprobado por Nintendo. DSLinux puede almacenar arhivos en la memoria SRAM encontrada en los Flash Carts del Game Boy Advance y en tarjetas CompactFlash y SD.
    El Nintendo DS no tiene unidad de manejo de memoria, y solo tiene 4 MB(o 16MB en versiones más actuales) de RAM pero todas las unidades están limitadas por el viejo procesador ARM 7 y ARM9 do que corren. 
      • PSXLinux
    PSXLinux también conocido como Runix, es un kernel de Linux y un kit de desarrollo para el PlayStation. PSXLinux está basado en el kernel 
    μClinux 2.4.x, y contiene soporte específico para el Sony Playstation.
    Debido a que el PlayStation no ofrece manera para que un usuario ejecute su propio código, se debe hacer una solución para poder ejecutar Runix en hardware PlayStation. Existen dos métodos principales: ejecución mediante un dispositivo de terceros conectado al puerto paralelo de la consola, o mediante un CD especialmente diseñado que contenga los datos ejecutables, los cuales no se ejecutarían normalmente en una consola.
      • iPodLinux
    iPodLiinux es una distribución de Linux basada en μClinux diseñada especialmente para correr en el iPod de Apple. Cuando el kernel de iPodLinux es booteado, toma el lugar del sistema operativo del iPod y automáticamente carga Podzilla, una interfaz alternativa y el lanzador de un número de adicionales programas incluidos como reproductor de video, visor de imágenes, línea de comandos, juegos, emuladores para video juegos, demos de programación, y otros software experimentales.
    iPodLinux es en esencia un kernel de Linux construido desde código de 
    µClinux usando la librería estándar uClibc con el código de drivers para los componentes del iPod. 
    Además del kernel, iPodLinux cuenta con aplicaciones podzilla y podzilla2 como componentes primarios, que proveen lo siguiente:
      • Interfaz de usuario similar a la de iPod.
      • Playback de Video con sonido.
      • Soporte para playback de AAC, MP3 Y OGG básico.
      • Variedad de juegos, incluyendo TuxCHess, Bluecube, Chopper, StepMania.
      • Grabación de sonido mediante el conector de audio(con una mayor calidad que el original de Apple)-
      • Habilidad para jugar los juegos Doom y Doom II
      • Soporte para esquema de colores
      • Habilidad para correr muchos emuladores como: iBoy, iNES, iDarcNES, iMame, iGPSP.

    • RTLinux
    RTLinux es un sistema operativo de tiempo real que ejecuta Linux como un thread (hilo de ejecución) de menos prioridad que las tareas de tiempo real. Con este diseño, las tareas de tiempo real y los manejadores de interrupciones nunca se ven retrasados por operaciones que no son de tiempo real.
    La primera versión de RTLinux estaba diseñada para ejecutarse en la plataforma x86 y proporcionaba una pequeña API y un pequeño entorno de programación. La versión 2, que fue totalmente reescrita, fue diseñada para el soporte de multiprocesamiento simétrico (SMP) y para ser ejecutada en una amplia variedad de arquitecturas.


    RTLinux proporciona la capacidad de ejecutar tareas de tiempo real y manejadores de interrupciones en la misma máquina que el Linux estándar. Estas tareas y los manejadores ejecutan cuando se necesitan en detrimento de lo que estuviera ejecutando Linux. El peor caso de tiempo es entre que se detecta la interrupción hardware y el procesador ejecuta la primera instrucción del manejador de la interrupción. Este tiempo es del orden de los 10 microsegundos en la plataforma x86.


    Referencias:

    domingo, 15 de abril de 2012

    Domótica y Ambientes Inteligentes

    Trabajando con sistemas integrados es común escuchar el término de domótica. En la clase y laboratorio hay un grupo de personas que actualmente están trabajando en realizar diferentes proyectos que están enfocados en esa área, como el control de aire acondicionado, regulación del flujo de agua y otros proyectos interesantes, por lo que decidí investigar un poco al respecto.

    Domótica

    Se entiende por domótica el conjunto de sistemas capaces de automatizar una vivienda, aportando servicios de gestión energética, seguridad, bienestar y comunicación, y que pueden estar integrados por medio de redes interiores y exteriores de comunicación, cableadas o inalámbricas, y cuyo control goza de cierta ubicuidad, desde dentro y fuera del hogar. Se podría definir como la integración de la tecnología en el diseño inteligente de un recinto cerrado.


    La automatización de la casa puede incluir control centralizado de la luz, ventilación, calentamiento y el aire acondicionado, además de otros sistemas, para mejorar el confort, eficiencia de energía y la seguridad. También existe un tipo de domótica dedicado a las personas ancianas y discapacitadas que puede proveer una calidad de vida mejorada para las personas que de otra manera requieren de enfermeras u otro tipo de cuidado.

    Un sistema como este requiere circuitos eléctricos integrados unos con otros dentro de una casa. Las técnicas empleadas incluyen no solo las mencionadas anteriormente, sino también el control de actividades domésticas como los sistemas de entretenimiento, regado de plantas, alimentación de mascotas, cambiar el ambiente para diferentes eventos, y el uso de robots domésticos. 



    Los dispositivos pueden ser conectados mediante una red de computadoras para permitir el control mediante una computadora personal, y pueden ser usadas remotamente a través de internet. Mediante la integración de las tecnologías de información, estos sistemas pueden comunicarse de una manera integrada lo que resulta en beneficios en la seguridad y la eficiencia de la energía.

    Ya que el número de dispositivos controlables en una casa aumenta, la interconexión y comunicación se convierte en una característica conveniente y deseada. Por ejemplo, una chimenea puede enviar un mensaje de alerta cuando necesita limpieza, o un refrigerador cuando necesita reparación. Los cuartos pueden ser inteligentes y enviar señales al controlador cuando alguien entra. Si se supone que nadie debería estar en la casa y la alarma es activada, el sistema llamaría al dueño, los vecinos o a un número de emergencia.

    En instalaciones simples esto puede ser tan simple como prender los focos cuando una persona entra en un cuarto. Por otro lado, en sistemas avanzados los cuartos pueden sentir no solo cuando una persona esta dentro, sino saber quien es esa persona y quizás ajustar la luz, temperatura, niveles de música o canales de televisión, tomando en cuenta el día de la semana, la hora del día y otros factores.

    Otras tareas automáticas incluyen activar el aire acondicionado para ajustarlo a un modo de ahorro de energía cuando no haya personas en la casa, y volviendo al modo normal cuando una persona esta por volver. Algunos sistemas más sofisticados pueden mantener un inventario de productos, grabando su uso mediante códigos de barra, o una etiqueta RFID, y preparar una lista de compras o hasta ordenar reemplazos automáticamente.

    La domótica también provee una interfaz remota para los aparatos caseros o la automatización del sistema en sí mediante una línea de teléfono, transmisión inalámbrica o el internet, para permitir el control y monitoreo mediante un smartphone o un navegador web.



    Un ejemplo de monitoreo remoto en la domótica puede referirse a un detector de incendios, que detecta cuando hay una posible alerta de incendio, haciendo que todas las luces de la casa parpadeen para informar de una posible alerta de incendio. Si el la casa esta equipada con un home theatre, un sistema con automatización en casa puede apagar todos los componentes de audio y video para evitar distracciones, o para hacer un anuncio de emergencia. El sistema puede también llamar al dueño de la casa a su número de celular para alertarlo, o llamar al departamento de bomberos.

    En términos de automatización de luz en la casa, es posible ahorrar energía instalando varios productos. Con funciones simples como sensores y detectores de movimiento integrados en un simple sistema, se pueden ahorrar horas de energía desperdiciada en aplicaciones residenciales y comerciales.

    Arquitectura

    Desde el punto de vista de donde reside la inteligencia del sistema domótico, hay varias arquitecturas diferentes:
    • Arquitectura Centralizada: un controlador centralizado recibe información de múltiples sensores y, una vez procesada, genera las órdenes oportunas para los actuadores.
    • Arquitectura Distribuida: toda la inteligencia del sistema está distribuida por todos los módulos sean sensores o actuadores. Suele ser típico de los sistemas de cableado en bus, o redes inalámbricas.
    • Arquitectura mixta: sistemas con arquitectura descentralizada en cuanto a que disponen de varios pequeños dispositivos capaces de adquirir y procesar la información de múltiples sensores y transmitirlos al resto de dispositivos distribuidos por la vivienda, por ejemplo, aquellos sistemas basados en Zigbee y totalmente inalámbricos.

    Aplicaciones


    Podemos dividir las funciones o servicios que se ofrecen en cinco subgrupos:

    1. Ahorro Energético

    El ahorro energético es un concepto al que se puede llegar de muchas maneras. En muchos casos no es necesario sustituir los aparatos o sistemas del hogar por otros que consuman menos sino una gestión eficiente de los mismos.
    • Climatización: programación y zonificación.
    • Gestión eléctrica:
      • Racionalización de cargas eléctricas: desconexión de equipos de uso no prioritario en función del consumo eléctrico en un momento dado
      • Gestión de tarifas, derivando el funcionamiento de algunos aparatos a horas de tarifa reducida
    • Uso de energías renovables
    2. Confort

    El confort conlleva todas las actividades que se puedan llevar a cabo que mejoren el confort en una vivienda. 


    • Iluminación:
      • Apagado general de todas las luces de la vivienda
      • Automatización del apagado/ encendido en cada punto de luz.
      • Regulación de la iluminación según el nivel de luminosidad ambiente
    • Automatización de todos los distintos sistemas/ instalaciones / equipos dotándolos de control eficiente y de fácil manejo
    • Integración del portero al teléfono, o del videoportero al televisor
    • Control vía Internet
    • Gestión Multimedia y del ocio electrónicos
    • Generación de macros y programas de forma sencilla para el usuario.
    3. Seguridad 

    Consiste en una red de seguridad encargada de proteger tanto los bienes patrimoniales como la seguridad personal.



    • Alarmas de intrusión (Antiintrusión): Se utilizan para detectar o prevenir la presencia de personas extrañas en una vivienda o edificio.
      • Detección de un posible intruso
      • Cierre de persianas puntual y seguro
      • Simulación de presencia
    • Alarmas de detección de incendios, fugas de gas, escapes de agua, concentración de monóxido de carbono.
    • Alerta médica. 
    • Acceso a Cámaras IP.

    4. Comunicaciones

    Son los sistemas o infraestructuras de comunicaciones que posee el hogar.



    • Control remoto desde Internet, PC, mandos inalámbricos(smartphones, PDA con WiFi).
    • Asistencia remota
    • Mantenimiento remoto
    • Informes de consumo y costes
    • Transmisión de alarmas.
    • Intercomunicaciones.
    5. Accesibilidad

    En la accesibilidad se incluyen las aplicaciones o instalaciones de control remoto del entorno que favorecen la autonomía personal de personas con limitaciones funcionales, o discapacidad.
    La domótica aplicada a favorecer la accesibilidad es un reto ético y creativo pero sobre todo es la aplicación de la tecnología en el campo más necesario, para suplir limitaciones funcionales de las personas. El objetivo de estas tecnologías es favorecer la autonomía personal. Los destinatarios de estas tecnologías son todas las personas, ya que por enfermedad o envejecimiento, todos somos o seremos discapacitados, más pronto o más tarde.

    Referencias