0% encontró este documento útil (0 votos)
86 vistas8 páginas

Código, Tips y Programas Varios - Manejo de Interrupciones Con Arduino

Este documento describe cómo manejar interrupciones externas con Arduino. Explica que las interrupciones permiten que el microcontrolador deje de ejecutar su código principal temporalmente para atender eventos externos como cambios en líneas de entrada. Detalla que Arduino usa bibliotecas que simplifican el manejo de interrupciones, permitiendo asociar código a interrupciones específicas. Finalmente, menciona que las funciones de interrupción de Arduino son básicas y que para aplicaciones avanzadas se debe revisar la documentación del microcontrolador.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
86 vistas8 páginas

Código, Tips y Programas Varios - Manejo de Interrupciones Con Arduino

Este documento describe cómo manejar interrupciones externas con Arduino. Explica que las interrupciones permiten que el microcontrolador deje de ejecutar su código principal temporalmente para atender eventos externos como cambios en líneas de entrada. Detalla que Arduino usa bibliotecas que simplifican el manejo de interrupciones, permitiendo asociar código a interrupciones específicas. Finalmente, menciona que las funciones de interrupción de Arduino son básicas y que para aplicaciones avanzadas se debe revisar la documentación del microcontrolador.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 8

18/11/2015 Código, 

Tips y Programas Varios: Manejo de Interrupciones con Arduino

Código, Tips y Programas Varios
Pequeño blog aderezado con trocitos de código.

19 DICIEMBRE 2012
ENLACES
Manejo de Interrupciones con Arduino La Tienda de TeUbi.co

El artículo anterior conectamos un simple display de 7 segmentos a nuestro Arduino y programamos
un sencillo contador. Pero... ¿Qué tal si queremos interactuar con eventos externos? PÁGINAS DATOS
PERSONALE
Fuente S
Una de las formas comunes de interactuar con cosas que suceden "fuera" de nuestro control es por Abierta
ejemplo  monitorear  el  estado  de  las  líneas.  Dentro  de  nuestro  "loop"  principal  podemos  leer Directorio de
continuamente el valor de una línea de entrada y ejecutar por medio de una condicional un código Software
especifico en caso de que detectemos un cambio. MiniSXF
DRGPIO
El problema de este método es que el código se vuelve sumamente complejo cuando tenemos que Mario
In English
Gómez
monitorear  muchas  cosas  o  cuando  nuestro  loop  principal  simplemente  tiene  que  hacer  cosas  que
Seguir 376
toman demasiado tiempo.
Ver todo mi
En esta entrada vamos a comprender como utilizar las interrupciones externas del Arduino. Esto nos perfil
será de mucha utilidad para interactuar ya sea con el usuario o con otros dispositivos de hardware
que emitan "señales" que nos permitan saber que un evento ha sucedido. ARCHIVO DEL BLOG
►  2015 (5)
Antes de continuar preparen su display de 7 segmentos porque en esta entrada lo vamos a re­utilizar.
►  2014 (9)
►  2013 (39)
Una cosa a la vez... ▼  2012 (17)
▼  diciembre (11)
Los Arduino basados en los microcontroladores Amtel AVR pueden ejecutar una sola secuencia de El Muro de la Vergüenza
instrucciones a la vez. El problema de esto es por ejemplo, si ustedes están enviando números a su
DNS Dinámico en la
display y luego el usuario presiona un botón. Si nuestro ciclo toma mucho tiempo en ejecutarse puede Raspberry PI
que  pase  mucho  tiempo  antes  de  que  podamos  leer  la  línea  de  nuestro  usuario  y  perdamos  el
Haciendo un "puente
evento,  o  tal  vez  simplemente  estamos  ocupando  un  ciclo  en  hacer  algo  interesante.  Esto  es  una wireless" para la
"desventaja" de microcontroladores sencillos y es algo con lo que las computadoras han tenido que Raspberry PI...
convivir prácticamente desde que fueron inventadas. Instalando Lighttpd+PHP
5+Sqlite en la RasPI
¿Como manejar eventos externos? Manejo de Interrupciones
con Arduino
Afortunadamente los diseñadores de microcontroladores pensaron en este problema hace bastante Fabricando un contador
tiempo  y  de  ahí  surgieron  las  famosas  "interrupciones".  Las  interrupciones  (omitiendo  muchos simple con Arduino y
un dis...
detalles)  funcionan  de  manera  muy  sencilla:  Existe  una  lista  de  eventos  internos  o  externos  que
genera  ya  sea  el  microcontrolador  o  una  línea  externa  y  al  detectarse  estos  eventos  el Conectando la Raspberry
PI al Arduino vía Serial
microcontrolador  detiene  la  secuencia  de  comandos  que  está  ejecutando.  Luego  de  esto,  llama  al
código  definido  previamente  que  se  encarga  de  "manejar"  esa  interrupción  en  específico  y  luego, Redimensionando
Imágenes con PHP y
cuando ha terminado de "atender la interrupción" regresa a ejecutar la secuencia principal que había
GD
dejado pausada.
Convirtiendo Gráficos
Vectoriales (SVG) en
Tal vez no es una solución perfecta pero nos permite "atender" cosas que consideramos importantes PNG pro...
por ejemplo cuando un dispositivo externo envía datos vía serial o cuando una línea de interrupción
¡Hello World! en Java
cambia su valor de 0 a 1 o viceversa. (Estricto al paradigma
OO)
Hablando un poco más sobre las interrupciones Variando la intensidad de
un LED en Arduino con
PW...
No  hay  un  "estándar"  de  como  se  manejan  o  cuales  on  las  interrupciones  disponibles.  Cada
fabricante implementa diferentes tipos de interrupciones dependiendo del microcontrolador que han ►  noviembre (2)
diseñado  y  el  uso  que  se  le  piensa  dar.  La  ventaja  con  los  Arduinos  es  que  como  comparten  un
►  octubre (4)
microprocesador  común  los  desarrolladores  han  creado  unas  bibliotecas  que  permiten  manejar
interrupciones de una manera muy sencilla.

