Skip to main content

Sesión 9 - Manejo de interrupciones

Objetivos
  • Comprender la diferencia entre polling, interrupciones e Hilos
  • Aprender a desarrollar aplicaciones que involucren el uso de interrupciones

Introducción

En construcción...

Para empezar retomemos el mapa de pines de la plataforma ESP32:

pines_dev_kit_v4

Super loop

En los programas realizados hasta el momento se ha seguido un patron de diseño conocido como Super loop (tambien conocido como mega loop, main loop o infinite loop). En este patron, la función principal (main) el cual esta compuesto de dos partes principales:

  1. Sección de inicializacion: Esta parte del codigo realizada al principio es la encargada de realizar las tareas de inicialización del sistema (configuración de modulos, inicialización de variables globales, incialización de puertos, etc).
  2. Ciclo infinito: En esta parte se implementa la logica del sistema como tal, ejecutando de manera repetiva las siguientes tres tareas de acuerto a los requerimientos del sistema:
    • Lectura de entradas.
    • Procesamiento de entradas o datos.
    • Control de salidas.

El siguiente fragmento de código muestra el esquema tipico para este patrón:

void main (void)
{
// various initializations

for(;;) // "super loop" or "main loop"
{
// do stuff
}
}
tip

Para profundizar mas sobre el concepto de super loop puede consultar las siguientes paginas:

  • How To Write Super Loops In Firmware [link]
  • Basic concepts [link] (Parte de la documentación de uOS++)
  • What is a Real-Time Operating System (RTOS)? [link]

Como habrá visto a lo largo del curso se ha usado este patron para programar el Arduino y la ESP32. El siguiente es un ejemplo tipico en el cual se sigue este patron para poner a parpadear un led.

led_blink

El código del microcontrolador, se muestra a continuación:

#define LED 19
int led_status;

void setup() {
led_status = HIGH;
pinMode(LED, OUTPUT);
}

void loop(){
digitalWrite(LED, led_status);
delay(500);
led_status = !led_status;
}

Simulación En el siguiente [link] se puede simular el código anterior

Si se observa el ejemplo anterior, notará que no se estan haciendo uso de entradas externas de modo que ¿Que es lo que se suele hacer para que una aplicación interactue con entradas externas?

Para responder a la pregunta anterior, haremos uso del concepto de Polling el cual sera tratado a continuación.

Polling

Cuando un sistema usa entradas, es necesario evaluar su estado para que el programa responda de acuerto a los eventos que ocurren cuando estas cambian. El procedimiento de leer continuamente el valor de una entrada y consultar (sondear) si esta ha cambiado se conoce como Polling. La siguiente figura (tomada del siguiente link) ilustra el concepto:

polling

El polling (consulta) puede ser realizado a toda alta velocidad dentro del loop (lo cual hace que el loop ocupe todos los frecursos del procesador) o tambien puede ser realizado a intervalos menos frecuentes y regulares. Para ilustrar esto, observemos el siguiente sistema en el cual se prende un led mientras se tiene un pulsador presionado.

button_polling

El código que se ejecuta en el microcontrolador se muestra a continuación:

const int buttonPin = 2;
const int ledPin = 22;

int buttonState = 0;

void setup() {
// put your setup code here, to run once:
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
}

void loop() {
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
digitalWrite(ledPin, HIGH);
}
else {
digitalWrite(ledPin, LOW);
}
//delay(10); // this speeds up the simulation
}

Simulación El código anteriormente mostrado se puede simular en el siguiente [link]

En el ejemplo anterior, no hay ninguna tarea critica ya que la respuesta al evento de presionar el botón no tiene que ser inmediata; sin embargo, si se tuviera una situación en la cual se estuviera controlando un motor desde el microcontrolador y la función del botón consistiera en realizar una parada de emergencia, usar polling sería ineficiente y hasta peligroso ya que debido al caracter secuencial del esquema empleado, la respuesta al evento de presionar el botón no seria inmediata.

A continuación, encontramos las ventajas y desventajas cuando se usa polling:

VentajasDesventajas
  • Facil de entender
  • No hay problemas de concurrencia (thread safety)
  • A veces, hay problemas de complejidad cuando se utiliza el súper bucle implementa gran cantidad de código.
  • No es energeticamente eficiente
  • La respuesta a eventos criticos puede ser demorada, lo cual puede ser delicado sobre todo en aplicaciones de tiempo real
  • Para solucionar la limitación al responder a eventos criticos que se tienen con el polling, se hacen uso de las interrupciones tal y como se muestra en la siguiente figura (tomada del siguiente link)

    super_loop_irq

    Cuando se emplean interrupciones, si se produce un evento externo el flujo de ejecución del super loop se interrumpe inmediatamente para atender la interrupción, ejecutando el conjunto de instrucciones asociadas a esta de tal modo que una vez se ejecutan estas, el programa reanuda su ejecución el el punto del super loop donde fue interrumpida. La siguiente figura ilustra esto.

    super_loop_irq

    En la siguiente sección vamos a profundizar mas en el uso de interrupciones.

    Referencias