You are on page 1of 30

Arduino y las interrupciones | Tutoriales Arduino

TIENDA ARDUINO RASPBERRY PI FORO PROYECTOS CONTACTO

ARDUINO Y LAS INTERRUPCIONES


Gestionando excepciones

Home  Arduino Y Las Interrupciones

OBJETIVOS

     

 Presentar el concepto de Interrupcion en Arduino.


 Conocer los tipos de interrupciones.
 Mostrar los Flags de disparo.
 Consideraciones generales.

MATERIAL REQUERIDO.

Arduino UNO o equivalente.

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

Una Protoboard más cables .

Una resistencia de 330Ω.

Un pulsador.

LAS INTERRUPCIONES

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

Nunca he sabido muy bien que tiene esto de las interrupciones, que hacer temblar a programadores curtidos como si
fueran unos novatos.

Recuerdo que en una época en que nos dedicábamos a los microprocesadores (cuando los dinosaurios dominaban la
tierra) y comenzábamos a jugar con las interrupciones, había un porcentaje de técnicos, ingenieros electrónicos o
informáticos, que aun  comprendiendo la idea de las interrupciones, parecía que su cerebro no podía abarcarlas y
sencillamente las ignoraban elegantemente.

Mentarle las interrupciones a muchos Arduineros ya fogueados, en muchos casos supone que recordarán
inmediatamente la necesidad de salir urgentemente a hacer algo. Nunca he sabido porque pasa esto, pero vamos a
intentar ponerlo remedio inmediatamente.

¿Qué es una interrupción hardware?

A un nivel básico, una interrupción es una señal que interrumpe la actividad normal de nuestro microprocesador y salta a
atenderla. Hay tres eventos que pueden disparar una interrupción:

 
 Un evento hardware, previamente definido.
 Un evento programado, o Timer
 Una llamada por software.

 
Cuando un evento dispara una interrupción, la ejecución normal del micro se suspende (ordenadamente para poder
volver) y salta a ejecutar una función especial que llamamos Interrupt Service Handler o ISH (Servicio de gestión de
interrupción).

Cuando el ISH finaliza, el procesador vuelve tranquilamente al punto donde lo dejó y sigue con lo que estaba como si no
hubiese pasado nada.

 
  El concepto de interrupción nace de la necesidad imperiosa de reaccionar de forma
inmediata en respuesta a un acontecimiento electrónico fulgurante, que no admite demora.
Bien sea por la urgencia del suceso o porque algo se podría perder de forma irrecuperable
sino reaccionamos con suficiente presteza.

Pero ¿Qué hay tan urgente que no pueda esperar? ¿Es que nuestros Duinos no son lo suficientemente rápidos para ver
cada poco si hay una señal de alarma? ¿Por qué complicarnos la vida con una cosa tan extravagante?

La respuesta como siempre es… depende. Nuestro Arduino puede estar liado y solo leerá la señal de un pin de tanto en
tanto. Y si la señal que aparece se desvanece antes de que hayamos ido a ver, ni siquiera lo sabremos, porque aunque
los Duinos son rápidos una señal electrónica lo es varios millones de veces más. Este es otro motivo por el que usar

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

delays tiene mucho peligro.

 
  En la jerga técnica, a pasar de vez en cuando a ver como está el asunto, se le llama Polling.

Por otro lado las interrupciones nos ofrecen una ventaja enorme a la hora de organizar nuestro programa. Se define la
función que se ejecutará al recibir una interrupción dada y se ejecuta limpiamente cuando ocurre, no hay que comprobar
si se da o no una situación.

Simplemente te olvidas y se ejecutará única y exclusivamente cuando se alce la interrupción. No me digáis que no es
elegante (SI, es una obsesión).

En realidad, nosotros funcionamos por interrupciones habitualmente, en respuesta a sucesos no previstos que nos sacan
de la rutina habitual.

Imagínate que estás viendo tu serie favorita en la tele y estas esperando a tu colega, amigo o novia.

Hay dos maneras de abrirle la puerta. Una es pasar a ver si ha llegada cada, digamos dos minutos, para ver si esta con
cara de pánfilo/pánfila en la puerta esperando a que le abramos.

La otra es establecer una interrupción, para eso están los timbres. Cuando tu compi llega, pulsa el timbre. Tu paras tu
capitulo tranquilamente, dejas el refresco en la mesa y vas a abrirle.

Cuando vuelves con él, reanudas tu peli y recoges el refresco. ¿Qué tienen de raro las interrupciones? ¿Qué me decís
del teléfono o de los Whatsapp? Es la misma idea. Y lo mismo pasa con tu Arduino.

¿Por qué voy a renunciar a las interrupciones y dedicarme a pasar por la puerta cada poco? Es absurdo. Las
interrupciones no tienen nada de extraño ni de incognoscible. Dedícale un poco de tiempo y te encontrarás una
herramienta magnifica que te resolverá limpiamente más de un problema.

TIPOS DE INTERRUPCIONES

De los tres  sucesos que pueden disparar una interrupción

 
 Un evento hardware,
Un evento programado, o Timer

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino


 Una llamada por software.

 
Nos encontramos con que Arduino no soporta las interrupciones por software y punto.

¿Y entonces porque hemos hablado de ellas? Pues, porque otros entornos de programación las aceptan y no será raro
que en el futuro Arduino también.

Los eventos programados o Timers, son muy interesantes y tendrán una sesión monográfica propia en un futuro próximo.
Pero por ahora vamos a meternos con las interrupciones disparadas por hardware.

LAS INTERRUPCIONES POR HARDWARE