http://fuenteabierta.teubi.co/2012/12/manejo­de­interrupciones­con­arduino.html 1/8
18/11/2015 Código, Tips y Programas Varios: Manejo de Interrupciones con Arduino
Nota aclaratoria: Las funciones de manejo de interrupciones de la referencia del Arduino son muy,
pero  muy  básicas.  Los  microprocesadores  Amtel  AVR  tienen  una  larga  lista  de  diferentes  tipos
interrupciones  disponibles.  Sin  embargo  el  manejar  estas  interrupciones  no  resulta  "tan  trivial"  y
depende mucho de las características de cada microprocesador en particular. Para aplicaciones más
avanzadas,  si  desean  más  información  de  como  programar  estas  interrupciones,  pueden  revisar  la
documentación de AVR Libc en la sección dedicada al manejo de interrupciones.

En Arduino podemos asociar el código de las interrupciones a través de la función attachInterrupt().
Las interrupciones o eventos que podemos asociar a las líneas mediante esta función en el Arduino
Mega son las siguientes:

1.  Cuando el nivel lógico de la línea es 0 (LOW)
2.  Cuando el nivel lógico de la línea cambia independientemente de su estado lógico (CHANGE)
3.  Cuando el nivel lógico cambia de 0 a 1 (RISING)
4.  Cuando el nivel lógico cambia de 1 a 0 (FALLING)

Antes de continuar, vamos a hacer un pequeño circuito que nos permita cambiar los valores lógicos
de las líneas de interrupción:

Al circuito anterior se le conoce como "resistencia pull­up", su función es mantener  un nivel lógico en
la  compuerta  aunque  el  circuito  se  encuentre  abierto.  Para  nuestro  caso  mantendrá  un  1  lógico
permanente con el pulsador abierto y un 0 lógico cuando esté cerrado.

Luego, para capturar las interrupciones la tenemos un poquito más fácil, simplemente replicamos este
circuito para cuantos interruptores querramos capturar y lo conectamos a las líneas correspondientes.
Para este ejemplo utilizaremos las líneas 18, 19 y 20 que corresponden a las interrupciones 3, 4 y 5
del Arduino.

