Fuentes:
Las interrupciones son sucesos que pueden ocurrir en cualquier momento por lo que no podemos prever exactamente cuando detectarlas. Por ejemplo, podemos colocar un sensor en el frente de un vehículo para que detecte a distancia los posibles obstáculos que encuentre en su camino y lo informe a la tarjeta cambiando el estado de un Pin.
Arduino Uno tiene dos de los pines específicos, el Pin 2 y el Pin 3, capaces de detectar interrupciones en cualquier instante, independientemente de lo que en ese momento esté haciendo la función principal “loop”, Cuando Arduino detecta un cambio en el estado de uno de esos pines puede parar el funcionamiento del bucle “loop”donde se encuentre y lanzar una función asociada a esa interrupción inmediatamente, para continuar posteriormente el proceso del bucle “loop” desde donde lo parará.
¿Qué necesitamos para gestionar una interrupción?
volatile
En primer lugar definir previamente una variable del tipo “volatile” . Esta variable se caracteriza por que su valor pueda ser modificado por algo fuera de la sección del código en el que aparece, o sea en una función concurrente. asociadas a interrupciones, tambien llamadas rutina de servicio de interrupción (interrupt service routine).
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.
La sintaxis de “volatile” es: Volatile definición_de_variable
“volatile” indica que la variable que definimos a continuación la cambie siempre que se produzca una interrupción
attachInterrupt
En segundo lugar hay que informar a Arduino que utilizaremos la interrupción lo que hacemos como es habitual en función “setup” con la instrucción “attachInterrupt”. Este mandato especifica la función a invocar cuando se produce una interrupción externa. La mayoría de las placas Arduino tienen dos interrupciones externas: Las número 0 (en el pin digital 2) y la 1 (en el pin digital 3). Arduino Mega tiene otras cuatro: Las número 2 (pin 21), 3 (pin 20), 4 (pin 19) y 5 (pin 18).
La sintaxis de “attachInterrupt” es: attachInterrupt(nint, nfuncion, modo) donde:
“attachInterrupt” avisa a Arduino que vamos a utilizar interrupciones
“nint” número de interrupción. 0 si utilizamos el pin2, 1 si utilizamos el pin 3 “
“nfuncion” nombre de la función que invocamos.
“modo” es el acontecimiento que provoca la interrupción: Los acontecimientos contemplados son:
- LOW (bajo)dispara la interrupción cuando el pin pase a valor bajo (LOW).
- CHANGE (cambio) dispara la interrupción cuando el pin cambia de valor .
- RISING (aumentar) dispara la interrupción cuando el pin pasa de LOW a HIGH
- FALLING (caer) dispara la interrupción cuando el pin pasa de HIGH a LOW
interrupt service routine
Por último tendremos que definir lo que se hace cuando se dispara la interrupción, o sea la rutina de servicio de interrupción o en inglés interrupt service routine.
Esta rutina no admite ni parámetros de entrada ni devuelve nada pues los valores que pudiéramos pasarla a no ser de tipo volatile no están presentes en la memoria RAM del procesador cuando comienza inesperadamente su actuación y por otra parte no tendría sentido entregar parámetros que fuera a utilizar alguien fuera de esta función sin saber si van a existir o no. Por tanto debe ser del tipo void nfuncion () como lo son por ejemplo las funciones “setup” y “loop” que tampoco tienen parámetros ni devuelven nada.
También hay que tener al programarla que los mandatos relacionados con el transcurso del tiempo, no funcionan, pues el ordenador de forma virtual ha interrumpido precisamente el paso del tiempo para “congelar” la función “loop”. Por ello las interrupciones son esencialmente atemporales, y dentro de ellas no funcionan correctamente ni el mandato “delay” que para el programa durante el tiempo que se le indique, ni el mandato “millis” que devuelve el tiempo en milisigundos en que ha estado funcionando Arduino desde que arranco por última vez.
Tambien puede ocurrir y hay que tener en cuenta, que si se envían datos serie desde el exterior, por ejemplo del PC a Arduino, cuando se encuentra “ocupado” con una interrupción, pueden perderse, pues el ordenador está entonces volcado a hacer “otra cosa”, lo que mande hacer la interrupción.
Ejemplo:
int pin = 13;
volatile int estado = LOW;
void setup()
{
pinMode(pin, OUTPUT);
attachInterrupt(0, parpadeo, CHANGE);
}
void loop()
{
digitalWrite(pin, estado);
}
void parpadeo()
{
estado = !estado;
}
Otros comandos:
interrupts()
Descripción: Activa las interrupciones (después de haberlas desactivado con noInterrupts().
Parámetros: ninguno
Devuelve: no devuelve nada
noInterrupts()
Descripción: Desactiva las interrupciones (pueden reactivarse usando interrupts()).
Parámetros: ninguno
Devuelve: no devuelve nada
detachInterrupt(interrupt)
Descripción: Apaga la interrupción dada.
Parámetros: interrupt: el número de interrupción a invalidar (0 o 1).