Imprimir
Categoría de nivel principal o raíz: Arduino
Categoría: Laboratorio ARD
Visto: 1636
Inicio desactivadoInicio desactivadoInicio desactivadoInicio desactivadoInicio desactivado
 

Las interrupciones son un mecanismo muy potente y valioso en procesadores y autómatas. Arduino, por supuesto, no es una excepción. En esta entrada veremos qué son las interrupciones, y como usarlas en nuestro código.

Para entender la utilidad y necesidad de las interrupciones, supongamos que tenemos Arduino conectado a un sensor, por ejemplo encoder óptico que cuenta las revoluciones de un motor, un detector que emite una alarma de nivel de agua en un depósito, o un simple pulsador de parada.

Si queremos detectar un cambio de estado en esta entrada, el método que

hemos usado hasta ahora es emplear las entradas digitales para consultar repetidamente el valor de la entrada, con un intervalo de tiempo (delay) entre consultas.

Este mecanismo se denomina “poll”, y tiene 3 claras desventajas.

Para resolver este tipo de problemas, los microprocesadores incorporan el concepto de interrupción, que es un mecanismo que permite asociar una función a la ocurrencia de un determinado evento. Esta función de callback asociada se denomina ISR (Interruption Service Rutine).

Cuando ocurre el evento el procesador “sale” inmediatamente del flujo normal del programa y ejecuta la función ISR asociada ignorando por completo cualquier otra tarea (por esto se llama interrupción). Al finalizar la función ISR asociada, el procesador vuelve al flujo principal, en el mismo punto donde había sido interrumpido.

Como vemos, las interrupciones son un mecanismo muy potente y cómodo que mejora nuestros programas y nos permite realizar acciones que no serían posibles sin el uso de interrupciones.

 

Para usar interrupciones en dispositivos físicos (como pulsadores, sensores ópticos, … ) debemos antes eliminar el efecto “rebote”.

 

INTERRUPCIONES EN ARDUINO