Esta es una pequeña foto de como se ven los pulsadores armados en la breadboard:

Notarán  que  uso  resistencias  de  10K.  Usualmente  se  recomienda  el  uso  de  resistencias  de  4.7K,
lástimosamente no tenía a la mano a la hora de armar el circuito, sin embargo, en la práctica no hay
demasiada  diferencia  ya  que  su  único  trabajo  es  evitar  que  cuando  presionemos  el  pulsador  se
produsca un corto circuito.

Programando las Interrupciones

Lo  primero  que  tenemos  que  hacer  es  definir  algunas  constantes  que  nos  indiquen  las  lineas  que
utilizaremos como interrupciones, además de algunas variables "volatiles". En general, utilizaremos el
modificador  "volatile"  para  indicarle  al  compilador  que  nuestra  variable  podría  ser  accedida  desde
http://fuenteabierta.teubi.co/2012/12/manejo­de­interrupciones­con­arduino.html 2/8
18/11/2015 Código, Tips y Programas Varios: Manejo de Interrupciones con Arduino
distintas  ubicaciones  en  el  código  de  nuestro  programa.  Esto  obliga  a  asignar  espacio  de  RAM  a
nuestra variable en vez de guardarla en la memoria de datos.

// Botones
const int BTN1 = 18;
const int BTN2 = 19;
const int BTN3 = 20;

// Display 7‐Segmentos
const int D0 = 4;
const int D1 = 5;
const int D2 = 6;
const int D3 = 7;

// Contador
volatile int inc;

// Encendido y Apagado del display
volatile int onOff;

// Tiempo en que se realizo la última interrupción.
volatile long lastInt;

Las constantes de nombre "BTN" representan mis botones y las constantes "D" las líneas a donde
tengo conectado el decodificador a 7 segmentos.

Definiendo las funciones que modificarán los valores

Vamos  a  definir  un  par  de  funciones  "ayudantes"  extra  que  se  encargarán  de  incrementar  y
decrementar el contador.

// Incrementa y escribe el número al display
void increment() {
  inc++;
  inc = (inc < 10) ? inc : 0;
  writeTo7Seg(inc);
}

// Decrementa y escribe el número al display
void decrement() {
  inc‐‐;
  inc = (inc >= 0) ? inc : 9;
  writeTo7Seg(inc);
}

El  siguiente  paso  es  definir  el  código  que  se  encargará  de  manejar  las  interrupciones,  vamos  a
realizar  funciones  muy  simples,  un  botón  incrementara  el  contador,  el  otro  lo  disminuira  y  el  último
encenderá  y  apagará  el  display  de  7  segmentos.  Con  las  funciones  anteriores  el  código  se  vuelve
muy fácil de entender:

// Codigo para la interrupcion 5
void int5() {
    increment();
}

// Codigo para la interrupcion 4
Este sitio emplea cookies de Google para prestar sus servicios,
void int4() {
para personalizar anuncios y para analizar el tráfico. Google recibe
    decrement();
información sobre tu uso de este sitio web. Si utilizas este sitio web,
}
se sobreentiende que aceptas el uso de cookies.

MÁS INFORMACIÓN ENTENDIDO
// Codigo para la interrupcion 3
void int3() {
    onOff = onOff^1;
    if(onOff) {
      writeTo7Seg(15);

http://fuenteabierta.teubi.co/2012/12/manejo­de­interrupciones­con­arduino.html 3/8
18/11/2015 Código, Tips y Programas Varios: Manejo de Interrupciones con Arduino
    } else {
      writeTo7Seg(inc);
    }
}

Por  defecto  no  hay  ningún  código  asignado  para  manejar  las  interrupciones,  por  ello  es  necesario
que definamos la asociación de las interrupciones en el "setup".

void setup() {
  // Establecemos las líneas del display como salida
  pinMode(D0,OUTPUT);
  pinMode(D1,OUTPUT);
  pinMode(D2,OUTPUT);
  pinMode(D3,OUTPUT);
  
  // Inicializamos nuestras variables
  inc = 0;
  lastInt = 0;
  onOff = 1; //Displa encendido al encender
  
  // Asociamos la interrupción a nuestro código
  attachInterrupt(5,int5,RISING); // línea 18
  attachInterrupt(4,int4,RISING); // línea 19
  attachInterrupt(3,int3,RISING); // línea 20
  
  //Colocamos un 0 en nuestro display de 7 segmentos
  writeTo7Seg(inc);
}

Tal vez en este momento se estén haciendo la siguiente pregunta: ¿Por qué uso RISING y no otro
tipo  de  interrupción?  La  respuesta  a  esta  pregunta  realmente  tiene  mucho  que  ver  con  lo  que
estemos  programando  y  como  querramos  que  funcione.  En  este  caso,  quería  que  el  contador  se
incrementara cuando el usuario dejara de presionar el botón, como nuestro botón genera un 0 lógico
cuando  esta  presionado  y  un  1  lógico  cuando  esta  sin  presionar  si  queremos  incrementar  nuestro
contador justo despues de que se ha presionado el botón el evento RISING es el más adecuado. Si
en  cambio  estuvieramos  programando  algo  como  un  control  de  arcade  posiblemente  deberíamos
usar la interrupción FALLING para que el usuario no perciba un "retardo" a la hora de presionar el
botón y ver una respuesta en el juego.

¿Qué hacemos luego con el loop principal?

Pues nada, lo dejamos vacío ya que no lo utilizaremos en este ejemplo:

// Loop vacío
void loop() {
}

Bonus: Eliminando el Rebote vía software.
Si toman el código que puse anteriormente junto con el circuito que coloqué, se van a dar cuenta que
el contador funciona de manera errática como se muestra en el siguiente video: 

Este  no  es  un  problema  de  software  sino  más  bien  de  hardware.  Es  el  famoso  "rebote"  de

http://fuenteabierta.teubi.co/2012/12/manejo­de­interrupciones­con­arduino.html 4/8
18/11/2015 Código, Tips y Programas Varios: Manejo de Interrupciones con Arduino
interruptores. 

Uno  de  los  grandes  problemas  al  trabajar  con  circuitos  digitales  e  interruptores,  es  que  los
interruptores  simplemente  no  son  perfectos.  Dependiendo  del  diseño  de  los  mismos,  estos  pueden
dar lugar a este molésto fenómeno. 

El  rebote  literamente  significa  que  los  contactos  dentro  del  interruptor  rebotan  brevemente,  esto
sucede tan rápido que simplemente no nos damos cuenta, pero el circuito digital en vez de recibir un
solo pulso recibe varios. 
¿Cómo corregir el rebote?

Existen diferentes métodos vía hardware para eliminación de rebote de interruptores, sin embargo si
su aplicación no necesita tiempos de respuesta "críticos". Pueden utilizar esta sencilla solución que
les propongo a continuación.

Primero,  ¿Recuerdan  la  variable  "lastInt"  que  definimos  al  principio?  Lo  que  vamos  a  hacer  para
eliminar  el  rebote  es  "filtrar"  nuestras  interrupciones.  La  lógica  que  utilizaremos  es  muy  simple,  si
nuestra  interrupción  ocurre  en  menos  del  tiempo  umbral  especificado  entonces  simplemente  la
ignoraremos.

¿Cuanto  es  el  umbral  que  deseamos  definir?  La  respuesta  no  es  sencilla  ya  que  depende  de  las
caraterísticas físicas interruptor que estemos usando. En mi circuito, luego de experimentar con un
poco de prueba y error, un umbral de 200 milisegundos parece funcionar a la perfección.

Para  hacer  funcionar  este  eliminador  de  rebote  por  software  simplemente  vamos  a  usar  una
condicional y antes de salir de la función guardaremos el valor de millis() y vamos a comparar para
ver si ha pasado tiempo suficiente.

