Las interrupciones en Arduino y otras cosas de bien

interrupciones en Arduino¿Otra semana por aquí? ¡Me alegro! Esta semana la empezamos con las interrupciones. Las interrupciones en Arduino es algo de lo que te hablé hace algún tiempo. Son esos seres ocultos en la placa que actúan como si fuesen The Night’s Watch (Los Guardianes de la Noche) de Game Of Thrones. O como el Ratoncito Pérez, si quieres ser más de esta zona 😉

¿Qué son las interrupciones?

Hasta ahora te he explicado pequeños proyectos que no necesitan de interrupciones…o no mucho. Pero si quieres hacer proyectos más grandes son recomendables. ¿Por qué?

  • Evitan que la placa esté en funcionamiento todo el tiempo
  • Al tener menos carga, hay menos consumo energético
  • Nos dan el poder de estar en dos lugares a la vez

Y es que las interrupciones serían el sustituto de esto:

void setup() {

}

void loop() {

  while(digitalRead(9)){}
    
  /*Resto de codigo despues de darse la condicion*/
    
}

¿Ves cómo te impide hacer otras cosas? Lo que haces es leer el valor del pin digital 9. Mientras valga 1 (recibas 5 Voltios) no va a hacer nada, ya que dentro de las llaves del while no hay NADA. Una vez llegue un cero, entonces se ejecuta el resto de código que te queda. Este cero que llega puede ser de un sensor que siempre da 5 Voltios excepto cuando sucede algo. Algo similar a  lo que viste con el comparador.

Allí lo que hice fue utilizar un sensor magnético y tenía un amplificador operacional que me marcaba un límite. Si se superaba enviaba a una tensión a Arduino y si no lo hacía enviaba otra. Pues esto…esto es de lo más común. No vas a estar malgastando tiempo mirando si llega o no llega la señal, cuando tendrías que estar moviendo un motor, o encendiendo unos leds o que sé yo.

Por eso lo que hacen las interrupciones es, cuando se da el cambio que queremos, ejecutan un pequeño código. Digo pequeño porque es como debería ser. Imagínate que el programa está en un punto y salta la interrupción. Lo que pasa es que va hasta la interrupción, hace lo que tiene que hacer y vuelve al punto en el que estaba. Claro, si es muy largo el código que hay en la interrupción casi que no te sirve de nada y encima te jode lo que estabas haciendo.

Y si el tiempo es una variable importante…¡ya ni te cuento! Por eso, el código que pongas en la interrupción debe de ser corto, muy corto. Y nada de delays, están totalmente prohibidos. Cómo mucho la función delayMicroseconds() que espera una serie de milisegundos. Y aún así te miraría mal si la utilizases.

Attach y detach una interrupción

Bueno, pues la forma de una interrupción es esta:

void setup() {
  attachInterrupt(0, interrupcion, RISING);
}

void loop() {
    
  /*Codigo a realizar*/
    
}

void interrupcion(){
  /*Codigo a realizar cuando suceda lo que queremos*/
  
}

Como puedes ver aquí hay tela. Lo primero es la primera línea dentro del setup. Esto lo que hace es adjuntar (sí sí, como en los e-mails) la interrupción. Esto se hace en el setup porque se hace una vez y basta. Aunque, existe la función:

detachInterrupt(0);

Esto es porque puede darse el caso de que en un momento concreto no necesites a la interrupción. Si, por ejemplo la interrupción detecta cuando un imán se está acercando y cuando lo hace muestra un mensaje por una pantalla LCD (son pantallas rollo la de los móviles, podrías montar el juego de la Snake en ellas si te lo propusieras) puede que, si soy un poco cabrón, y separo el imán y lo vuelvo a poner rápido el proceso de escritura se vea perjudicado.

Entonces, podría hacer una espera dentro de la interrupción. O bien, cuando llega el proceso de escritura, eliminar temporalmente la interrupción. De manera que no acuaría mientras se escribe en la pantalla LCD y luego volverías a escribir el attachInterrupt.

Claro, para esto podrías utilizar una variable que se activase con la interrupción y que produjese la escritura en el LCD en el loop. Para esto, necesitas conocer las variables volátiles.

volatile int chivato = 0;

