Felix Maocho

Para quien le interese lo que a nosotros nos interesa

Arduino – Atelier JCM, Capítulo Cinco

Por Félix Maocho 12/7/2013

Finalizo en este post con la traducción comentada de los post de Introducción a Arduino de Ateleier JMCEn este último capítulo el autor nos indica la utilidad del manejo de las interrupciones para registrar cambios muy rápidos de estado en algunos de nuestros pines digitales, Concretamente en Arduino UNO en los Pines 2 y 3. El ejemplo que utiliza es el control de las revoluciones eje de un aparto construido con Meccano. A parte, en el ejemplo que utiliza se manejan, (las para nosotros), nuevas instrucciones y mandatos, explicaré con detalle la sintaxis y utilización de cada una de ellas.

 Introducción al Arduino Capítulo 5

De nuevo  el montaje descrito en la sección Arduino realizaciones.. Permite medir la  velocidad de un motor.

 Nota del traductor

 El montaje a que se refiere el autor es hacer girar una pieza de Maccano de tres agujeros entre medias de un sensor de luz, de modo que la tira (e donde no hay agujero ), corta el rayo de luz que detecta el sensor con dos cambios consecutivos de estado de luz a oscuridad y viceversa muy rápidas antes y después de cruzar la tira (no donde no hay agujero) por delante del sensor. 

El programa publicado hace su trabajo. O más exactamente hace lo que puede para devolver  un  resultado correcto. Es fácil ver que este modo de programar tiene sus límites. Por ejemplo, con una barra de tres agujeros de Meccano que se rota entre un “tenedor de un sensor óptico, o con una rueda de 6 agujeros de Meccano, podemos decir que tenemos un dispositivo analógico de 3 agujeros y que solo precisa de un pequeño cálculo para calcular la velocidad de rotación del eje. La verdad es que no funciona bien, pues ocurre como si los cambios de estado llegaran demasiado rápido, lo que produce frecuentemente resultados falsos. Para comprender lo que sucede, cambiemos de escala de tiempos y el dominio: La telefonista Esta telefonista es una apasionada de la poesía; lee poemas durante casi todo el día y cuando lee, no es cuestión de descolgar el teléfono. Más exactamente el ritmo es la siguiente: 10 minutos de lectura, un minuto tomando llamadas … y así sucesivamente durante todo el día. ¿No sería molesto si interrumpe su lectura en caso de llamada, pero no … ella no quiere oír hablar de eso. Por lo tanto pierde una buena cantidad de llamadas … Bueno de nuevo al Arduino … Cuando la función “loop ()” se ejecuta, Arduino ejecuta un montón de instrucciones que toman su tiempo y no es está en la detección de cambios de estado que puedan producirse: detectar el cambio es el objeto de algunas instrucciones escritas en el programa, pero cuando Arduino ejecuta otras instrucciones, está sorda a los cambios de estado que puedan ocurrir, debe esperar al próximo ciclo para pasar por las instrucciones de “escucha”. Si los acontecimientos se suceden muy rápidamente, capturarlos se convierte en un problema: Arduino puede perder los cambios de estado. Por ejemplo, el Pin 2 se incrementa desde el estado alto al estado bajo, pero el Arduino, que estaba ocupado con otra cosa, no vio nada, no entendió nada. Hay una forma muy elegante de resolver el problema: utilizar las interrupciones de Arduino. De esta forma, aun cuando el programa este ocupado en ejecutar las instrucciones del bucle de la función loop(), se mantiene permanentemente en la búsqueda de cambios.

// Capítulo 5