Estas interrupciones hardware, se diseñaron por la necesidad de reaccionar a suficiente velocidad en tiempos
inimaginablemente cortos a los que la electrónica trabaja habitualmente y a los que ni siquiera el software era capaz de
reaccionar.

La idea que debéis  que tener en mente es que vamos a definir una función que se ejecutará de forma asíncrona, sin
planificación, cuando se ocurra un cierto suceso electrónico.

Para definir una interrupción necesitamos tres cosas:

  Lo
 Un pin de Arduino que recibirá la señal de disparo
 Una condición de disparo
 Una función que se ejecutará, cuando se dispare la interrupción (Llamada call back
function).

 
primero es un pin de Arduino donde conectaremos el “timbre” de llamada. Dependiendo del modelo Arduino que
tengamos, tendremos varias posibilidades:

MODELO
INT 0 INT 1 INT 2 INT 3 INT 4 INT 5
ARDUINO

UNO Pin 2 Pin 3

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

MEGA 2 3 21 20 19 18

DUE Todos los pines del DUE pueden usarse para interrupciones.

Leonardo 3 2 0 1 7

Esto quiere decir que el Arduino UNO puede definir dos interrupciones hardware llamadas 0 y 1, conectadas a los pines
2 y 3 (Para que no sea fácil).

El Mega como es habitual en él, acepta nada menos que 6 interrupciones diferentes. Y el DUE, muy sobrado, exhibe su
poderío.

En cuanto a la condición de disparo puede ser:

  Si
 LOW, La interrupción se dispara cuando el pin es LOW.
 CHANGE, Se dispara cuando pase de HIGH a LOW o viceversa.
 RISING, Dispara en el flanco de subida (Cuando pasa de LOW a HIGH).
 FALLING, Dispara en el flanco de bajada (Cuando pasa de HIGH a LOW).
 Y una solo para el DUE: HIGH se dispara cuando el pin esta HIGH.

 
nuestra call back function se llama Funcion1 (),  para activar la interrupción usaremos:

attachInterrupt(interrupt, ISR, mode)

Donde Interrupt es el número de la interrupción, ISR será Funcion1 y mode es una de las condiciones que hemos visto
arriba. Así en un Arduino UNO podría ser:

attachInterrupt(0, Funcion1, RISING) ;

Suponiendo que hemos enchufado la señal de interrupción al pin 2 de Arduino. Vamos a ver algún ejemplo de
interrupciones.

ESQUEMA DE CONEXIONES

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

Es una especie de costumbre en Arduino, usar un pulsador para ilustrar el concepto de Interrupción, así que nos
plegáramos a ello. Vamos a utilizar un típico circuito para leer un pulsador con un pullup.

Hasta ahora habríamos escrito el programa para leerlo así,

void setup()
{ pinMode(2, INPUT);
Serial.begin(9600);
}

void loop()
{ bool p = digitalRead(2);
Serial.println(p);
}

El resultado seria normalmente 1, por el pull up y la lectura bajaría a 0, al pulsar el botón. Nada nuevo en esto.

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

Pero vamos a reescribir el programa para  establecer una interrupción en el pin 2 (Interrupción 0) .El programa quedara
más o menos así:

int contador = 0;
int n = contador ;

void setup()
{   Serial.begin(9600);
attachInterrupt( 0, ServicioBoton, FALLING);
}
void loop()
{
if (n != contador)
{     Serial.println(contador);
n = contador ;
}
}

void ServicioBoton()
{ contador++ ;
}

En primer lugar fijaros que hemos eliminado la definición de entrada del pin 2, porque no vamos a usarlo como input
estrictamente. Con definir la interrupción es suficiente.

En segundo lugar usamos attachInterrupt() pasándole como parámetros la interrupción 0, que es el pin2 de Arduino
UNO. SI fuese la Interrupción 1, la conectaríamos al pin 3 (Anda que…)

Le pasamos el nombre de la función CallBack ServicioBoton, que es de lo más sencilla. Un variable global contador,
guarda el número de pulsaciones. Lo único que hace la función de servicio es aumentar contador en uno cada vez que
se pulsa y volver.

Y por último el trigger es FALLING porque el estado es normalmente HIGH y baja a LOW al pulsar el botón,  utilizaremos
el disparo con el flanco de bajada, o sea FALLING o LOW.

  El
 Un disparador en inglés es trigger y es el nombre que encontrareis en la jerga técnica.

loop comprueba si el número de pulsaciones ha cambiado y si es así lo imprime, pero puede dedicarse a hacer cualquier
cosa, porque no vamos a perder ninguna pulsación.

Os puede parecer una manera extravagante de hacer las cosas pero no me digáis que no es elegante. De hecho todos
los lenguajes modernos de alto nivel para Windows, Mac o Linux utilizan la programación por eventos que es algo

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

básicamente igual a esto (Salvando las distancias claro).

Cuando veamos la salida en la consola tendremos una sorpresa esperada:

Cuando pulsamos el botón, el número que aparece no aumenta de uno en uno si no a golpes. ¿Por qué?

Pues como ya vimos en su día, se debe a los rebotes del pulsador. Decíamos en la sesión “Condicionales y botones”, que
para eliminar el rebote de los botones, tenemos que hacer el debouncing y allí lo hacíamos con un delay de 250 ms.

Pero vamos a tener un problema. No podemos usar un delay dentro de una interrupción. No funciona. ¿Cómo dice?

Hay varias consideraciones a tener en cuenta con las interrupciones:

 
 Haz lo que quieras pero no te demores. Acaba cuanto antes y lárgate.
 Hay cosas que no funcionan, como las funciones delay (), millis () y cualquier cosa
que dependa de interrupciones o timers.

 Ni se te ocurra meter un Serial.Nada en una interrupción, son muy lentos (Y además


tampoco funcionan porque también dependen de interrupciones).

 Debes entender que una interrupción es como un estado de excepción, que se puede
