
Tienes tu módulo de detección de sonido, presencia… conectado a tu Arduino y quieres activar algún motor o modificar una variable cuando suceda algo (haya ruido, entre alguien…) pero claro ¿Si no sabes cuándo va a suceder ese evento cómo haces el código? ¿Te pasas todo el día monitorizando ese pin? ¿Y si justo sucede cuando la instrucción que se está ejecutando es un delay()? ¿Y si es un sonido impulsivo (como un golpe) y no lo detectas con el código? Todos estos problemas encuentran su solución en el uso de las interrupciones. Las interrupciones en Arduino te permiten detectar eventos de forma asíncrona con independencia de las líneas de código que se estén ejecutando en ese momento en tu microcontrolador.
Haz click para ir a lo que más te interese.
- 1 Tutorial Sobre El Manejo De Interrupciones
- 1.1 ¿Qué Es Una Interrupción?
- 1.2 ¿Para Qué Sirven Las Interrupciones De Arduino?
- 1.3 Ventajas E Inconvenientes De Usar Interrupciones
- 1.4 ¿En Qué Pines De Arduino Se Pueden Usar Las Interrupciones?
- 1.5 Modos De Activar Las Interrupciones
- 1.6 Código Asociado A Las Interrupciones
- 1.7 Ejemplo Del Uso De Interrupciones En Arduino
- 1.8 Eliminando El Efecto Rebote
- 1.9 Información Adicional
Tutorial Sobre El Manejo De Interrupciones
En este tutorial vas a aprender lo que se puede y no se puede hacer con las interrupciones en tu placa Arduino y de qué forma. Aprenderás cómo con unos simples pasos puedes aprovechar una de las herramientas más interesantes de Arduino (así como cualquier otro microcontrolador), con lo que seguro que muchos de tus proyectos mejorarán considerablemente (serán más eficientes y precisos).
Este (al igual que el anterior en el que te hablé de cómo usar la memoria EEPROM de Arduino) es uno de los tipos de post que más me gusta y eso se debe a que no necesitas comprar ningún módulo ni placa, es algo que ya tenías y que no sabías usar, es algo que tenías y, simplemente, estabas desaprovechando, es algo que me recuerda que te diga: ¡Conoce tu Arduino! Vale, tampoco me voy a poner en plan Bruce Lee pero en serio, gastamos mucho dinero para hacer cosas que podríamos hacer con lo que ya tenemos y usar las interrupciones en Arduino es un gran ejemplo de esto.
¿Qué Es Una Interrupción?
Una interrupción consiste básicamente en detectar detectar un evento y realizar algo en consecuencia. Tu Arduino tiene una serie de pines (podrás ver cuáles más adelante) a los que puedes asociar un módulo (un segmento de código) de modo que este se ejecute cuando en ese pin cambie de un estado a otro que tú previamente has establecido.
De hecho, seguramente ya habrás utilizado las interrupciones de Arduino sin saberlo. Cuando utilizas instrucciones del tipo millis() estás utilizando interrupciones. ¿Te suena eso de que la función millis() vuelve a 0 tras 50 días con tu Arduino conectado? ¡Exacto! Eso también se hace con interrupciones (aunque de otro tipo al que vas a ver en este post).
¿Para Qué Sirven Las Interrupciones De Arduino?
Como todos los códigos, sirve para lo que tú lo quieras usar en tu proyecto. No te ha ayudado mucho ¿Verdad? Bueno, para que te hagas un poco a la idea de para qué puedes usar las interrupciones te pongo unos cuantos ejemplos:
- Para detectar cambios como un pulsador que ha sido presionado.
- Para determinar cuando se ha terminado de gestionar la memoria EEPROM o Flash de tu Arduino.
- A modo de despertador del controlador. Esta es una interesantísima funcionalidad de tu placa que te permite mantener el consumo al mínimo dejando tu Arduino en standby hasta que suceda algún evento. Con ello podrás hacer que tus baterías duren mucho más. Como esta parte es especialmente interesante, escribiré un artículo al respecto. Entre tanto, te recomiendo que le eches un vistazo a este post si quieres aprender a optimizar las baterías de tu placa.
- Como un Watchdog. La idea es similar a la del punto anterior y espero también hacer un post sobre esto.
- Como el complemento ideal a los módulos digitales de sonido, temperatura… que disponen de un potenciómetro que regula cuándo se activa la salida digital. Así puedes, por ejemplo, realizar un montaje simple en el que ocurra alguna acción cuando se supere un cierto umbral de sonido o una cierta distancia.
Ventajas E Inconvenientes De Usar Interrupciones
Soy de los que repiten una y otra vez los conceptos importantes así que aquí va: una interrupción es un evento asíncrono que se detecta con independencia del código que esté ejecutando en ese momento tu Arduino.
Ésto está muy bien si estás construyendo un coche que evita obstáculos ya que, si optas por el método tradicional, o vas parando cada poco tiempo los motores para medir la distancia, o es posible que, si todavía quedan muchas instrucciones por ejecutarse en tu código, cuando quieras comprobar la distancia para cambiar de rumbo, ya sea demasiado tarde (¡CRASH!). Sin embargo, utilizando las interrupciones de Arduino puedes tener tu código ejecutando las instrucciones que sean y, sólo cuando esa interrupción se active, tu programa se va al código que has asociado a esa interrupción, lo ejecuta y luego vuelve a donde estaba (a la parte del código que estaba ejecutando cuando se activó la interrupción).
Lo que te acabo de contar como una ventaja es al mismo tiempo un inconveniente. Si tu Arduino responde a la interrupción con independencia del código que se esté ejecutando ¿Qué pasa si se estaba ejecutando un delay() o una instrucción tipo millis()? Pues que tu Arduino atiende a la interrupción y vuelve por donde iba, esto es, ahora el tiempo real y el tiempo que ha pasado para tu Arduino no son lo mismo porque la interrupción se empezó a ejecutar cuando el tiempo que había transcurrido desde que conectaste tu Arduino (instrucción millis() ) eran 200ms se activó tu interrupción y ha durado 20ms pero para tu microcontrolador ese tiempo no ha existido, es decir, el valor de la función millis() no se ha incrementado y ahora no puedes fiarte del tiempo transcurrido y lo peor es que es posible que tú ni siquiera seas consciente de que la interrupción ha sucedido. ¿Y si el motor de ese coche tenía que estar encendido 200ms y nada más que 200ms?
Como te puedes imaginar, todo esto que te acabo de contar es un poco más complejo. Sin embargo, espero que haya sido suficiente para que te hagas una idea de lo que puedes esperar cuando utilices interrupciones.
¿En Qué Pines De Arduino Se Pueden Usar Las Interrupciones?
Sólo hay unos pocos pines en los que se pueden realizar interrupciones y dependen del modelo de tu placa. Aquí te dejo una lista con los pines y los nombres de las interrupciones (al existir la posibilidad de tener varias interrupciones en la misma placa, tienes que asociarles un nombre):
Modos De Activar Las Interrupciones
Ahora que sabes a qué pines se pueden asociar las interrupciones en Arduino, te falta conocer cómo activarlas, es decir, qué tiene que suceder en ese pin para que la interrupción se ejecute. Estos modos de activación los determinas tú cuando programas la interrupción y las posibilidades son las siguientes:
- LOW: La interrupción se activa cuando el valor de voltaje del pin elegido es bajo, esto es, 0V.
- CHANGE: La interrupción se activa cuando el pin cambia de valor, es decir, cuando pasa de LOW a HIGH o de HIGH a LOW.
- RISING: Se activa únicamente cuando el valor del pin pasa de LOW a HIGH.
- FALLING: Es el caso opuesto al modo RISING. Se activa la interrupción cuando el valor pasa de HIGH a LOW.
- HIGH: Este modo solo está disponible en la placa DUE y funciona de manera opuesta al modo LOW, es decir, se activa cuando el valor de voltaje del pin es alto.
Código Asociado A Las Interrupciones
Como te he comentado antes, la gracia de las interrupciones reside en que se ejecuten una serie de líneas de código cada vez que se activa la interrupción. Para conseguir esto deberás implementar un módulo asociado a dicha interrupción.
Seguramente ya conozcas el concepto de módulo pero por si tienes alguna duda de a lo que me estoy refiriendo te diré que, básicamente, se trata de un segmento de código que se ejecuta cuando es invocado. El void setup(){} y el void loop(){} a los que seguro que estás acostumbrado son un tipo particular de módulo. Puesto que no es el objetivo de este post, no voy a explicarte en profundidad las características de los módulos pero puedes dejar tu comentario si tienes alguna duda.
Para que puedas asociar un módulo a una interrupción correctamente, éste debe cumplir unas características concretas:
- No puede tener parámetros de entrada, es decir, no puede ser una función del tipo void f_interrupt (int entrada).
- No puede devolver ningún valor, por tanto debe ser un módulo de tipo void.
- Para que este segmento de código pueda interactuar con el resto de tu programa puedes crear una variable de tipo volátil (por ejemplo volatile int variable), lo que te permitirá leer el valor de dicha variable fuera del módulo asociado a la interrupción y actuar en consecuencia. Algunas de las prácticas más habituales consisten en crear una variable que cambia de estado (entre LOW y HIGH) cada vez que se activa la interrupción o un acumulador, una variable que incrementa su valor con cada interrupción y que puede ser consultada en cualquier momento por el resto de módulos.
Ejemplo Del Uso De Interrupciones En Arduino
Ya conoces todas las características que debes tener en cuenta a la hora de implementar una interrupción. Estoy seguro de que podrías hacerlo sin problemas. Aun así, aquí tienes un ejemplo de cómo se crea una interrupción en Arduino.
Supón que quieres encender un LED o cualquier otro dispositivo mediante el uso de interrupciones (recuerda que en el caso del LED debes añadirle una resistencia, puedes leer más sobre la configuración de LEDs en este post), de tal manera que cada vez que se presione un pulsador, éste se encienda.
Una vez configurado un circuito para tu pulsador como el que puedes ver, conectado al pin correspondiente de interrupción que prefieras (en este caso el pin 2, es decir, la interrupción 0), debes elegir el modo en el que se activará dicha interrupción. Aunque quizás a primera vista pienses que el modo que debes elegir es LOW, recuerda que en ese estado la función se estaría ejecutando mientras tuvieses presionado el pulsador. Para evitar esto, debes seleccionar el modo RISING o el FALLING según prefieras que tu LED se encienda al presionar o levantar el pulsador.
Aquí te dejo el código para que veas cómo se haría.
/* EducaChip – Cómo Usar Las Interrupciones En Arduino*/ // www.educachip.com //Se declara una variable asociada al pin en el que se va a conectar //el LED. Se puede utilizar el valor 13 para observar el efecto de //este código a través del LED de la placa de Arduino. int LED = 8; //Se declara una variable volátil que cambiará de estado en el //módulo de la interrupción y se utilizará fuera. //Si la variable no se utilizase fuera del módulo de la interrupción //no sería necesario crearla de tipo volátil. volatile int estado_actual = LOW; //Se crea la función que se ejecutará cada vez que se active la //interrupción. Esta función es de tipo void (por lo que no devuelve //ningún valor) y no tiene parámetros de entrada. void fun_cambio_estado() { //Se cambia al estado contrario al actual, es decir, de LOW se pasa //a HIGH y de HIGH a LOW. estado_actual = !estado_actual; } void setup() { //Se declara el pin digital correspondiente al LED como salida. pinMode(LED, OUTPUT); //Se determina la interrupción 0 (por lo que el pin asociado al pulsador //será el 2 en caso de tratarse de un Arduino UNO o similar) a la que se //le asocia la función fun_cambio_estado que se activará al presionar el //pulsador (por tratarse del modo FALLING). attachInterrupt(0, fun_cambio_estado, FALLING); } void loop() { //Se escribe el valor actual del LED. digitalWrite(LED, estado_actual); }
Eliminando El Efecto Rebote
Cuando presionas un pulsador el contacto producido entre el botón y la base no siempre es fijo. Normalmente se producen una serie de rebotes al cambiar de estado el pulsador que tu Arduino percibe como si hubieses presionado varias veces. Esto es un verdadero problema si estás utilizando las interrupciones de tu placa para incrementar el valor de una variable o si, como en el caso del LED, este problema provoca que, como no sabes cúantos rebotes va a haber, el estado final de tu variable estado_actual sea desconocido.
Para evitar este problema te voy a enseñar dos posibles soluciones:
Solución Vía Hardware
Esta solución es ideal si tu sistema necesita unos tiempos de reacción cortos o no quieres cargar tu microcontrolador con más código. La idea es sustituir el circuito del interruptor por el que puedes ver en la figura.
Solución Vía Software
Si no quieres gastar dinero en más componentes o el espacio es un factor crítico en tu proyecto, puedes modificar el código anterior añadiendo una variable de tiempo, de tal forma que justo después de que tu Arduino perciba un cambio de estado, tengan que pasar unos pocos milisegundos (deberás adaptarlo en función de tu pulsador pero un valor entorno a los 200ms debería funcionar en la mayoría de los casos) antes de que se le haga caso a cualquier otra pulsación.
Si tienes algún problema realizando cualquiera de los dos procedimientos recuerda dejar un comentario.
Información Adicional
Ahora que ya sabes cómo usar las interrupciones en Arduino, aquí tienes una serie de conceptos y tips que considero importantes:
- Debes implementar los módulos de tus interrupciones lo más cortos y eficientes que te sea posible.
- Sólo se puede ejecutar una instrucción de cada vez, esto es, si se está ejecutando una interrupción y se activa una segunda, no tendrá efecto hasta que la primera termine.
- No es posible utilizar la función delay() conjuntamente con las interrupciones.
- La función millis() no incrementa su valor durante el transcurso de una interrupción.
- A pesar de que las funciones delay() y millis() no funcionan correctamente cuando hay activadas interrupciones, sí que puedes utilizar la función delayMicroseconds().
- Si estás transmitiendo o recibiendo datos (Serial.begin() ) cuando se activa una interrupción, es posible que los pierdas.
- Si quieres utilizar la variable que es modificada por tu interrupción (estado_actual) fuera de ese módulo, debes crearla de tipo volatile.
- Puedes deshabilitar las interrupciones en cualquier momento utilizando la instrucción detachInterrupt().
Esto ha sido todo. Espero que te haya gustado el post y que hayas aprendido a usar las interrupciones de Arduino. Si tienes cualquier duda, quieres contarnos tu experiencia con las interrupciones, etc. deja tu comentario.
Por último, te recuerdo que (si te ha gustado) compartas este artículo en tus redes sociales favoritas y te suscribas al blog.
Un saludo y hasta el próximo post :)
Sebastian dice
Hola!, me ha gusta mucho tu explicación y los ejemplos que pones bien explicados. Tengo una pregunta, se pueden realizar interrupciones analógicas? Lo que sucede es que tengo un LDR y como sabes me manda solo datos analógicos, lo que quisiera es asociar eso e implementar en una interrupción para que si, un objeto corta un has de luz entre el láser y el LDR, entonces no importa lo que este ejecutando y ahí haga la interrupción.
Enrique dice
Buenas Sebastian,
Lo que necesitas se llama detector de ventana y se hace con un amplificador operacional. También puedes simular un comportamiento parecido con un buffer.
Un saludo, Enrique.
Valentin dice
Hola Enrique, estoy haciendo un scketch bastante extenso para medir energía trifásica. El tema que quiero saber si puedo usar interrupciones pero fuera del “setup”, o sea, dentro de un void por ejemplo predefinido por mi, dado que quiero que esa interrupción actúe solamente en cierto momento de la ejecución… es posible? Muchas Gracias
Enrique dice
Buenas Valentín,
Eso es lo normal, que asocies un conjunto de código a un cambio en el valor de un registro del microcontrolador.
Un saludo, Enrique.
David Ramos dice
Hola Enrique:
Me ha sido de gran ayuda tu Post y el resto de la web me esta pareciendo igualmente útil.
Te comento una duda a ver si puedes ayudarme aun mas de lo que lo has hecho.
Estoy utilizando un modulo de Sensor de Sonido con mi Arduino. Mi intención es detectar si se esta produciendo un ruido y cambiar una variable Bool. Al ver tu articulo pensé que lo mejor era conectar la salida digital del sensor al pin 2 o 3 y gestionar esto con una interrupción.
Todo parece funcionar bien con ruidos cortos como palmadas. Pero con ruidos largos como silbidos y soplidos, la señal se activa y desactiva varias veces durante el silbido. Supongo que es por la frecuencia del sonido en si, aparte de un molesto efecto rebote.
¿Crees que esto se podría solucionar añadiendo un condensador como mencionas? Me parece que una solución por hardware es la mas conveniente.
¿Si es así, me podrías indicar que tipo y valor de condensador utilizar? Así como la forma correcta de conectarlo.
Te dejo aqui el código que estoy usando:
#define PinDigSensor 3
volatile bool Soplando=false;
void setup()
{
Serial.begin(9600);
attachInterrupt(1, DetectaRuido, RISING);
}
void loop()
{
}
void DetectaRuido()
{
Serial.print(“—-INICIO DEL RUIDO—-\n”);
Soplando=true;
attachInterrupt(1, NO_DetectaRuido, FALLING);
}
void NO_DetectaRuido()
{
Serial.print(“———–FIN———-\n”);
Soplando=false;
attachInterrupt(1, DetectaRuido, RISING);
}
GRACIAS UNA VEZ MAS.
Enrique dice
Buenas David,
No creo que necesites hacer gran cosa. Seguramente lo puedas solucionar directamente aumentando el nivel de potencia del sonido (o reduciendo la sensibilidad del micrófono).
Un saludo, Enrique.
David Ramos dice
La verdad es que he intentado ajustar el sensor de todas las formas y sigo sin solucionar el problema de que emita varias señales. Crees que se podria solucionar por hardware con condensadores?
Gracias.
Enrique dice
Buenas,
La idea de los condensadores es la de evitar un mal contacto entre las partes metálicas de un interruptor o pulsador. Puede que te llegue a funcionar si lo pones entre la salida del micrófono y la entrada de la placa (justo ese problema no lo he sufrido nunca).
También puedes jugar deshabilitando las interrupciones, midiendo tiempos con la función millis() para evitar que cambios en cortos periodos de tiempo realicen una acción o incluso con el modo en el que se activan las interrupciones.
Te daría una solución concreta, pero me temo que vas a tener que ir probando.
Un saludo, Enrique.
shecko dice
Hola Enrique muy buenos dias excelete aporte este que haces muchas felicidades,te escribo por que tengo dos dudas:
La primera es con respecto a como eliminar el efecto rebote de un push button por medio de software? con ese push estoy disparando una interrupcion pero al verificar en el monitor serial del ide de arduino noto comportamientos inestables que atribuyo al efecto rebote.
La segunda estoy intentando hacer que cuando la interrupcion ocurra se mande una peticion a un servidor web (tengo un modulo nodeMCU) para saber que el boton ha sido presionado desde una pagina que yo monitoreo.Sin embargo aunque me consta que la interrupcion si es reconocida (checo una varible volatil en el monitor serie)la peticion no se hace. cabe mencionar que el codigo de mi peticion lo he probado poniendolo en el modulo loop y lo realiza sin problema, Gracias de antemano y qu tengas buen dia
Enrique dice
Buenas Shecko,
Hay muchas formas de hacerlo. Puedes meter un pequeño delay después del primer cambio en el pin de la interrupción de modo que no te capte los demás.
Respecto a la segunda duda no sé qué decirte. Si sabes que la interrupción se está llevando a cabo, prueba a hacer la petición sin utilizar interrupciones, así puedes asegurarte de que el problema esté en el resto del código.
Un saludo, Enrique.
Luis Arcila dice
Amigo se me ocurre una manera de resolver esto por hardware retroalimentado por software: es adicionando una compuerta AND, una de las entradas es tu sensor y la otra un pulso que controle la longitud del silvido, ahora la entrada de la AND de control “Control1” la puedes realimentar con una de las salidas del arduino “Retro1” de la siguiente manera: Salida de realimentacion Retro1 del arduino siempre High conectada a Control1, Entrada Sonido ON > AND pasa a alto > Activa Int > Retro1=0 > Entrada de control pasa a 0 > la compuerta and se cierra 0 > tu codigo sigue en ejecucion y al final de la interrupcion vuelves a poner Retro1=1 para que detecte nuevos silvidos… bye espero ayude
Andres Bonilla dice
Cordial Saludo: Es muy interesante tu articulo pero tengo una duda y quisiera saber si me la puedes solucionar. estoy controlando un conjunto cintas led RGB a traves de un control remoto de TV, el problema que tengo es que por ejemplo le doy la tecla numero 1 e ingresa al case correspondiente el cual enciende la cinta led con una combinacion de luces a traves de fading mediante bucles for, quisiera por ejemplo oprimir la tecla 2 y que termine donde vaya es decir sin terminar el bucle apague la cinta y que por ejemplo lleve a cabo otra instruccion.
Enrique dice
Buenas Andrés,
Se me ocurre que puedes meter un if() dentro del bucle y hacer que, si la tecla se pulsa, el índice del for() se ponga en el último valor. Así paras el bucle.
Un saludo, Enrique.
Francisco Ayala dice
Hola buenas tardes, tengo un detalle con mi proyecto estoy tratando de enviar los contadores de una maquina de engomado de cajas de carton, lo que busco es enviar el dato de la Orden de Trabajo, Numero de Nomina del operador y el total de cajas que ha contabilizado mi arduino, solo que no se si deba usar interrupciones para que pregunte al operador los primeros 2 datos (partida y numero de nomina), posterior a esto empiece el sensor del arduino a contabilizar las piezas y con un boton (push boton) confirmar el termino de la partida y se envie el dato a un MYSQL, me falta experiencia en la programacion ya que me estoy adentrando en este mundo del arduino, al momento tengo el clasico ejemplo del registrador de temperatura con el LM35 enviando los registros a una tabla en MYSQL, la duda es saber si con interrupciones puedo lograr l oque busco. Gracias de antemano y muy buen aporte con tu blog.
Enrique dice
Buenas Francisco,
No creo que sea necesario. Puedes hacer que Arduino pregunte esos datos, el trabajador los introduzca y luego ya se ejecute el programa. Es decir, leer una variable de entrada y no actuar hasta que se inserte (tienes ejemplos dentro de la propia IDE).
Un saludo, Enrique.
Marcelo dice
Como estas Enrique te consulto sobre las interrupciones actualmente estoy trabajando con un caudalimetro de 2″ con arduino UNO y necesito que en cierto valor de caudal o Hz me realice una interrupción y se quede en cero por ejemplo un valor que va de 0 a 80 l/m o lo que corresponda a Hz si supera el valor en este caso de 80 l/m se debe ir a cero el medidor, se podrá realizar con la interrupción, espero tu respuesta, el post es muy bueno, saludos.
Enrique dice
Buenas Marcelo,
Puedes sacar la señal con la frecuencia que necesitas, filtrarla y, si es la correcta hacer que la señal la lea la tu Arduino. Te dejo un post sobre filtros pasa banda, creo que te va a ayudar.
Un saludo, Enrique.
David dice
Hola, muy bueno tu blog, super claro tu post.
Queria consultarle lo siguiente, en mi proyecto estoy haciendo funcionar un motor a pasos, el cual abre y cierra una puerta a traves de dos pulsadores (uno abre y otro cierra). Y un tercer pulsador debe detener la apertura o el cierre de la puerta, en caso de X situacion. La parte de las interrupciones las entendí perfectamente, pero como puedo hacer para que el tercer pulsador detenga el movimiento del motor, y luego, el motor retroceda tantos pasos como los que se hayan ejecutado al momento de pulsar la interrupcion??
Gracias
Enrique dice
Buenas David,
Puedes usar una tercera interrupción. Si tus interrupciones cambian el valor de una variable “estado”, puedes hacer que esta tenga tres valores posibles (0, 1 y 2 por ejemplo). Si el valor es dos (detener apertura o cierre) se comprueba el valor previo que tenía la variable (que puedes almacenar en una variable auxiliar como “estado_previo”) con sentencias if(). Si estado vale 2 y estado_previo vale 0 la puerta se estaba abriendo, entonces ejecutas la orden de cerrar y le dices a tu motor que vaya a la posición 0. Si estado vale 2 y estado_previo vale 1, entonces la puerta se estaba cerrando y puedes decirle a tu motor que vaya a la posición de apertura.
Espero que te haya quedado más o menos claro. :)
Un saludo, Enrique.
David dice
Buenas Enrique,
Eres un genio! Muchas gracias, me ha quedado claro, ahora lo escribiré en código, pero se aprecia muy buena la idea.
Muchas gracias
Enrique dice
Wow! Me alegro de que te haya gustado, David. :)
Ánimo con tu proyecto. Un abrazo.
Sergio dice
Me encanta el blog!
Tengo unas dudas con la funcion millis.
He leido que dices que los millis se resetean en el dia 55. Yo tengo que hacer un proyecto en el cual el arduino tiene que estar siempre encendido y para hacer delays lo hago evitando la funcion delay y uso los previusmillis y tal, no se si me explico. La pregunta es… Si se resetean como puedo validar mi codigo para que no me diera error al hacer el delay?
Saludos!
Enrique dice
Buenas Sergio,
Al final, lo que haces cuando trabajas con millis() es utilizar diferencias de tiempo. Puedes utilizar, por ejemplo, un if() que considere si se ha reseteado el contador y, en tal caso, volver a coger la referencia.
Un saludo, Enrique.
M.Dominguez dice
Felicidades por tu blog.
Un trabajo fantástico.
Enrique dice
Muchas Gracias. Me alegro de que te guste :)
Marcial dice
Hola, muy bueno el post, te felicito.
Llegue a el porque quiero leer el paso de una tecla de una vieja maquina de escribir con un sensor optico y con ello accionar un relay. El problema que tengo es que, cuando la interrupcion en el sensor optico es muy rapida no funciona, si cuando la interrupcion es por mas tiempo. Como puedo acelerar esa lectura?
Desde ya mil gracias
Enrique dice
Buenas Marcial,
Me parece muy raro lo que comentas. ¿Qué tipo de interrupción estás usando? Parece que sea cosa de un rebote o algo similar.
Un saludo, Enrique.
GItmel dice
Hola Enrique, muchas gracias por la información tan útil !
Muy bien explicado todo
Vicente dice
Un saludo de otro Graduado en Ingeniería de tecnologías de telecomunicación XD.
Gracias por el aporte, me sirvió para capturar las interrupciones hardware para contar las vueltas que da un anemómetro y las cucharadas de un pluviómetro para mi TFG.
Saludos.
Carlos dice
Hola, buen trabajo el que haces, Enrique.
Un pregunta, quizá un poco absurda.
El modo de activación de interrupción LOW, cuando el pin siempre es low, ¿qué hace? ¿llama constantemente a la función de interrupción?
¿cuál es la diferencia entre LOW y FALLING?
Gracias.
.
Enrique dice
Buenas Carlos,
LOW activaría la interrupción siempre que el valor fuera bajo y FALLING activaría la interrupción únicamente en el momento justo en el que se pase de un valor alto a uno bajo.
Un saludo, Enrique.
Nelson Dario Florez Muñoz dice
He revisado para arduino si existe una opción que me permita incrementar el valor de una variable en “1”, la cual esta asociada a un pin de entrada y que solo se incremente durante un flaco (subida o bajada) sin ninguna relación con interrupciones. Es la mejor forma de contar la ejecución de un suceso.
Agradezco una respuesta a quien la tenga.
Hector Villanueva dice
Buen día, felicidades y muchas gracias por la claridad de tu explicación, ha sido la mejor en lo que llevo buscando información respecto a los rebotes manejados mediante interrupciones, pero ¿que crees? en no me aparece el código ejemplo precisamente de los rebotes solo aparece una linea horizontal y nada mas donde debería ir el código vía software. Ojala se pueda.
Enrique dice
Buenas Héctor,
Creo recordar que dejé el código en uno de los comentarios previos.
Un saludo, Enrique.
Juan David dice
Hola Enrique, he estado al tanto de tu página y he encontrado cosas muy buenas. Tengo una pregunta acerca de un proyecto que estoy realizando. Necesito sensar una variable por un tiempo y si en ese tiempo se cumple la condición que haga algo, es bastante sencillo. Por ejemplo con una fotorresistencia, necesito que el arduino se cerciore de que haya x cantidad de luz durante 1 minuto, si es así pongo en 1 algún pin. Espero me puedas ayudar con este asunto. Saludos
Enrique dice
Buenas Juan David,
Puedes hacer, por ejemplo, que la cantidad de luz active dos interrupciones (una cuando el voltaje supera un valor y otra cuando pasa a estar por debajo de dicho valor) y que éstas guarden los momentos en los que se hizo.
Un saludo, Enrique.
roberto dice
hola excelente post te felicito tengo una consulta y creo que me puedes ayudar deseo realizar un horometro electrónico pero este horometro revisara varios estados a la vez de diferentes funciones por lo cual existirá en algún momento 5 o 6 señales activas juntas a la vez y necesito estar contando el tiempo de activación de estos estados sin perder el tiempo ni de uno ni de otro necesito estar monitoreando todos a la vez la consulta es se puede realizar a travez de las interrupciones??.
Enrique dice
Buenas Roberto,
Si te fijas en el código del funcionamiento de la instrucción millis(), verás que se utilizan variables para ir gestionando los tiempos. Puedes usar esta idea para tener tu contador de tiempo corriendo y almacenar en variables los momentos en los que tus motores cambiaron de estado.
Un saludo, Enrique.
Lautaro dice
Hola, te envió saludos y agradecimientos por tu conocimiento y tiempo brindados.
Me fue de mucha ayuda.
Enrique dice
Buenas Lautaro,
Me alegro de que te haya sido de utilidad el blog. :)
Un abrazo, Enrique.
Walter dice
Hola Enrique, te felicito por tus excelentes blogs.
Quisiera saber si se podría utilizar una interrupción relacionada al tiempo, me explico.
Tengo una Yun y con una rutina obtengo la datetime en string desde Linino cada segundo. Convierto la string en int para la hora y los minutos y los comparo con una hora fija (8:00AM). Cuando son las 8 de la mañana, se genera un pulso de 900 ms y se activa un relay el cual abre una puerta. El problema está en que el relay empieza a pulsar durante un minuto por lo tanto me veo obligado a parar la rutina con un delay de 61 segundos (hasta que la hora cambia a 8:01). No comparo los segundos porque podría pasar este instante y la puerta no se abriría.
Siendo una Yun, no quiero utilizar las librerías time y timesAlarms.
Dicho eso y volviendo a mi pregunta inicial, se podría usar una interrupción en este caso y, de ser así, cómo?
Gracias y un saludo.
Enrique dice
Buenas Walter,
Disculpa la tardanza en contestar.
Puedes intentar solucionarlo con la función millis(), utilizando la idea de ir restando tiempos que tienes en el código del post.
Un saludo y ánimo con el proyecto, Enrique.
Rafael Osorio dice
Pues es un excelente post, bien explicado, en palabras faciles de entender para los que comenzamos en el tema de la programacion, y revisando los comentarios siempre estas en contacto con los que comentan.
Enrique dice
Buenas Rafael,
… Y justo te ha tocado a ti que haya tardado en contestar, ya lo siento. He estado un poco ocupado :P.
Me alegro de que te esté gustando el blog.
Un abrazo, Enrique.
Edurne dice
Buenas Enrique,
Me he metido en el mundo del arduino para hacer un regalo y ando algo perdida. Podrías facilitarme un e-mail para poder comentarte y enviarte lo que quiero hacer? la verdad que no sé por donde empezar.
Gracias!
Enrique dice
Buenas Edurne,
Puedes escribirme desde la sección de contactos del blog (así evitamos que queden los emails publicados).
Un saludo, Enrique.
Miguel Angel Bravo Cabrera dice
Hola!
Primero gracias por tu tiempo y enhorabuena por tu web :)
Si quisieras meter un retardo dentro de la interrupción, ¿como podrías hacerlo?
Pongamos el caso de que está detectando si una puerta se abre, y si lo hace cuenta si se queda abierta mas de X segundos para avisarte de alguna forma. Como se implementara ese “comprueba si esta interrupción lleva X segundos” ?
Muchas gracias!
Enrique dice
Buenas Miguel,
Desde dentro de la interrupción puedes cambiar el valor de una variable que leas fuera para controlar ese tiempo.
Un saludo, Enrique.
Jerónimo dice
Hola, Enrique.
Excelente explicación. Muy clara y didáctica, sobre todo para quienes no somos del mundo de la electrónica.
Te molesto con una consulta.
Estoy utilizando un Arduino Mega 2560 con un módulo de RFID (pn532) y una shield ethernet. Lo que necesito hacer es que cuando alguien apoye una tarjeta en el lector RFID se envíe el tag, a través de la shield ethernet, a una aplicación en una pc para que valide el tag y devuelva a la shield el resultado (habilitar/no habilitar).
Había pensado en estar monitoreando constantemente el lector para que, una vez detectada una tarjeta, se desencadene toda la secuencia de transferencia y recepción hacia y desde la pc, para luego, llegado el caso, abrir el molinete (a través de un relay con un solenoide y finalmente retomar el monitoreo del lector RFID.
Esto, claro, hasta que leí tu post sobre interrupciones. ¿Será mejor hacerlo con interrupciones?
Muchas gracias por tu post y por leer mi comentario/consulta.
Jerónimo
Enrique dice
Buenas Jerónimo,
Si puedes sí. La verdad es que ahora que lo dices nunca me he puesto a ver la compatibilidad de las interrupciones con ese shield. Si te decides a probarlo, haz el favor de comentármelo. :)
Muchas gracias, Enrique.
Jerónimo dice
Hola, Enrique.
Haré algunas pruebas y luego volveré aquí para compartir los resultados obtenidos.
Muchas gracias.
Jerónimo
Jonatan dice
Buenos días Enrique, tengo un Arduino Duemilanove, y quiero medir el tiempo entre dos pulsaciones de la misma señal, para calcular el tiempo de paso de un motor paso a paso. Necesito duplicar la velocidad de giro de un eje respecto de otro. Que funcion utilizarías? soy totalmente nuevo en esto.
Enrique dice
Buenas Jonatan,
Para calcular el tiempo que ha transcurrido entre dos acciones puedes utilizar la función millis().
Un saludo, Enrique.
Samuel dice
Hola Enrique, lo primero gracias por estas explicaciones. Una duda que tengo con el puerto Serie. Si yo quiero que el arduino ejecute una interrupción cuando le llega algo por el RX y el resto del tiempo esté descansando, ¿cómo podría hacerlo? ¿Se podría hacer algo similar para cuando quiero transmitir algo por el TX del puerto Serie?
Un saludo, gracias
Enrique dice
Buenas Samuel,
Échale un ojo a la librería de comunicación serial, seguramente verás instrucciones y módulos que te sirvan.
Un saludo, Enrique.
Pablo dice
Hola Enrique, consulta ¿Para eliminar el efecto rebote vía software, poner un delay (o millis( )) de 40 milisegundos entra en conflicto? Solo para llamar a la función que me cambia el estado (attachInterrupt(0, fun_cambio_estado, FALLING);). Muchas gracias
Enrique dice
Buenas Pablo,
Para evitar conflictos puedes utilizar la función delayMicroseconds().
Un saludo, Enrique.
Ricardo dice
Hola Enrique, muy bueno tu post. ¡Habrá mucha gente agradecida, seguro!
Tengo un problema que creo que puedo solventar con interrupciones pero no sabría cómo hacer ya que estoy usando un módulo GSM que ocupa los pines de interrupción y no podría utilizarlos.
Cuento mi problema: tengo implementado un sketch que, en algún momento de éste, se para y espera a leer un localizador con un lector de código de barras a través de un usb. Se queda para aquí: “usb.Task()”. Y hasta que no lee el localizador, no sigue corriendo el sketch. Pero me gustaría que si se tirara mucho tiempo esperando el localizador hiciera otras cosas.
¿Tendrías una idea?
Muchísimas gracias.
Mando el ejemplo del sketch de la librería USB-Host.
“”””””””””
/*
Keyboard Controller Example
Shows the output of a USB Keyboard connected to
the Native USB port on an Arduino Due Board.
created 8 Oct 2012
by Cristian Maglie
http://arduino.cc/en/Tutorial/KeyboardController
This sample code is part of the public domain.
*/
// Require keyboard control library
#include
// Initialize USB Controller
USBHost usb;
// Attach keyboard controller to USB
KeyboardController keyboard(usb);
// This function intercepts key press
void keyPressed() {
Serial.print(“Pressed: “);
printKey();
}
// This function intercepts key release
void keyReleased() {
Serial.print(“Released: “);
printKey();
}
void printKey() {
// getOemKey() returns the OEM-code associated with the key
Serial.print(” key:”);
Serial.print(keyboard.getOemKey());
// getModifiers() returns a bits field with the modifiers-keys
int mod = keyboard.getModifiers();
Serial.print(” mod:”);
Serial.print(mod);
Serial.print(” => “);
if (mod & LeftCtrl)
Serial.print(“L-Ctrl “);
if (mod & LeftShift)
Serial.print(“L-Shift “);
if (mod & Alt)
Serial.print(“Alt “);
if (mod & LeftCmd)
Serial.print(“L-Cmd “);
if (mod & RightCtrl)
Serial.print(“R-Ctrl “);
if (mod & RightShift)
Serial.print(“R-Shift “);
if (mod & AltGr)
Serial.print(“AltGr “);
if (mod & RightCmd)
Serial.print(“R-Cmd “);
// getKey() returns the ASCII translation of OEM key
// combined with modifiers.
Serial.write(keyboard.getKey());
Serial.println();
}
void setup()
{
Serial.begin(9600);
Serial.println(“Program started”);
delay(200);
}
void loop()
{
// Process USB tasks
usb.Task();
}
“”””””””””
Enrique dice
Buenas Ricardo,
¿Has pensado en utilizar la placa Leonardo o la DUE que tienen más pines de interrupción?
Un saludo, Enrique.
Ricardo dice
Hola Enrique, muchas gracias por contestar.
Tengo que utilizar esta placa, sí o sí.
Estoy trabajando en una empresa y ya están todas compradas.
Yo soy el desarrollador del proyecto.
Enrique dice
Buenas de nuevo,
Podrías intentar tirar por programar vía AVR pero va a ser mucho trabajo, eso sí.
Un saludo, Enrique.
H.Navarrete dice
En caso de utilizar una entrada análoga. Por ejemplo al utilizar una LDR o un LM35 ¿Como seria el uso de interrupciones en ese caso?
Enrique dice
Buenas,
Las interrupciones están asociadas a pines concretos. No puedes (en principio) utilizar interrupciones de ese tipo.
Si tienes idea de utilizar muchas interrupciones te recomiendo que le eches un ojo a la placa DUE.
Un saludo, Enrique.
Nuño Valencia dice
Buen aporte, las interrupciones son importantes en procesos críticos aún no se hacen demasiadas aplicaciones industriales con Arduino pero es lo mismo que un aútomata y cualquiera debe conocer esto si desea ser un buen programador.
Enrique dice
Muy buen dato Nuño :)
jorge gomez dice
gracias por las instrucciones
por favor estoy utilizando una pantalla 4 d systems controlo cuatro resistencias y un reloj y se detiene la pantalla despume de 20 minutos que puedo hacer
Enrique dice
Buenas Jorge,
Es difícil de saber lo que está ocurriendo con esos datos, pero me parece un problema de alimentación.
Un saludo, Enrique.
pedro dice
Hola Enrique.
A estas alturas ya no me es útil esta información, yo ya llegué a estas conclusiones a la fuerza y haciendo muchas pruebas y con muchos fracasos, el antirebote del teclado lo hice con 250ms, no sabía que se podía hacer con hardware, pero también me supone problema de espacio (como bien decías podía suceder)
No obstante me encanta como has tratado este tema, y como lo has redactado.
Te he castigado con un share de Facebook y un +1 de google. :-p
Felicidades!
Enrique dice
Muchísimas gracias Pedro. La verdad es que esas cosas son imprescindibles para darle vidilla al blog.
Un abrazo, Enrique.
Felipe Vazquez dice
Hola Enrique.
Espero te encuentres bien.
Me gustaría saber si puedes ayudarme con una duda.
Al momento de querer hacer la solución del Efecto Rebote por medio de Software.
¿En qué parte del programa le agregas el delay()? Antes de la función atachtInterrup() o después.
De antemano muchas gracias.
Enrique dice
Buenas Felipe,
Debe implementarse dentro del módulo que se ejecuta cuando se activa la interrupción.
Un saludo, Enrique.
jose dice
muchas gracias por ayudarme.
trate de construirlo y quisiera que me ayudases a verificar si esta bien lo que he querido hacer si no es mucho problema:
int pinder = 13; //nombro los pines
int pinizq = 12;
int estado; //variables
int movimiento;
void setup() {
attachInterrupt(0, paradaestado, RISING);//interrupcion para el boton de
//parada de estado
pinMode(pinder, OUTPUT); //declaro salidas de izq y der
pinMode(pinizq, OUTPUT);
Serial.begin(9600);//comunicacion serial
}
void loop() {
movimiento = 0;//valor predeterminado
while(movimiento == 1){
Serial.println(“derecha”);
digitalWrite(pinder, HIGH);
}
while(movimiento == 2){
digitalWrite(pinder, LOW);//derecha apagado, se detiene
Serial.println(“stop”);
}
while(movimiento == 3){
digitalWrite(pinizq, HIGH);//izquierda encendido
Serial.println(“izquierda”);
}
while(movimiento == 4){
digitalWrite(pinizq, LOW);//izquierda encendido
Serial.println(“stop”);
}
estado = 1;//defino etapa giro derecha
Serial.println(“derecha”);
digitalWrite(pinder, HIGH);//derecha encendido por 3 segundos
delay(3000);
estado = 2;//defino etapa frenado 1
digitalWrite(pinder, LOW);//derecha apagado, se detiene por 4 seguindos
Serial.println(“stop”);
delay(4000);
estado = 3;//defino etapa giro izquierda
digitalWrite(pinizq, HIGH);//izquierda encendido por 1 segundo
Serial.println(“izquierda”);
delay(1000);
estado = 4;//defino etapa frenado 2
digitalWrite(pinizq, LOW);//parada por 2 segundos
Serial.println(“stop”);
delay(2000);
}
//la interrupcion hace que el estado de movimiento sea igual al estado que se
//este ejecutando en ese momento, asi se habilitara el while correspondiente
void paradaestado() {
movimiento = estado;
}
ese seria el programa, si no tienes tiempo esta bien solo te pediria que me dijeras donde podria contactar a algun tipo de mentor ya que aca no tengo, y sos quien responde mas rapido y con mayor experiencia que conozco sobre el tema, muchas gracias
Enrique dice
Buenas Jose,
Lo primero que veo es que los delay() y las interrupciones no se llevan bien :/.
En cualquier caso, te diría que probases el código que has implementado ya que te será más sencillo ver posibles comportamientos erráticos.
Un saludo, Enrique.
José dice
buenas enrique me gusto muchisimo tu post, soy estudiante de secundaria de electrónica y estoy empezando a usar el arduino soy bastante nuevo, todavia no lo tengo pero he empezado a estudiarlo, por q mi tiempo es corto, me fascina este amiguito por que previamente he trabajado con assembler que es mas jodido jaja, pero la idea de programar es casi la misma, y la cuestion esta aca: estoy haciendo un programa que encienda un motor, en realidad hay que verlo como que tiene 4 estados, en el primero manda un high desde un pin durante 3seg (este hara girar el motor a la derecha mediante un puente h) luego esperar 4seg (todo en low) luego 1 otro pin en high (gira a la izq) y despues esperar 2seg mas, esto se repetira ciclicamente y es como un lavarropa (der, stop, izq, stop etc) ahora , necesito 1boton de parada de estado el cual no se como asociarle la interrupcion ni la funcion por q lo q tieene q hacer es justamente mantener el estado que se esta ejecutando en ese momento, es decir, si esta girando a la der y lo presiono, se quedará girando hasta q lo vuelva a presionar o si esta en stop que siga en ese estado cuando lo presione, ese seria mi problema, y quisiera si podes, ayudarme a solucionarlo muchas gracias, perdon por los errores de ortografía :)
Enrique dice
Buenas Jose,
Puedes introducir el código relativo a los movimientos dentro de un if() y “activar o desactivar” ese if() en función del valor de la interrupción, así conseguirás que se siga moviendo el motor al no modificarse la instrucción asociada. Es sólo una idea, seguro que dándole unas vueltas se te ocurre algo mejor.
Un saludo, Enrique.
Pamela dice
Hola, buenos días! Soy estudiante de mecatrónica curso el segundo semestre, me encanto tu articulo/post. Tengo una duda, estoy haciendo un proyecto en la escuela, un “pov led globe”, Estoy ocupando un arduino mega, 24 leds y un motor de ventilador . Estaba ocupando los delay pero ya veo que no era una buena idea, me gustaría ocupar las interrupciones para que el mundito se pueda ver con claridad, el problema es que no tengo idea de como ponerlo en el código :(
int LED = 8;
volatile int estado_actual = LOW;
void fun_cambio_estado()
{
//Se cambia al estado contrario al actual, es decir, de LOW se pasa
//a HIGH y de HIGH a LOW.
estado_actual = !estado_actual;
}
void setup()
{
//Se declara el pin digital correspondiente al LED como salida.
pinMode(LED, OUTPUT);
//Se determina la interrupción 0 (por lo que el pin asociado al pulsador
//será el 2 en caso de tratarse de un Arduino UNO o similar) a la que se
//le asocia la función fun_cambio_estado que se activará al presionar el
//pulsador (por tratarse del modo FALLING).
attachInterrupt(0, fun_cambio_estado, FALLING);
}
void loop()
{
//Se escribe el valor actual del LED.
digitalWrite(LED, estado_actual);
}
No entendí esa parte, donde quedo el pin 2?
De antemano, Gracias!
Enrique dice
Buenas Pamela,
Lo que tienes es que utilizar es simplemente el pin al que esté asociada esa interrupción de Arduino.
Un saludo, Enrique.
Pamela dice
Gracias!! Lo intentare :)
Wilder dice
hola quetal muy bueno el post y bueno no se si me podrias ayudar estoy en un proyecto el cual consiste en un medidor de agua los datos de la lectura del sensor de flujo tienen que ser enviados atraves de un modulo gprs sim900 el problema es que el modulo gprs utiliza los pines 2 y 3 para la comunicacion con el arduino y me invalida la posibilidad de usar las interrupciones ya que el arduino uno maneja solo los pines 2 y 3 para el manejo de interrupciones te agradeceria mucho que me dieras alguna pista saludos…
Enrique dice
Buenas Wilder,
Puedes plantearte usar un Leonardo, que es muy parecido al UNO pero tiene más interrupciones.
Un saludo, Enrique.
Susana dice
Cuál es tu apellido. Lo necesito para una referencia de un reporte. Gracias.
Enrique dice
¿Un reporte? :)
Me apellido Romero.
Un saludo.
Pablo dice
Hola Enrique, Muy bueno tu aporte! Se agradece! Soy estudiante de ingeniería informática y por mi cuenta comencé a hacer proyectos con arduino y tu blog me resulta de gran ayuda. Abrazo grande
Enrique dice
Muchas gracias por los ánimos, Pablo. :)
yonidix manriquez dice
hola Enrique.
Te envío este mensaje para pedirte ayuda con un ejercicio de pulsadores en arduino y guardarlos en la memoria eeprom. Quisiera saber si tienes disponibilidad para hacerlo, ya que he buscado mucha información y no logro saber como hacerlo.
Ahí te dejo mi correo para saber tu respuesta y enviarte el ejercicio.
Gracias ante todo.
Enrique dice
Buenas,
No tengo mucho tiempo últimamente :S pero intentaré ayudarte con las dudas puntuales que puedas tener.
Un saludo, Enrique.
Diego Quimbert dice
Hola Enrique, felicidades, bueno tengo una consulta no se si me salte esa parte o que paso, pero yo tenia entendido que existen distintos tipos de interrupciones, por ejemplo las externas (las que tu mencionaste en tu post) y las internas que son manejando los módulos del timmer del mismo MCU ATMEGA. Saludos!
Enrique dice
Exacto Diego,
Hay un pequeño registro en el chip en el que se almacena si se produjo un tipo de interrupción (sea del tipo que sea) y de ser así, se ejecuta.
Un saludo, Enrique.
Pablo dice
Buenas, estaba programando un teclado de seguridad y queria hacer un gestor de bateria, mientras la bateria esta por encima del 20% parpadearia un led verde, y cuando estuviera por debajo del 20% un led rojo, la cosa es que estoy usando un teclado matricial conectado en los pines digitales del 2 al 9 de un arduino uno, con lo que no podria usar los pines de las interrupciones, mi duda es si podria usar la interrupcion para medir ese porcentaje de alguna manera, o si en este programa no es necesario usar interrupciones? Muchas gracias ^^
Enrique dice
Buenas Pablo,
Puedes simplemente monitorizar el estado de la batería cada cierto tiempo o incluso ampliar los pines de Arduino para evitar este tipo de problemas, te dejo un post sobre esto.
Un saludo, Enrique.
Cristian dice
Excelente articulo Enrique ! gracias por compartir y enseñarnos mas cosas.
Enrique dice
Gracias a ti por leerlo, Cristian. Me alegro de que te haya gustado. :)
Un saludo.
pablo dice
Hola Enrique, excelente post.
Me gustaría hacerte una consulta sobre los antirrebotes de botones, la cuestión es que estoy haciendo un cronometro, de tal forma que cuando pase un objeto por delate de un ldr iluminado con un láser empiece a contar y cuando pase por otro pare de contar, el problema es que tengo 4 botones que controlan el valor de una variable pero el antirrebote lo hago con delays y creo que por eso hay errores en el resultado fina. Como no puedo añadir un condensador como dices en el post me gustaría arreglarlo vía software, ¿como podría evitar estos delays?
Un saludo
Enrique dice
Buenas Pablo,
Las interrupciones son “incompatibles” con los delays, pero sí que puedes utilizar delayMicrosecond().
Un saludo, Enrique.
pablo dice
Muchas gracias por responder Enrique.
Me gustaría hacerte una pregunta más, intentando aplicar la teoría de este post, me di cuenta de que no entendía muy bien que es una variable tipo volatile int, no si me lo podrás explicar, ¿ Qué es? ¿ Cómo funciona?
Un saludo y nuevamente muchísimas gracias.
Enrique dice
Buenas Pablo,
La instrucción volatile se utiliza para decirle al compilador que almacene la variable en la RAM en lugar de en el registro donde se almacenaría habitualmente, con ello se consigue que pueda ser accedida por acciones “externas” al sketch como son las interrupciones.
Un saludo, Enrique.
Arroyo Rivera dice
Hola que tal, me parece muy util tu post, tengo una pregunta, espero que me puedas ayudar, trabajo en un proyecto bio-médico y necesito lo siguiente:
se estará ejecutando una rutina en el arduino, pero al momento de que por bluetooth, por medio de una app, se mande un caracter, se pase a ejecutar las ordenes que se mandan del celular y se dejen de ejecutar las rutinas que se estaban ejecutando, la pregunta sería, como hago para que la interrupción me detecte ése caracter, leí que comentaste algo de serialEvent….
espero me puedas ayudar, gracias y excelentísima página
saludos
Enrique dice
Buenas Arroyo Rivera,
El serialEvent(){} es una función que se activa cuando se reciben datos. Puedes implementar instrucciones dentro de ésta (entre los corchetes) como sería, por ejemplo, Serial.read() para que (cuando recibas datos) los lea tu placa o los gestiones como necesites.
Un saludo, Enrique.
Claudio dice
Hola, el post solo hace referencia a que las interrupciones se activen según un valor binario (HIGH y LOW), si el sensor devuelve otros valores (como el sensor de temperatura y humedad DHT), puede configurarse la interrupción para que se dispare después de cada cambio de valor?
Saludos, Claudio
Enrique dice
Buenas Claudio,
La verdad es que no tengo demasiada experiencia con esos sensores pero si no me equivoco funcionan por comunicación serie con la placa. En tal caso lo que puedes hacer es poner el pin del sensor relativo a esa comunicación en paralelo con la base de un transistor que sea la que active el paso de un voltaje HIGH o LOW con los que regular la activación de las interrupciones.
Un saludo, Enrique.
Eduardo desde Argentina dice
Muchas gracias Enrique
Jorge dice
Tengo un proyecto de cuando se activan switch realice una accion pero tengo ocupado todos los pines, como puedo ocupar las interrupciones cuando tengo todos los pines ocupados? debido a que mi codigo es muy extenso y mientras realiza el resto del codigo y se activa un switch espera q ejecute el resto del codigo y despues activa la salida cuando regresa a la linea en la q pregunta x el switch..
Enrique dice
Buenas Jorge,
Puedes ampliar las salidas de Arduino para dejar libres las correspondientes a las interrupciones. Te dejo un link sobre cómo realizarlo.
Un saludo, Enrique.
MIRM dice
Excelente post.
Tengo la duda de como podría hacer para cambiar una variable guardada en la EEPROM mientras se ejecuta la interrupción para después utilizarla en el programa principal. Necesito guardar esta variable forzosamente en la EEPROM pues no quiero perder este dato aun cuando se quita la energía en el Arduino.
saludos.
Enrique dice
Buenas Mirm,
Puedes almacenar la variable en la memoria EEPROM sin problema. Te dejo un post para que te hagas una idea de cómo se haría.
Un saludo, Enrique.
Vicente dice
Cuidado, que la EEPROM tiene un número limitado de escrituras.
Saludos.
Francisco dice
Hola,
Me ha resultado muy esclarecedor este artículo tuyo Enrique. Llevo 8 años trajinando con Arduino y las interrupciones siempre me resultaron “yu yu”, hasta ahora.
Me gusta mucho tu estilo pedagógico. Tienes madera de profe, como soy yo. Además somos colegas pues yo también soy Ingeniero de Telecomunicaciones, aunque mucho mas viejo que tu.
Saludos.
Enrique dice
Buenas Francisco,
Siempre es un gusto encontrarse con telecos :). Me alegro de que te haya servido el post.
Un saludo, Enrique.
Jairo Andres Acevedo dice
Enrique, buen tutorial. Conoces como son las interrupciones por transmisión y recepción con la USART=? gracias
Enrique dice
Buenas Jairo,
Supongo que te refieres a las interrupciones del tipo serialEvent() en las que se realiza alguna acción tras la llegada de algún carácter… ¿Qué problema tienes exactamente?
Lamento la tardanza. Un saludo, Enrique.
Antony dice
Gracias por la pronta respuesta Enrique.
Lo que pasa es que cuando la puerta se encuentra cerrada, tendría 5Vdc en el pin y cuando se encuentre abierta tendría 0Vdc, lo que podría hacer es una interrupcion en CHANGE y luego leer el nivel de voltaje en el Pin de interrupción para saber si se encuentra abierta o cerrada. Quedaría probar que solución me consume menos bateria.
Gracias por el comentario!
Enrique dice
Buenas Antoni,
En ese caso, una interrupción de tipo CHANGE es buena opción.
En cuanto a lo de leer el voltaje del pin, de eso ya se encarga la propia interrupción. Así que no debes preocuparte.
Un saludo, Enrique
Antony dice
Enrique que tal, un gusto participar en tu sitio web.
Tengo una consulta, por ejemplo necesito conocer cuando se abra y cierre una puerta mediante un reel switch, estoy pensando en hacerlo con 02 interrupciones (Falling y Rising) pero orientadas al mismo pin de interrupción, será posible asignar estos 2 modos diferentes al mismo pin? Gracias de antemano.
Sldos.
Enrique dice
Buenas Antony,
Para una misma interrupción sólo puedes establecer un modo de “activación”. En cualquier caso, no creo que necesites utilizar más. El hecho de que la puerta suba o baje no influye en el voltaje, es decir, si tu sensor manda 5V pasadas “x” distancias, en ambos casos (cuando abre y cuando cierra) el efecto en la interrupción es el mismo. Lo que puedes hacer es utilizar una variable booleana en la interrupción y así cuando ocurre la interrupción una vez abre y la siguiente cierra.
Esperando haberte ayudado. Un saludo, Enrique.
asploman dice
Oye y que hay de las interrupciones internas ? buen post man ;)
Enrique dice
Buenas Asploman,
Si buscas hacer cosas más complejas, más cerca de lo que es el controlador, necesitas programarlo mediante AVR (sin utilizar la IDE de Arduino).
Un saludo, Enrique.
Oscar dice
Hola, Excelente tu post, podrías poner un ejemplo de interrupción por software? es que no me quedó claro sobre cómo usarlas, soy nuevo en esto gracias por la paciencia
Enrique dice
Buenas Oscar,
¿A qué te refieres exactamente con interrupción por software?
Un saludo, Enrique.
Jukar dice
Hola Enrique. Muchas gracias y Enhorabuena por tu post, es lo mas claro y conciso que he leído referido a las interrupciones en Arduino. Ahora solo me queda revisar todos mis sketch es y modificarlos xd
Enrique dice
Buenas Jukar, me alegro de que te haya gustado.
Espero que no sean muchos sketchs sino… ¡Vaya curro! pero seguro que notas la diferencia :)
Un saludo, Enrique.