¡¡¡Mucho  Cuidado!!!  el  valor  de  millis()  se  reinicia  automáticamente  aproximadamente  cada  70  días.
Esto  significa  que  si  deciden  usar  este  método  y  piensan  tener  funcionando  su  arduino  sin  parar
durante más de 70 días, tienen que capturar la excepción de reinicio del contador de milisegundos
porque  si  no,  llegara  un  momento  que  nunca  se  cumplirá  la  condición  y  se  ignorarán  todas  las
interrupciones que usen este método. Así que: "advertidos están". 

Una vez dada esta advertencia modifiquemos un poco nuestro código de manejo de interrupciones: 

void int5() {
  if((millis()‐lastInt)>200) {
    increment();
    lastInt = millis();
  }
}

void int4() {
  if((millis()‐lastInt)>200) {
    decrement();
    lastInt = millis();
  }
}

void int3() {
  if((millis()‐lastInt)>200) {
    onOff = onOff^1;
    if(onOff) {
      writeTo7Seg(15);
    } else {
      writeTo7Seg(inc);
    }
    lastInt = millis();
  }
}

Nota: Si notan, comparto "lastInt" con todo el código de interrupciones, esto en la práctica significa
que  no  solo  estoy  eliminando  el  rebote  sino  también  la  posibilidad  de  presionar  dos  botones
diferentes en menos de 200ms. Una posible solución a este bug es utilizar un marcador de tiempo
diferente  para  cada  interrupción  (latInt1,  lastInt2,  lastInt3),  de  esta  manera  podríamos  eliminar

http://fuenteabierta.teubi.co/2012/12/manejo­de­interrupciones­con­arduino.html 5/8
18/11/2015 Código, Tips y Programas Varios: Manejo de Interrupciones con Arduino
efectivamente el rebote para cada interruptor de manera independiente, sin bloquear la ejecución del
código en caso de recibir una interrupción de una línea diferente.
Probando Todo

Pueden descargar el código y cargarlo a su arduino. Si utilizan otra tableta diferente a la Mega solo
revisen la lista de interrupciones y ajusten los pines de salida a su conveniencia en el código. 

Si todo funciona bien deberá de funcionar de manera similar a como se muestra en el siguiente video:

Conclusiones
Las interrupciones resultan sumamente útiles para ejecutar código de manera asíncrona, es decir que
nuestro código reaccione a eventos externos sin necesidad de estarlos monitoreando continuamente.

En esta entrada he "abusado" un poco de las interrupciones externas. Jugando un poco con circuitos
digitales  podemos  crear  una  especie  de  controlador  de  interrupciones  que  nos  permita  monitorear
varios eventos utilizando una sola línea de interrupción, sin embargo esto lo podemos dejar para una
entrada posterior.

Ya solo nos queda un artículo más para esta serie de tres entradas, en el último artículo leeremos
datos  de  la  Raspberry  e  intentaremos  crear  una  aplicación  interesante  con  nuestro  módulo  de
pruebas. 

No habiendo nada más que decir por ahora... ¡Hasta la próxima!
Publicado por Mario Gómez en 11:13 p. m. 

+4   Recomendar esto en Google

Etiquetas: Arduino, ArduinoBoardMega, Interrupciones

9 comentarios:
Moises Alm dijo...
Saludos muy bueno el articulo, soy nuevo en el mundo de los micotroladores. Me gustaria
saber si las interrupciones se limitan solo a las entredas digitales I/O, por que estoy
necesitando una interrrupcion para un ADC. Estoy utilizando un ARDUINO NANO Ver.3.
Gracias.
20 de agosto de 2013, 21:13

Mario Gómez dijo...
¡Hola Moises!

Según leo en la hoja técnica del ATMega328 (Pag #65), si es posible agregar código de
interrupción para detectar el "final de conversión" (22 0x002A ADC ADC Conversion
Complete).

Ahora, si lo que quieres es lanzar una interrupción cuando exista un cambio en el voltaje,
existe otra interrupción (24 0x002E ANALOG COMP Analog Comparator).

Estas interrupciones no se pueden configurar con la instrucción "attach" de Arduino,
tendrías que hacerlo a mano utilizando un código similar al que se muestra en este link:
http://www.uchobby.com/index.php/2007/11/24/arduino­interrupts/

Voy a tratar de hacer de hacer tiempo para escribir un tutorial sobre usos avanzados de

http://fuenteabierta.teubi.co/2012/12/manejo­de­interrupciones­con­arduino.html 6/8
18/11/2015 Código, Tips y Programas Varios: Manejo de Interrupciones con Arduino
interrupciones.

¡Saludos!
23 de agosto de 2013, 9:38

miguel aguilar dijo...
Buen dia buen articulo pero falta la escritura en 7 segmentos podrias pasarmela para revisar
9 de octubre de 2013, 4:26

Homar Lopez dijo...
Hola, gracias por tu aporte, pero me podrias expliccar donde ubico los difrentes codigos? ya
esta claro que el loop queda vacio, pero el resto donde va? al inicio? en el setup??
gracias..
23 de enero de 2014, 6:31

Mario Gómez dijo...
¡Hola Homar!

Las interrupciones se ejecutan bajo "demanda" es decir, cuando se recibe un cambio en la
línea de la interrupción. Por ello no se colocan en el loop principal.

La forma que Arduino te permite asociar un código específico a una interrupt es la función
attachInterrupt donde especificas:

attachInterrupt(,,);

Por ejemplo, digamos que tienes el código siguiente que quieres que se ejecute con el
cambio en la interrupción 3:

void cambioInt3() {
Serial.println("Cambio detectado");
}

Para asociarlo al cambio de línea, en el setup tendrías que colocar:

attachInterrupt(3, cambioInt3, FALLING);

FALLING indica que la interrupción se ejecutará cuando el nivel lógico de la interrupción 3
cambie de 1 a 0.

Espero haberte ayudado. ¡Saludos!
23 de enero de 2014, 7:42

Javi dijo...
Hola Moises.
Antes de nada agradecerte esta publicación. A despejado muchas dudas, aunque como
pasa siempre, abierto otras.

Te cuento, estoy intentando controlar mediante RC (emisora­receptor) un coche, robot o
quad (aun no lo he hecho, estoy en fase aprendizaje), pero he visto que por problemas de
tiempo de eventos (lo que tu bien explicas) no puedo utilizar PulseIn(), sino que tengo que
utilizar las interrupciones.
Mi preguntas son:

a)Cómo leo 6 canales o entradas con un Arduino Uno que tiene disponibles dos
interrupciones

b) No entiendo bien lo de las interrupciones asociadas a un pin. Significa eso que solo
puedo hacer la interrupción de ese pin en concreto.

Muchas gracias de nuevo.
Un saludo,

Javi
6 de mayo de 2014, 3:49

http://fuenteabierta.teubi.co/2012/12/manejo­de­interrupciones­con­arduino.html 7/8
18/11/2015 Código, Tips y Programas Varios: Manejo de Interrupciones con Arduino

eduardoz barea escobar dijo...
buenas, tengo una mini pro compatible jy­mcu y supuestamente deberia tener el
attachinterrupt0 en el pin 2 pero no me funciona.

he estado buscando informacion pero no encuentro nada. 

Se puede asignar el attachinterrupt el pin que yo defina??

muchas gracias
20 de mayo de 2014, 8:00

Juan Carlos Durán dijo...
Hola disculpa ¿no sabrás como realizar las interrupciones en un periodo de tiempo? 
Por ejemplo, necesito contar cuantas interrupciones se dan en 10 segundos... ¿Tendrás
alguna idea o referencia de cómo hacerlo?
Sería de gran ayuda, agradezco de antemano.
1 de diciembre de 2014, 18:04

Cristian Veloso dijo...
Excelente articulo, justo estaba pensando en redactar un articulo referido a lo mismo.
se les interesa les comparto mis notas

http://www.electrontools.com/2014/08/registro­de­desplazamiento­74hc595.html

espero que les agrade.
saludos!
14 de julio de 2015, 12:25

Publicar un comentario en la entrada

Entrada más reciente Página principal Entrada antigua

Suscribirse a: Enviar comentarios (Atom)

Plantilla Picture Window. Con la tecnología de Blogger.

http://fuenteabierta.teubi.co/2012/12/manejo­de­interrupciones­con­arduino.html 8/8

También podría gustarte