Como ves, se declara igual que una variable normal pero se le añade la palabra volatile delante. Esto se hace para guardar esta variable en la memoria RAM y que pueda acceder la interrupción a ella. Digamos que sino se guarda en una cosa llamada registro y está como encerrada. Si se guarda en volátil es más general y cualquiera puede acceder a ella. ¿Por qué no hacerlas todas volátiles? No te líes, que la memoria RAM de estos chismes no es para echar cohetes.

Pines de interrupciones en Arduino

Bueno, volviendo al código de la interrupción, lo siguiente que veíamos en el attachInterrupt era un cero. Ese cero corresponde al número de interrupción. Y cada número de interrupción tiene asociado un pin. De hecho, como es una cosa que depende del chip interno de Arduino, los pines cambian incluso dentro de la familia Arduino:

Placa int.0 int.1 int.2 int.3 int.4 int.5
Uno, Ethernet 2 3
Mega2560 2 3 21 20 19 18
Leonardo, Micro 3 2 0 1 7

Como ves, si tienes el Arduino UNO la interrupción 0 corresponde con el pin 2, pero si tienes el Leonardo (que ya no se fabrica) corresponderá con el pin 3. Si sigues mirando la función attachInterrupt verás que el siguiente campo es un nombre. No es más que la función que has creado para la interrupción.

Es el lugar dónde has puesto el código que quieres que se haga durante la interrupción. Yo, en un ataque de originalidad lo he llamado interrupcion pero puedes llamarle ‘pendejo‘ si es lo que quieres. Eso sí, cuando declares esta función ten en cuenta que debe de ser un void y además que no debe de tener nada en los paréntesis. Ni se recibe ni se envía nada. Esa es otra razón por la que se utilizan las variables volátiles 😉

RISING y FALLING en interrupciones, ¡qué dolor de cabeza!

Por último te queda la última variable que yo he puesto como RISING. Lo siento tío, pero esto si que es más jodido. En Arduino puedes utilizar las palabras RISING, FALLING, CHANGE, LOW y HIGH. Digamos que esto es el modo de la interrupción: el cuándo se tiene que activar.

Bueno, el RISING y el FALLING son los más comunes. RISING significa crecimiento y FALLING decrecimiento. De esta manera, el RISING es cuando de 0 Voltios pasamos a 5 Voltios y el FALLING a la inversa. Es muy útil para la mayoría de sensores que al tener un cambio cambian la tensión que ofrecen.

Por otra parte está CHANGE, que lo que hace es activar la interrupción en cada cambio. Si te paras a pensarlo, una señal cuando va de 0 a 5 Voltios sube, pero luego..cuando el evento que ha hecho que esa señal suba desaparece vuelve a bajar. En los dos primeros modos sólo se tomaba lectura una vez, con éste dos: al subir y al bajar.

Por último están LOW y HIGH. LOW lo que hace es activar la interrupción cuando el valor del pin vale 0 Voltios y HIGH cuando está a 5 Voltios. Lo único es que HIGH solamente lo puedes utilizar si tienes un Arduino Due o un Arduino Zero por lo que, mejor utilizar la función RISING.

Opt In Image

Despedidas con temporizadores

Llegamos al final. Pero antes de despedirnos quería decirte que esto que te he contado son las interrupciones por hardware, pero existen las interrupciones por Timers. Un timer es como una alarma que se pone. Digamos que creamos una interrupción que cada tanto tiempo se dispara y se ejecuta. De esta manera puedes hacer proyectos que sean repetitivos. Esto en sí es complicado en Arduino, pero existe una librería llamada TimerOne que parece resolverlo todo de una manera fácil fácil.

Como yo no la he probado y no te voy a reinventar la rueda porque ya sabes cómo funcionan las interrupciones y cómo debes crear tus gestores de interrupciones (sí sí, que se me olvidaba, a las funciones que creamos para meter el código de la interrupción se les llama gestores) te dejo un post que explica cómo utilizar esta librería maldita.

Así que, si no me necesitas para nada más, me largo. Comparte este post con los botones de ahí abajo para que mueran menos gatitos anda. Y sígueme en Google+ que ahí es dónde hay realmente jaleo! 😉

[Total:9    Promedio:4/5]

Deja un comentario