usar sin reparos, pero entendiendo que hay que hacer el trabajo y salir cuanto antes.

 De hecho, una ISR o función CallBack, no puede devolver parámetros ni tampoco


recibirlos

 
Además cuando definimos una variable global como contador, de la que depende una función ISR, se recomienda
definirla como volatile y no como una global normal.

  Si
 Estrictamente hablando, volatile no es un tipo de variable, sino una directiva para el
compilador.

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

 Eso significa que la variable en cuestión, debe ser almacenado de un cierto modo que
evite algunos problemas raros que pueden surgir cuando una variable puede ser
cambiada por el ISR o por el programa (algo que no ocurre en nuestro ejemplo).

 Bajo ciertas circunstancias puede surgir un conflicto y volatile lo evita y por eso se
recomineda hacerlo así siempre.

 
necesitas un retraso para algo, o sea , un delay, siempre es mejor, comprobar el tiempo transcurrido y decidir si se toma
la acción o no. Veamos otro ejemplo

volatile int contador = 0; // Somos de lo mas obedientes


int n = contador ;
long T0 = 0 ;  // Variable global para tiempo

void setup()
{ pinMode(2, INPUT);
Serial.begin(9600);
attachInterrupt( 0, ServicioBoton, LOW);
}
void loop()
{   if (n != contador)
{   Serial.println(contador);
n = contador ;
}
}
void ServicioBoton()
{
if ( millis() > T0  + 250)
{   contador++ ;
T0 = millis();
}
}

En primer lugar definimos contador como volátil, por prescripción médica, y definimos otra variable global T0 para
almacenar el tiempo a partir del cual contaremos.

En la ISR la diferencia es que comprobamos si el valor actúan de millis es mayor en 250 ms a la última vez que paso por
la interrupción. Si no es así, lo consideramos un rebote y lo ignoramos olímpicamente. Por el contrario si ha pasado un
tiempo prudencial incrementamos contador.

La ventaja d este sistema es que no congelamos el procesador con un delay, si no que le dejamos seguir con su trabajo,
atendiendo otras interrupciones, por ejemplo.

Pero….Un momento… No habíamos dicho que millis() no funciona en las interrupciones.

Así es. Mientras una interrupción esta activa millis está congelada y su valor no cambiará, pero sigue pudiéndose leer.

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

 
 Mientras estas dentro de una interrupción, todas las demás interrupciones, son
ignoradas, por eso, nada que dependa de otras interrupciones funciona.

 Por eso es importante salir pronto, para garantizar que no nos perdemos nada de
interés.

 Mientras una interrupción está activa, millis() y micros()se congelan. Eso quiere decir
que si tienes unos cuantos miles de interrupciones por segundo (Como si estas
midiendo la frecuencia de una onda de audio) tu medida de tiempo con millis o micros
se puede ver distorsionada.

 
Por ultimo os conviene saber que existen algunas otras instrucciones relativas a las interrupciones:

   
 noInterrupts(), Desactiva la ejecución de interrupciones hasta nueva orden.
 Interrupts(), Reinicia las interrupciones definidas con attachInterrupt().
 detachInterrupt( num Interrupt), Anula la interrupción indicada.

RESUMEN DE LA SESIÓN

     

 Hemos conocido el motivo y el concepto de las interrupciones.


 Hemos empezado por estudiar las interrupciones hardware, dejando los Timers para
futuras sesiones.

 Vimos que en Arduino UNO solo disponemos de 2 interrupciones llamadas 0 y 1 en


los pines 2 y 3 respectivamente.

 Vimos los posibles disparos de una interrupción por flanco de subida, bajado o LOW.

 
Anterior Siguiente
 

« COMENTARIOS MÁS VIEJOS

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

(109) Comments

Victor Gozalo 28 Feb 2017


Buenas tardes,
Ante todo gracias por tu ejemplo. Pero estoy intentando hacer algo similar pero un lugar de con
Reply un pulsador con otro sistema. Tengo conectado por cable USB el Arduino UNO al ordenador y lo
unico que hago es leer del puerto serie si recibo un 1 o 0 sobre el pin 2 de (que lo he definido de
entrada), pero me va variando los valores 0 a 1 constantemente e incluso sin tener nada
conectado al pin 2. Es normal? puede ser que el USB le de algun tipo de ruido?

int leer_tpv=0;
int escribir_tpv=0;
int led_salida_cafe=13;
int led_entrada_cafe=2;
int estado_cafe=0;