Arduino dispone de dos tipos de eventos en los que definir interrupciones. Por un lado tenemos las interrupciones de timers (que veremos en su momento al hablar de temporizadores. Por otro lado, tenemos las interrupciones de hardware, que responden a eventos ocurridos en ciertos pines físicos.

Dentro de las interrupciones de hardware, que son las que nos ocupan en esta entrada, Arduino es capaz de detectar los siguientes eventos.

Los pines susceptibles de generar interrupciones varían en función del modelo de Arduino.

En Arduino y Nano se dispone de dos interrupciones, 0 y 1, asociados a los pines digitales 2 y 3.El Arduino Mega dispone de 6 interrupciones, en los pines 2, 3, 21, 20, 19 y 18 respectivamente. Arduino Due dispone de interrupciones en todos sus pines.

 

Modelo INT0 INT1 INT2 INT3 INT4 INT5
UNO 2 3        
Nano 2 3        
Mini Pro 2 3        
Mega 2 3 21 20 19 18
Leonardo 3 2 0 1 7  
Due En todos los pines

 

 

LA FUNCIÓN ISR

La función asociada a una interrupción se denomina ISR (Interruption Service Routines) y, por definición, tiene que ser una función que no recibe nada y no devuelva nada.

Dos ISR no pueden ejecutarse de forma simultánea. En caso de dispararse otra interrupción mientras se ejecuta una ISR, la función ISR se ejecuta una a continuación de otra.

LA ISR, CUANTO MÁS CORTA MEJOR

Al diseñar una ISR debemos mantener como objetivo que tenga el menor tiempo de ejecución posible, dado que mientras se esté ejecutando el bucle principal y todo el resto de funciones se encuentran detenidas.

Imaginemos, por ejemplo, que el programa principal ha sido interrumpido mientras un motor acercaba un brazo para coger un objeto. Una interrupción larga podría hacer que el brazo no para a tiempo, tirando o dañando el objeto.

Frecuentemente la función de la ISR se limitará a activar un flag, incrementar un contador, o modificar una variable. Esta modificación será atendida posteriormente en el hilo principal, cuando sea oportuno.

 

No empleéis en una ISR un proceso que consuma tiempo. Esto incluye cálculos complejos, comunicación (serial, I2C y SPI) y, en la medida de lo posible, cambio de entradas o salidas tanto digitales como analógicas.

 

LAS VARIABLES DE LA ISR COMO “VOLATILES”

Para poder modificar una variable externa a la ISR dentro de la misma debemos declararla como “volatile”. El indicador “volatile” indica al compilador que la variable tiene que ser consultada siempre antes de ser usada, dado que puede haber sido modificada de forma ajena al flujo normal del programa (lo que, precisamente, hace una interrupción).

Al indicar una variable como Volatile el compilador desactiva ciertas optimizaciones, lo que supone una pérdida de eficiencia. Por tanto, sólo debemos marcar como volatile las variables que realmente lo requieran, es decir, las que se usan tanto en el bucle principal como dentro de la ISR.

EFECTOS DE LA INTERRUPCIÓN Y LA MEDICIÓN DEL TIEMPO

Las interrupciones tienen efectos en la medición del tiempo de Arduino, tanto fuera como dentro de la ISR, porque Arduino emplea interrupciones de tipo Timer para actualizar la medición del tiempo.

Efectos fuera de la ISR

Durante la ejecución de una interrupción Arduino no actualiza el valor de la función millis y micros. Es decir, el tiempo de ejecución de la ISR no se contabiliza y Arduino tiene un desfase en la medición del tiempo.

Si un programa tiene muchas interrupciones y estas suponen un alto tiempo de ejecución, la medida del tiempo de Arduino puede quedar muy distorsionada respecto a la realidad (nuevamente, un motivo para hacer las ISR cortas).

Efectos dentro de la ISR

Dentro de la ISR el resto de interrupciones están desactivadas. Esto supone:

CREAR INTERRUPCIONES EN ARDUINO

Para definir una interrupción en Arduino usamos la función:

 

 

Donde interrupt es el número de la interrupción que estamos definiendo, ISR la función de callback asociada, y mode una de las opciones disponibles (Falling, Rising, Change y Low)

No obstante, es más limpio emplear la función digitalPinToInterrupt(), que convierte un Pin a la interrupción equivalente. De esta forma se favorece el cambio de modelo de placa sin tener que modificar el código.

 

 

Otras funcionas interesantes para la gestión de interrupciones son:

Probando las interrupciones en Arduino

Para probar las interrupciones en Arduino, vamos a emplear una salida digital de Arduino para emular una señal digital. En el mundo real, sería otro dispositivo (un sensor, otro procesador…) el que generaría esta señal, y nosotros la captaríamos con Arduino.

Conectamos mediante un cable el pin digital 10 al pin digital 2, asociado a la interrupción 0.

 

Haciendo parpadear un LED a través de interrupciones

En el siguiente código definimos el pin digital 10 como salida, para emular una onda cuadrada de periodo 300ms (150ms ON y 150ms OFF).

Para visualizar el funcionamiento de la interrupción, en cada flanco activo del pulso simulado, encendemos/apagamos el LED integrado en la placa, por lo que el LED parpadea a intervalos de 600ms (300ms ON y 300ms OFF)

Puede que a estas alturas ver parpadear un LED no parezca muy espectacular, pero no es tan simple como parece. No estamos encendiendo el LED con una salida digital, si no que es la interrupción que salta la que enciende y apaga el LED (el pin digital solo emula una señal externa).

 

 

Contando disparos de una interrupción

El siguiente código empleamos el mismo pin digital para emular una onda cuadrada, esta vez de intervalo 2s (1s ON y 1s OFF).

En cada interrupción actualizamos el valor de un contador. Posteriormente, en el bucle principal, comprobamos el valor del contador, y si ha sido modificado mostramos el nuevo valor.

Al ejecutar el código, veremos que en el monitor serie se imprimen números consecutivos a intervalos de dos segundos.

 

 

Lógicamente, nuestro objetivo es emplear interrupciones de hardware no solo con otros dispositivos digitales, si no también con dispositivos físicos como pulsadores, sensores ópticos…

Sin embargo, como hemos adelantado, estos dispositivos generan mucho ruido en los cambios de estado, lo que provoca que las interrupciones se disparen múltiples veces. Este fenómeno se denomina “rebote”.

fuente: luisllamas.es