Interrupciones de Software con Arduino

Interrupciones de Software con Arduino

Las interrupciones de software con Arduino, también llamadas interrupciones de timer o de tiempo, son un tipo de interrupciones que se programan o configuran y sirven para varios propósitos pero nosotros abordaremos uno de los más interesantes que es la ejecución de instrucciones en períodos programados e independiente del programa principal del Arduino.

En los proyectos que usted trabajará, es posible que se encuentre con la necesidad de hacer 2 cosas a la vez (o simularlo) como por ejemplo prender un led 3 veces por segundo y prender otro a la vez 5 veces por segundo. Como ambos son numeros primos, no será facil armar un bucle para cumplir las dos tareas a la vez.

Una solución sería usar millis() y comparar tiempo, pero hay situaciones en donde no tenemos bien definidas las tareas y esto no es posible, como por ejemplo responder a módulos manteniendo un led prendiendo 2 veces por segundo. Entonces si usa un bucle lo que pase en medio de él puede alterar la frecuencia del encendido del led.

¿Qué son las interrupciones de software?

Las interrupciones de software con Arduino es una forma especial de programa que le indica a su Arduino que interrumpa la ejecución del programa principal cada cierto tiempo, y haga algo (por ejemplo ejecute una serie de instrucciones). En cierta manera, configuradas correctamente le permite simular que su Arduino de hecho puede hacer más de una tarea a la vez. De hecho, usted podría configurar una interrupción de tiempo para que corra en una frecuencia realmente rápida (muchas veces por segundo) y crear así una segunda función loop() que su Arduino evaluará.

El Arduino UNO posee 3 interrupciones de software mientras que el Arduino Mega 2560 posee 6. Las interrupciones usan unos contadores internos para saber cuando “interrumpir”. No todas las interrupciones disponibles en los Arduino son iguales pero para el propósito que buscamos en este explicativo nos alcanza con lo explicado.

Las interrupciones son sensibles al reloj del microcontrolador. Esto significa que si su Arduino usa un cristal diferente al estandard, las interrupciones funcionarán diferente también, ya que su configuración se hace a través de funciones matemáticas dividiendo la frecuencia del reloj. En ambos Arduino UNO y Mega 2560 el reloj anda a 16Mhz o 16.000.000 ciclos por segundo, pero hay versiones chinas que usan cristales de menor frecuencia (yo poseo uno a 12Mhz).

La librería TimerOne

Arduino comparte en su sitio oficial una librería para facilitar la tarea de usar las interrupciones de software con Arduino, o mejor dicho, para usar una de ellas llamada Timer1 (o en inglés TimerOne). La misma es compatible con varios tipos de Arduino pero nosotros nos concentraremos en los dos que trabajamos, es decir el Arduino UNO y el Arduino Mega 2560.

En este explicativo usaremos la librería mencionada que puede descargarla desde aquí.

Luego de instalar la librería podrá probar el Sketch de ejemplo que les comparto más abajo.

Ejemplo

El siguiente ejemplo inicializa una interrupción de software con Arduino para prender un led (el led de la placa) cada 1 segundo, mientras en el programa principal leerá lo que ustedes envíen por el Monitor Serial y lo repetirá como contestación. El siguiente Sketch funciona tanto en Arduino UNO como en Arduino Mega 2560 y considera que usted usa un Arduino original o al menos una version que anda a 16Mhz.

#include <TimerOne.h>

void setup() {
  
  // Inicializamos el pin 13 como salida
  pinMode(LED_BUILTIN, OUTPUT);
  // Nos aseguramos que al comenzar el led este apagado
  digitalWrite(LED_BUILTIN, LOW);
  
  // Inicializamos Timer1 para que ejecute cada 0,5 segundos (dos veces por segundo)
  Timer1.initialize(500000);
  // Ejecutar por cada interrupción la funcion parpadearLED()
  Timer1.attachInterrupt(parpadearLED);
  
  // Finalmente inicializamos el Monitor Serial 
  Serial.begin(9600);
}

void loop() {
  char buffer[256]; 
  
  if (Serial.available()) {
    buffer[Serial.readBytesUntil('\n', buffer, 256)] = '\0';
    
    Serial.println(String("Usted envio: ") + buffer);
  }
}

// Usamos esta variable global para guardar el estado del led (apagado inicialmente)
bool estado = false;

void parpadearLED() {
  if (estado) {
    digitalWrite(LED_BUILTIN, LOW);
    estado = false;
  }
  else {
    digitalWrite(LED_BUILTIN, HIGH);
    estado = true;
  }
}

Luego de cargar el Sketch en su Arduino UNO o Mega 2560, abra el Monitor Serial y envíe cualquier texto que Arduino le responderá. Mientras tanto observe que el led interno (de la placa) parpadea una vez por segundo, aun cuando usted le envíe algo por el Monitor Serial.

Limitaciones de las Interrupciones de Software con Arduino

Si bien lo compartido parece demasiado bueno para ser verdad, existen algunas limitaciones y consideraciones. Lo primero es que su Arduino en realidad está interrumpiendo la ejecución de su programa para hacer lo que usted le pidió al configurar la interrupción. Si dicha tarea es muy compleja y demora mucho tiempo, puede tener inconvenientes como por ejemplo afectar al programa principal (donde se noten las interrupciones) o incluso que se le apilen las interrupciones.

Para evitar que las interrupciones se apilen puede desactivarlas mientras trabaja dentro de la función de la interrupción mediante la función noInterrupts() y antes de finalizar puede activarlas de nuevo con la función interrupts().

El otro aspecto importante es el uso de variables. A veces es util el uso de variables globales para compartir información entre el programa principal y la función de interrupción. Sin embargo, esto es peligroso y trae muchas consideraciones. Una manera sencilla de evitar dolores de cabeza es desactivar las interrupciones cada vez que usted lea o escriba en una variable global compartida (usando las funciones mencionadas antes).

Avanzado

Puede ver como funcionan las interrupciones de timer en más detalle en este instructivo.

 

Deja un comentario