void setup() {
pinMode(led_salida_cafe,OUTPUT);
pinMode(led_entrada_cafe,INPUT);

Serial.begin(9600);

void loop() {
int leer_tpv=Serial.read() – ‘0’;
switch (leer_tpv) {
case 1://el tpv envia desbloquear molino cafe
digitalWrite(led_salida_cafe,HIGH);
break;
case 2: //el tpv envia bloquear molino cafe
digitalWrite(led_salida_cafe,LOW);
break;
default:
break;
}

estado_cafe=digitalRead(led_entrada_cafe);
Serial.println(estado_cafe);
delay(500);

Ivan 03 Mar 2017

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

Hola Victor, si tratas de leer un pin al que no tengas nada conectado, el valor fluctúa
constantemente. De ahí las lecturas de 0 y 1 sin aparente sentido. UN saludo.
Reply

Andres 16 Feb 2017


Hola, Te queria preguntar si de casualidad no tienes un tutorial de RTOS en arduino.

Reply

admin 16 Feb 2017


Hola Andres, no tengo nada porque hasta la fecha no he dedicado tiempo al tema, pero reconozco que
es de lo mas interesante
Reply

Sergio 08 Ene 2017


Hola buenas, ¿qué pines se pueden usar para interrupciones en el Nano?
Muchas gracias.
Reply

Ivan 09 Ene 2017


Holoa Sergio, el nano usa los pines 2 y 3 para las interrupciones. Un saludo.

Reply

Giovanny González 12 Feb 2017


Buena tarde.
Excelente tutorial. Gracias por compartir.
Reply Se me presenta el siguiente inconveniente al contar los pulsos de un pulsador por interrupciones. He
usado falling como parámetro para la interrupción. En Setup, defino const int boton = 2; , y luego
activo las pull up internas mediante pinMode(boton, INPUT_PULLUP); coloco el tiempo de
enmascaramiento dentro de la interrupción en 250 ms, y he ensayado con valores desde 100 hasta
1200 ms.
Cuando oprimo el botón y lo suelto rápidamente efectivamente cuenta y retorna al programa normal.
Pero cuando lo mantengo oprimido algún tiempo (tal vez mas de un segundo), vuelve a contar al
soltarlo duplicando la cuenta y presentando números errados.
¿Me podeis dar alguna luz de por que ocurre esta situación?
Gracias de antemano…

Reply
admin 13 Feb 2017

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

Hola Giovanny, en primer lugar no debes hacer delay dentro de las interrupciones porque
simplemente no funcionan como esperas. No use delays dentro de las rutinas de servicio de
las interrupciones vale.

En cuanto al tema e que cuenta de mas, te recomiendo hacer algunas pruebas con disparo por
Falling y rising porque a veces puedes tener una idea equivocada de lo que pasa (Nos pasa a
todos) pero despues de hacer pruebas de este estilo puede que veas algo de luz ¿Vale?

Pruebalo y me dices

Victor 02 Ene 2017


Muchas gracias por tu rápida respuesta!!, (por cierto, era la primera vez que participaba en un
foro)
Reply Me refiero al programa incluido como ejemplo en el IDE de arduino, dentro de wire, el programa
slave_receiver, de las comunicaciones i2c.
Copio el “receiveEvent” de este programa:
void receiveEvent(int howMany) {
while (1 < Wire.available()) { // loop through all but the last
char c = Wire.read(); // receive byte as a character
Serial.print(c); // print the character
}
int x = Wire.read(); // receive byte as an integer
Serial.println(x); // print the integer
}
Entiendo que lo que hace el esclavo es una interrupción de su loop cuando recibe la orden del
maestro, y que esa interrupción no debería utilizar el "serial.print" y, por lo que he leído, no
conviene declarar variables (en este caso se declara "char c" e "int x"). El serial.print dentro de
la interrupción podría provocar congelaciones aleatorias??
Me gustaría saber que se puede hacer y que no en la interrupción.
Y yendo un poco mas lejos (aunque esto no sería un comentario sobre interrupciones sino sobre
i2c) como puedo evitar que se solapen interrupciones, he visto en tu sesion sobre time que es
algo que no debería ocurrir, pero como eviarlo en las interrupciones de las comunicaciones i2c?.
Concretamente el maestro manda una orden al esclavo, el esclavo la escucha y abandona lo
que está haciendo para hacer la interrupción correspondiente pero… el maestro sigue
trabajando ¿no? puede ocurrir que el maestro de una nueva orden sin que el esclavo haya
terminado de ejecutar la anterior. ¿que se puede hacer para que el maestro sepa que el esclavo
esta ocupado en una orden y que espere antes de enviar la siguiente?.
Lo dicho, muchas gracias y FELIZ AÑO!!

Victor 31 Dic 2016


Hola muchas gracias por el tutorial, está muy bien escrito, es muy didáctico lo podemos entender
también los que sabemos poco de esto.
Reply Tengo algunas dudas sobre lo que se puede hacer y lo que no dentro de las interrupciones.
Concretamente:
1. declarar variables? (el ejemplo incluido en el IDE slave.receiver lo hace con int y char,
además ¿¿no estaba recomendado volatile byte??)

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

2. serial.print? idem comentario del ejemplo del slave receiver, lo hace dentro de interrupción
3. delay()
4. otras???
En el programa que estoy intentando hacer de vez en cuando el programa se cuelga y lo tiene
que reanimar un watchdog. Parece que ocurre en la comunicaciones entre maestro-esclavo,
concretamente PERO SOLO algunas veces, cuando el maestro manda ordenes marcha paro al
esclavo, el problema es que no ocurre siempre, solo de vez en cuando en el mismo punto.
Desde mi inexperiencia tras revisar los foros estoy intentando “limpiar” todo lo posible lo que
hace el esclavo, pero encuentro contradicciones entre las recomendaciones y los ejemplos del
IDE.
MUCHAS GRACIAS

admin 02 Ene 2017


Buenos dias Victor,
Vamos por partes, Puedes declarar las variables que neesites dentro de una funcion de servicio de
Reply interrupcion, pero se perderan para la proxima vez que vuelvas salvo que las declares volatile, pero no
es imprescindible.

No estoy seguro de que programa es el que me mencionas y pero la idea que tengo es que dentro de
una interrupcion no funcionan ni el delay ni las funciones serial ya que ambas dependen a su vez de
otras interrupciones por lo que aun cuando puediesen funcionar (Que creo que no) no seria interesante
de usar

MANNARROD1 29 Dic 2016


Hola buenas, estoy empezando con arduino y tengo el siguiente problema:
tengo un contador en la interrupción similar al del ejemplo, según el valor del contador se
Reply ejecuta una secuencia de leds u otra.
Sólo incremento el contador en la interrupción, pero cuando cada una de las secuencias lleva
unos cuantos ciclos el valor de contador aumenta solo, sin pulsar el pulsador de la interrupción.
Un saludo y muchas gracias de antemano.

admin 30 Dic 2016


Hombre, habria que ver el programa y como disparas la interrupcion para darte una opinion

Reply

tonny 12 Oct 2016


Hola… me ha gustado la explicación y es justo lo que estoy buscando… tengo un problema a la
hora de usar el “attachInterrupt” y es que estoy usando un kit para impresoras 3D (arduino mega
Reply 2560 R3, ramps 1.4 y full graphic smart controller) y estoy intentando controlar el encoder que
viene con la pantalla(full graphic smart controller), ya he comprobado que los pines del encoder
sean los correctos (CLK->33, DT->31, SW->35), tengo el siguiente código pero cuando muevo
el encoder no se ejecuta la función de la interrupción.

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

He probado más códigos usando “attachInterrupt” o “attachPinChangeInterrupt” y más simples


pero igual no me funciona. Alguien podría ayudarme?

#include
#include “U8glib.h”
#include
#include

U8GLIB_ST7920_128X64_1X u8g(23, 17, 16); //SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17

int encoderPinA = 33;


int encoderPinB = 31;
int encoderBttn = 35;

volatile int lastEncoded = 0;


volatile long encoderValue = 0;

long lastencoderValue = 0;

int lastMSB = 0;
int lastLSB = 0;

volatile int pos = 0;


int nA = LOW;
int nB = LOW;
void setup() {
pinMode (encoderPinA,INPUT);
pinMode (encoderPinB,INPUT);
pinMode (encoderBttn,INPUT);
Serial.begin (9600);
digitalWrite(encoderPinA, HIGH); //turn pullup resistor on
digitalWrite(encoderPinB, HIGH); //turn pullup resistor on
digitalWrite(encoderBttn, HIGH); //turn pullup bttn on

//call valorPos() when any high/low changed seen


//on interrupt 0 (pin 33), or interrupt 1 (pin 31)
PCintPort::attachInterrupt(encoderPinA, valorPos, CHANGE);
PCintPort::attachInterrupt(encoderPinB, valorPos, CHANGE);

void loop() {
if(digitalRead(encoderBttn)){
//button is not being pushed
}else{
Serial.println(“bttn ON”);
}

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

Serial.println(pos);
delay(500);
nA = digitalRead(encoderPinA);
nB = digitalRead(encoderPinB);

while((nA==1)&&(nB==1)){
//Serial.print (“pinA: “);
//Serial.println (nA);
//Serial.print (“pinB: “);
//Serial.println (nB);
Serial.println(pos);
nA = digitalRead(encoderPinA);
nB = digitalRead(encoderPinB);
};
}

void valorPos(){
Serial.println(“dentro del metodo”);
nA = digitalRead(encoderPinA);
nB = digitalRead(encoderPinB);
if(nA==0){
pos–;
}
if(nB==0){
pos++;
}
}

admin 13 Oct 2016


Hola Tony, es imposible probar tu codigo, pero puedes empezar por algo mas sencillo como comprobar
con un programa que solo controla el encoder, que la interrupciion salta. No hay muchas opciones de
Reply que no salte y si aun asi no salta suele ser:
No has anexado correctamente la calback function
el pin al que conects la salida no acepta interrupciones (No todos lo aceptan)
La condicion de disparo no se alcanza nunca por cualquier razon

Reply
tonny 14 Oct 2016
Hola, o sea que en el arduino mega2560 no todos los pines pueden hacer uso de la librería
PinChangeInt.h?? El mega tiene 53 pines de los cuales los que van conectados al encoder de
la pantalla son el 31,33 y 35 (pines digitales); ya probe otro código (el de abajo) pero igual no
me funciona son ninguno de los pines que estan conectados al encoder; no sé si tenga algo que

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

ver con lo que encontré sobre los pines del mega : Interrupt External ->2 3 and 18-21 ;
Interrupt Pin Change -> 10-15 and A8-A15 and SS, SCK, MOSI, MISO.

Éste código es de los ejemplos de la librería y lo usé pero no pasaba nada cuando movía el
encoder o pulsaba el encoder (usando: #define ARDUINOPIN 35 )

#include

// Modify this at your leisure.


#define ARDUINOPIN 33

// Notice that values that get modified inside an interrupt, that I wish to access
// outside the interrupt, are marked “volatile”. It tells the compiler not to optimize
// the variable.
volatile uint16_t interruptCount=0; // The count will go back to 0 after hitting 65535.

// Do not use any Serial.print() in interrupt subroutines. Serial.print() uses interrupts,


// and by default interrupts are off in interrupt subroutines. Interrupt routines should also
// be as fast as possible. Here we just increment a counter.
void interruptFunction() {
interruptCount++;
}

// Attach the interrupt in setup()


void setup() {
pinMode(ARDUINOPIN, INPUT_PULLUP); // Configure the pin as an input, and turn on the
pullup resistor.
// See http://arduino.cc/en/Tutorial/DigitalPins
attachPinChangeInterrupt(ARDUINOPIN, interruptFunction, FALLING);
Serial.begin(115200);
Serial.println(“—————————————“);
}

// In the loop, we just check to see where the interrupt count is at. The value gets updated by
the
// interrupt routine.
void loop() {
delay(1000); // Every second,
Serial.print(“Pin was interrupted: “);
Serial.print(interruptCount, DEC); // print the interrupt count.
Serial.println(” times so far.”);
}

Reply

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

admin 15 Oct 2016


Hola Tony,

Segun el manuela en el mega puedes usar los siguientes pine spara enlazar
interrupciones

Mega, Mega2560, MegaADK 2, 3, 18, 19, 20, 21

Por lo que veo tu has definido ARduinopin para la interrupcion , como el pin 33
pero ese pin no reconoce interrupcione spor lo que no va a funcionar. Tienes que
elegir uno de la lista

tonny 15 Oct 2016


Ya, es que los firmware(que se usan para las impresoras 3D con
este kit) usan esos pines en sus códigos, por eso mi duda… no he
encontrado cómo hacen para que el encoder les funcione usando
esos pines.

admin 17 Oct 2016


Hola Tony, poner en marcha una interrupcion es de lo mas sencillo.
SImplemente concta la salida del encoder al pin 2 0 3 de arduino
(Los que aceptan la interrupcion) despues crea una funcion de
servicio que incremente en 1 un contador cada vez que se dispare
la interrupcion y eso es todo

Desde l programa proncipal solo tienes que ver cuantas señales ha


contado el encoder

Emilio Machado 07 Oct 2016


Muchísimas gracias por este tutorial!!!, excelente y bien sincero.
Yo estoy luchando con interrups entre el MPU 6050 y pro mini 3,3. La rutina es sleep -wake-up
Reply con zeromotion interrups.
Todo funciona bien, le di en la tecla con duración y thresfold de forma que cuando hay actividad
del acc esta despierto y cuando no duerme.
El problema que tengo es que cuando reseteo el arduino o lo reescribo el interrups funciona a
revés, o sea que cuando tiene que estar activo descanasa y cuando debe estar descansando
está activo.
Esto pasa erraticamente lo reseteo nuevamente y funciona como debe.

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

La función del interrups es:


void doInt()
{
//———-ESTE FUNCIONA——
motionDetected=!motionDetected;
//—————————–
}
el void loop>
algo antes
Wire.beginTransmission(MPU);
Wire.write(0x43);
Wire.endTransmission(false);
Wire.requestFrom(MPU,4,true); //A diferencia del Acelerometro, solo se piden 4 registros
GyX=Wire.read()<<8|Wire.read();
GyY=Wire.read()< 20){
if (montaa==0){
StartTime=millis();
etc,etc,etc
}
Le saqué la orden de ir a dormir hasta que solucione este problema
desde ya much’isimas gracias nuevamente y 1000 disculpas por la molestia

Alberto 24 Sep 2016


Hola Charly,

Reply Es la primera vez que escribo. Primero mis impresiones y luego quiero comentar algo sobre mis resultados
con las interrupciones y preguntaros si estoy en lo cierto.

Me ha impresionado bastante el enfoque tan didáctico y ameno de este curso. Tengo (tenía) experiencia de
programación y me quedé en Pascal, sin apenas programar en C. Calcula mi edad… He hecho aplicaciones
y utilidades de sistemas para clientes y he programado PICs como hobby en código máquina, así que sé de
sobra lo que es programar. Pero tenía un tema pendiente que era entender el porqué de la famosa
programación orientada a objetos. Con tus breves pero clarificadoras lecciones lo he entendido a la
perfección. !Muchas Gracias!

Estoy siguiendo con todo detalle este curso y quisiera comentar una curiosidad que he observado con el
tema de las interrupciones y los rebotes del pulsador.

He realizado un montaje con vuestro KIT del curso, con 8 LEDs en secuencia de ir y venir, tipo coche
fantástico. Mas un pulsador que cada vez que lo pulsas cambia alternativamente el delay para que el
“movimiento” de luces sea más deprisa o más despacio.

He seguido el código para evitar los rebotes de esta lección, pero tenia curiosidad por saber el número de
rebotes y añadí un contador adicional de rebotes que siempre se incrementa en la rutina de interrupción, sin
pasar por el “if”. Pues bien, cada vez que pulso lo más rápido que puedo el pulsador, el contador bueno se
incrementa 1, como debe ser, pero el otro contador de rebotes, que cuenta las veces que se dispara la
interrupción al pulsar el botón, se incrementa cada vez no unas cuantas veces sino del orden de 5.000 o

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

10.000 veces (cinco mil a diez mil veces). Al tercer o cuarto pulsado del botón, el contador de rebotes
entero ya se ha desbordado y aparece negativo.

No me podía imaginar que la rutina de interrupción entrase tantas miles de veces, con un simple rebote de
pulsador. Lo que imaginé era que como la condición de interrupción programada era “LOW”, la
interrupción se disparaba continuamente mientras el pin estuviese LOW, es decir el botón pulsado. Al
cambiar la condición a “FALLING”, entonces el comportamiento es lo que yo esperaba. El numero de
rebotes es uno o dos, como máximo, o incluso ninguno, pulsando con firmeza y/o delicadeza.

Entonces parece ser que con la condición “LOW”, mientras se mantenga el pin LOW, se dispara
continuamente la interrupción. Habría que programar algún código en la rutina de interrupción para
deshabilitar esta interrupción, mientras se ejecuta la ISR. Y luego al final de la rutina de interrupción
volver a habilitar la interrupción para estar preparado para la siguiente.

Creo recordar que los PICs que programé hace años eso era automático, pero parece que con el PIC de este
arduino no es así y mientras se mantenga la condición LOW, se dispara una y otra vez la interrupción a la
máxima velocidad que permite el chip. ¿Estoy en lo cierto? ¿Podéis comentarlo si sabéis sobre este tema?

En fin, Muchísimas gracias por este curso que me está haciendo disfrutar de nuevo después de tantos
años…

Un Fuerte Abrazo,

Alberto

admin 25 Sep 2016


Hola ALberto, no recuerdo haber hecho la prueba que mencionas con las interrupciones pero por lo que
comentas el LOW dispara la interrupcion de forma continua. Personalmente tengo la costumbre de
Reply usar la condicion de Rising o falling desde hace mucho tiempo para evitar este tipo de problemas. UN
saludo y bienvenido al club

James 24 Dic 2016


Hola Alberto,
Al igual que en los PICs (CCS por ejemplo), Arduino también posee funciones para habilitar y
Reply deshabilitar las interrupciones si así lo necesitamos:
interrupts() y noInterrupts()

Más info: https://www.arduino.cc/en/Reference/NoInterrupts

GREBER ROAMIR 12 Ago 2016


unsigned long start = 0;
const int threshold = 400;
Reply const int analogPin = A0;
int led = 6;

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

void setup() {

start = millis(); // se cargas a la variable start con el valor de millis(), o sea un tiempo t1 en mseg
pinMode (led, OUTPUT);
Serial.begin(9600);

void loop() {
while (millis() – start threshold)
digitalWrite(led, HIGH);
else
digitalWrite(led, LOW);
// print the analog value:
Serial.println(analogValue);

} // fin del while


}

GREBER ROAMIR 12 Ago 2016


HOLA A TODOS ,
Tengo este codigo y quisiera agregarle un boton para que me pueda interrumpir el encendido de
Reply un led antes del tiempo establecido,
la funcion del codigo es que utilizo un potenciometro, la cual me activa un led al llegar a
(threshold = 400) al girar el potenciometro y llega al valor el
led se me enciende , mientras no presione el boton el led debera enceder al llegar al valor ,
ahora si presiono el boton antes del tiempo 15seg el led no se active , importante es que se
debe ejecutar una sola vez mientra el arduino este energizado . si reseteo o des energizo el
arduino se debe ejecutar el codigo.

unsigned long start = 0;


const int threshold = 400;
const int analogPin = A0;
int led = 6;

void setup() {

start = millis(); // se cargas a la variable start con el valor de millis(), o sea un tiempo t1 en mseg
pinMode (led, OUTPUT);
Serial.begin(9600);

void loop() {
while (millis() – start threshold)
digitalWrite(led, HIGH);

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

else
digitalWrite(led, LOW);
// print the analog value:
Serial.println(analogValue);

} // fin del while


}

admin 13 Ago 2016


hola greber,sera mas facil que alguien te ayude si lo posteas en el foro

Reply

Andres 26 Jul 2016


Buen dia
Estoy desarrollando un proyecto de toma de datos por i2c, mi interrupcion es por el pin 3 del
Reply arduino uno, al momento que necesito desactivar la interrupcion para leer los datos deshabilito
la interrupcion. despues de haber hecho la lectura de los datos necesito reiniciar la interrupción,
pero aqui es donde tengo el problema, no me quiere reiniciar la interrupción.
void loop()
If (con==3){
detachInterrupt(digitalPinToInterrupt(interruptPin));
lectura de datos;
interrupts();
}
Muchas gracias por la ayudita.

admin 26 Jul 2016


Andres
Estas usando detach por lo que no vas a poder rehabilitarla sin un usar un nuevo attach
Reply
Creo que lo que intentas hacer es bloquear las interrupcioines sin deshabiltarlas, usa nointerrupts y
entonces podras usar interrupts()

Andres 26 Jul 2016


noInterrupts(),
Interrupts(),
Reply detachInterrupt
Buenas noches
alguien que me expliqué la forma correcta de usar estos tres comandos
muchas gracias

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

Ivan 26 Jul 2016


Con no Interrupts() lo que haces es desactivar todas las interrupciones que estén definidas con un
attachInterrupt(), y para volver a activarlas utilizas la función Interrupts(), sin pasarles ningún
Reply argumento.

Si lo que quieres es anular sólo una interrupción utilizarías la función detachInterrupt( num Interrupt),
pasándole como parámetro el número de la interrupción, no el pin al que está asociada.

admin 26 Jul 2016


Hablo de memoria pero creo que es mas o menos asi:
Nointerrups. –> anula todas las interrupciones
Reply Interrupts –> habilita las interrupciones. Es lo contrario del anterior
Detachinterrupt –> inhabilita solo la interrupcion indicada pero no las demas

Jesus 13 Jul 2016


Hola.

Reply La verdad muchas gracias por tus tutoriales, tu web es un referente cuando buscas empezar con arduino y
también cuando quieres dominarlo, en serio gracias.

Ahora que sé que existen interrupciones te quería hacer una consulta:


si tengo un arduino conectado por comunicación serie a otro dispositivo o a un moden (con un adaptador
de red) y otro dispositivo iniciará una comunicación con el arduino ¿cómo me aseguro que el arduino
recibirá dicha señal? ¿Usando interrupciones (se supone que no porque leer un serial demora mucho
tiempo) o simplemente diseñando señales de comunicación para que ambos dispositivos al comunicarse se
avisen que lo están e intercambiar la información? ¿Tienes algún tutorial en donde hables sobre diseñar un
sistema ordenado de comunicación serial entre arduino y otro dispositivo?

Lo pregunto porque mi idea es que arduino se conecte con otro dispositivo (computadora, raspberry, otro
arduino) y que ambos dispositivos puedan emitir mensajes así como recibirlos de forma ordenada, lo único
que se me ocurre para esto es poner los métodos de leerSerial() y enviarMensaje() seguidos uno del otro
pero ¿qué sucede si caundo envío el primer mensaje para que el otro dispositivo me responda y este
responde arduino está de nuevo en enviarMensaje()? Si arduino solo funcionara como servidor no habría
problemas pero la idea es que también pueda enviar mensajes.

Saludos.

admin 13 Jul 2016


Hola Jesus,
Normalmernte todos los protocolos de comunicacion se basan en interrupciones d emodo que
Reply efectivamente se garantice que no perdemos ningun mensaje y los programas de bajo nivel son los que
gestionan este tipo de problemas. EN el caso de la comunicacion serie que es lenta no deberia ser nada
complicado hacerlo tu, pero siempre es mas comodo tirar de las librerias hechas que ademas se suelen
apoyar (Como en el caso de las Comm de arduino) en interrupciones hardware de bajo nivel

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

Para una comunicacion serie entre tu arduino y porejemplo un PC o Rasberry, usaria directamente la
conexion USB y tendras un monton de capas de drives de bajo nivel asegurandose de que van
recogiendo en un buffer lo que va entrando

Lo unico que tienes que hacer es no demorarte demasiado con delays y demas y realizar el loop con
cierta soltura ¿Valeee?

Tulio 31 May 2016


Buen día!

Reply Tengo un problema con un proyecto que me encuentro desarrollando pero aqui es mi problema:

Una vez que activo mi señal de entrada,por medio de un potenciometro condiciono un tiempo de trabajo
entre 100 ms y 1500 ms. El detalle que necesito que aunque la entrada siga en estado alto siga corriendo el
tiempo de trabajo y al terminar el estado cambie a LOW. :smiley-confuse:

Alguien que pueda aconsejarme que instruccion usar…a continuacion dejo mi codigo donde

SCI es la entrada!
CO es la salida!
offtime es el mapeo de la entrada analógica

[code]

const int pinpot = 0; //A0


const int LCO = 9;
const int SCI = 12;
int SCI = 0;
const int CO = 11;
int timewait = 0;  
int tw = 0;  
int p1;// Aux SCI
int p2; //Aux C0

unsigned long previousMillis = 0;        


long OnTimeMin = 100;          
long OnTime = 0;
long OnTimeMax =1500;
long OffTime = LOW;

void setup() {
 // Incializa el pin del boton como entrada
 pinMode(pinpot, INPUT);  
 pinMode(SCI,INPUT);
 // Incializa el pin del led piloto y  salida
 pinMode(LCO, OUTPUT);

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

 pinMode(CO, OUTPUT);
 // Inicializa la comunicacion serial
 Serial.begin(9600);

void loop(){
 
 //Lee boton
 p1=digitalRead(SCI);
 //  Lee el valor del pot
 tw = analogRead(pinpot);
 //  Transforma  este valor en el valor que usaremos para el led
 //  Para ello usaremos la funcion map()
 OffTime = map(tw, 0, 1023, OnTimeMin, OnTimeMax);
 //  Utilizamos este valor para iluminar el led
 
 
  // check to see if it's time to change the state of the LED
 unsigned long currentMillis = millis();

 if((p1 == HIGH) && (currentMillis - previousMillis >= OnTime))


 {
   (CO , HIGH);  // Turn it off
   previousMillis = currentMillis;  
   digitalWrite(CO, HIGH);
 }
 else if ((p1 == LOW) && (currentMillis - previousMillis >= OffTime))
 {
   
   previousMillis = currentMillis;  
   digitalWrite(CO, LOW);  
 }
}

Ed 31 May 2016
Vale Juanma!, muchas gracias!, ya lo revisaré, la pregunta era básicamente como controlar los
dos bits del rotary(A y B) que te dan los 4 estados posibles con los que se calcula si se
Reply incrementa o se decrementa. Pero al estar esos dos pins asociados a la interrupción y no poder
usarlos como valores ordinarios de entrada, tenía duda de como hacerlo, pero creo que será
como dices tu.

Muchas gracias de nuevo!

Ed 30 May 2016

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

Hola Juanma, muy chulo el post, estoy empezando en arduino y me ha gustado mucho, me has
enganchado para leer el resto de entradas!
Reply Tengo una duda conceptual que querría aclarar, estaba mirando información de las
interrupciones para un rotary encoder. la pregunta es, si pongo interrupciones a los dos pins que
leen el estado A y B, como hago para leer sus valores cuando llamo al callback si los pines stán
asociados a las interrupciones, de forma que no he podido definir variables para recuperarlos?

Muchas gracias, un abrazo!

admin 31 May 2016


Hola Ed no entiendo bien la pregunta, pero veamos. Un rotary encoder te envia manda una señal
cuadrada cada vez que la marca de control pasa por delante de ello. Puedes programar la interrupcion
Reply para que se dispare en el flanco de subida o de bajada, con lo que tendras una señal clara en cada pulso
y eso lo usar para lanzar una funcion que incrementa el contador, eso es todo.
Luego puedes leer el contador desde tu programa tranquilamente

Momelius 13 May 2016


Solo una cosa… estoy aprendiendo la leche.. y por otro lado… que asco me dais la gente como
tú, es decir, gente que puede hacer cosas que yo desearía hacer (pero es en el sentido total y
Reply absolutamente egoísta y de respeto, espero que se entienda)

admin 13 May 2016


Hola Momelius, jajaja tranquilo que nos lo tomamos en el mejor sentido y te agradecemos el cariño
que expresa.
Reply
Me gustaría decirte, para que te animes que no haya qui nada que no puedas aprender tu también y
basta con ganas y algo que se suele olvidar pero que es imprescindible, tiempo y meter horas.

Recuerda que un experto, suele ser alguien que se ha leído el manual antes que tu.

GIVE A REPLY

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

Name (required)
Email (required)
URL

Post comment
WordPress Anti-Spam by WP-SpamShield

CATEGORIAS
DE LOS
PRODUCTOS

Elige una
Elige una categoría
categoría

Copyright Prometec

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]


Arduino y las interrupciones | Tutoriales Arduino

http://www.prometec.net/interrupciones/[03/03/2017 02:45:22 p. m.]

You might also like