long chrono = 0; // valor actual del crono
long chrono_depart = 0; // valor de partida del crono
long duree_test = 15000; // prueba por 15 segundos 
volatile long nb_chgt = 0; // númrto de cambios de estado del Pin
void setup () {
  Serial.begin (19200);
  chrono_depart = millis();
//  la interruocion cero correponde al pin 2

// registrará todos los cambios de estado  
  attachInterrupt(0,gere_int0,CHANGE);
}
void loop() {
  chrono = millis ();
// ¿ha terminado la prueba? ?
  
  if (chrono - chrono_depart > duree_test) {
// pequeño truco: hay 4 cambios de estado por vuelta
// la hacer durar la prueba 15 segundos el númrro de cambios 
// tiene el mismo valor que el número de revoluciones por minuto.
              
  Serial.print ("Vitesse : ");
  Serial.print (nb_chgt);
  Serial.println (" trs/min");
// uns vez que se escribe se ejecuta un bucle vacio 
// así tenemos la escritura de la velocidad una sola vez
 
  while (1) {}
  
  }
  
}
// Gestión de la interrupción
void gere_int0() {
    nb_chgt = nb_chgt + 1 ; 
}

} El programa es muy corto … más fácil que el anterior programa propuesto.

Nota del traductor

Este programa se utilizan varias instrucciones nuevas para nosotros, las explico:

long

La primera es la instrucción “long” utilizada para definir una variable que va a ser un número entero muy grande. Es similar a la instrucción ·”int” que utilizábamos hasta el momento para definir una variable o parámetro entera no excesivamente grande, la diferencia reside en que “long” permite definir números enteros entre  – 2,147,483,648 y 2,147,483,647, que necesitan para poder guardarlos  32 bits (4 bytes, de 8 bits) de memoria, mientras que las variables definidas como  “int”. solo permiten guardar  números enteros en un rango entre –32,768 a 32,767, pero que solo necesitan ocupar 16 bits (2 bytes). Puesto que el tamaño de la memoria RAM, que se utiliza para efectuar las operaciones es una de las limitaciones del procesador de Arduino, lo correcto a la hora de definir una variable es seleccionar aquel tipo que ocupe lo menos posible de RAM y sea suficiente para albergar el valor que pueda adquirir nuestra variable.

volatile

La palabra clave “volatile” conocida como variable clasificada (qualifier), se utiliza  delante de un tipo de datos, para modificar la forma en que se va a guardar el valor de la variable en el procesador. Una variable normal, una vez modificada por el programa en la memoria principal RAM, muy escasa y cara, se almacena en una dirección de memoria, mas abundante y barata ROM. Declarar un variable como “volatile” ordenamos al compilador que mantenga permanentemente presente el valor de la variable en la RAM y nos la suministre desde un registro de almacenamiento, ROM. Una variable debe ser declarada “volatile” siempre que su valor pueda ser modificado por algo diferente de la sección del código en el que aparece, como por ejemplo un hilo de ejecución concurrente. En Arduino, esto solo ocurre en secciones de código asociadas a interrupciones, denominadas rutina de servicio de interrupción (interrupt service routine).

millis

La instrucción “millis()” devuelve el tiempo en milisegundos que ha estado encendido Arduino desde que arranco con el programa actual. Este número se desbordará, (y volverá a cero), cuando los milisegundos superen el máximo que puede recoger un entero “long” es decir 2,147,483,647 milisegundos, (aproximadamente 50 días ininterrumpidos de trabajo de un programa).

attachInterrupt

A la función “attachInterrupt” se la invoca automáticamente cuando se produce una interrupción externa, y reemplaza a cualquier otra función que estuviera previsto iniciar a continuación a la interrupción. La mayoría de las placas Arduino tienen dos interrupciones externas: La número 0 (en el pin digital 2) y la 1 (en el pin digital 3). Arduino Mega (otra tarjeta de la familia arduino más potente) tiene otras cuatro mas, las número 2 (pin 21), 3 (pin 20), 4 (pin 19) y 5 (pin 18). 

La sintaxis de esta función es la siguiente : attachInterrupt(interrupcion, funcion, modo)

Donde:

interrupcion es la del pin que vamos a manejar (en nuestro caso la  “0” que se corresponde a un cambio en el Pin2 funcion es el nombre de la función que se invoca cuando se produce una interrupción, esta función no puede tener parámetros ni de entrada ni de salida. En nuestro caso es la función  “gere_int0” que se limita a sumar uno al contador definido como variable “volatile”  nb_chgt (observe como se incrementa el contador ) modo indica la forma en que es disparada la interrupción, hay cuatro modos estandar de hacerlo::

LOW dispara la interrupción cuando el pin se encuentre a valor bajo (LOW). CHANGE dispara la interrupción cuando el pin cambia de valor. RISING dispara la interrupción cuando el pin pasa de valor bajo (LOW) a alto (HIGH). FALLING para cuando el pin cambie de valor alto (HIGH) a bajo (LOW)    

En nuestro caso utilizamos como disparador CHANGE es decir llamará a la función “gere_int0”, (o lo que es lo mismo sumara uno a la variable “volatile” nb_chgt  cada vez que cambie el estado de HAIG a LOW o de LOW a HIGH del Pin2, (o lo que es lo mismo la interrupción 0), es decir cada vez que la tira, (por la parte sin agujero), pase por delante del sensor de luz  el Pin2 pasará de 5 a = volts y vuelta a 5 voltios por tanto contara dos cambios.

while

 La instrucción “while” es una funcion condicional que genera un  bucle (dentro del bucle “loop”), que ejecuta las sentencias contenidas entre corchetes, en tanto que sea cierta la condición contenida entre paréntesis. Algo debe modificar la variable comprobada, o el bucle “while” nunca terminará, evitando que el bucle “loop” finalice . Lo que modifique la variable puede estar en el código, como una variable que se incrementa, o ser una condición externa, como el valor que da un sensor.

En nuestro caso la condición indicada es una constante “1” por tanto nunca cambiara y lo que se hace en “while” se repetirá indefinidamente, y entre corchetes no hay instrucciones, esta vacia, Así pues esta instrucción deja sin finalizar el primer ciclo de loop hasta que desenchufemos Arduino o demos al botón rojo de la tarjeta que la rearranca la. La consecuencia es que el sketch cuenta los cambio de estado del Pin2  durante 15.000 milisegundos, escribe los cambios detectados en la pantalla  y luego no hace nada . O sea, que obtendremos una lectura de la velocidad del motor cada vez que arranquemos la tarjeta.

Cálculo de las revoluciones

Cada vez el extremo la pioeza de Meccano ( que no esta perforado), pase por el sensor se detectan dos cambios, una vuelta completa supone por tanto 4 cambios, El tiempo que tomamos para medir la velocidad es 15 segundos  (15 milisegundos), o sea ¼ de segundo. por tanto el número de cambios detectados, se corresponden a las revoluciones por minuto del motor. Por lo que mandamos escribir ese número en nuestro monitor

En resumen. Podemos elegir entre dos interrupciones, la, 0 y 1. La interrupción cero con el siguiente trabajo a realizar:

  • Seguimiento de los cambios de estado del Pin 2
  • Si cambia, interrumpir inmediatamente el flujo de instrucciones de la función loop ()
  • Disparar la función de nuestra elección (ver la instrucción attachInterrupt())
  • Reanudar la ejecución del bucle loop () donde lo dejó
  • Continuar vigilando los cambios de estado del Pin2  …

La ventaja de esta forma de utilizar las interrupciones es que no se pierde los cambios muy rápidos, la desventaja es que tenemos solamente dos interrupciones posibles la 0 y la 1, respectivamente, que respectivamente el Pin 2 y el Pin 3. Para los eventos lentos, este modo de programación no es obligatorio. Pero es muy interesante de constatar que con esta técnica se puede seguir sin problema los movimientos muy rápidos. Si situamos una ruedas con 6 agujeros en llanta, no hay problema, Arduino sigue el ritmo de los cambios de estado. Una llanta con 8 agujero también trabaja … fui y busqué una rueda de cañón de 10 agujeros, no es muy común, también funciona. Con esta rueda, reduciendo el tiempo de prueba a 3 segundos, se muestra directamente el número de cambios de estado, que es también la velocidad en revoluciones / minuto. Con la reducción del tiempo del test a 1 segundo y la visualización de 3 veces el número de cambios de estado, obtenemos también la velocidad en revoluciones / min. Félix Maocho

Post de esta serie editados en el blog

Todos los post de arduino apareceran en Robótica bajo el subepigrafe Arduino  

Anuncios

23 julio 2013 - Posted by | Robotica | ,

Aún no hay comentarios.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: