Configuración y manejo de interrupciones GPIO en ESP32 con Arduino IDE

¡Hola equipo! Bienvenidos a Ingtelecto Pro. Hoy vamos a subir de nivel en programación. Vamos a dejar atrás la técnica de novatos llamada Polling (preguntar constantemente) y pasaremos a las Interrupciones.

Imagina que quieres detectar cuando alguien presiona un botón de emergencia. Si usas el método clásico digitalRead() dentro del loop(), y tu código está ocupado controlando una pantalla o enviando datos WiFi... ¡el ESP32 podría perderse la pulsación del botón! Eso es inaceptable en sistemas críticos.

Hoy aprenderemos a configurar el ESP32 para que detenga todo lo que está haciendo, atienda el botón inmediatamente y luego regrese a su trabajo. Y lo más importante: solucionaremos el famoso problema del "Efecto Rebote" que hace que una pulsación cuente como diez. ¡Vamos a ello! ⚡🛑

Analogía del Mundo Real: ¿Esperar en la puerta o Timbre?

Polling (Lo que hacías antes): Es como esperar al repartidor de pizza parado en la puerta, abriendo y cerrando cada 5 segundos para ver si llegó. No puedes hacer nada más (ni ver TV, ni dormir) porque estás ocupado comprobando la puerta.

Interrupción (Lo profesional): Te sientas a ver una película relajado. Cuando el repartidor llega, toca el timbre (Interrupción). Tú pausas la película, atiendes la puerta, recoges la pizza, y luego reanudas la película exactamente donde la dejaste. ¡Mucho más eficiente!

[Pega aquí el iframe de YouTube]
Índice de contenido
  1. Materiales Necesarios
  2. Fundamentos Técnicos: La Regla de Oro
  3. Conexiones y Diagramas ⚙️
    1. Tabla de Conexiones
  4. Ejemplo 1: Interrupción Básica (Con Problema de Rebote)
    1. El Problema Invisible: "El Rebote" (Bouncing)
  5. Ejemplo 2: La Solución Profesional (Debounce por Software) ✅
    1. Análisis del Código Anti-Rebote
  6. Modos de Interrupción: El Menú de Opciones
  7. Conclusión

Materiales Necesarios

Lista de Componentes ✅

  • 1 x Placa ESP32 (Cualquier versión).
  • 1 x Botón Pulsador (Push Button) de 4 pines o 2 pines.
  • 1 x Protoboard y cables.
  • (Opcional) 1 x Resistencia de 10k$\Omega$ (No la usaremos hoy porque activaremos la interna, ¡magia!).
[SUGERENCIA FOTO REAL: Un botón simple conectado en la protoboard al ESP32]

Fundamentos Técnicos: La Regla de Oro

Las interrupciones son poderosas, pero peligrosas. Si no sigues estas reglas, el ESP32 se reiniciará (Crash).

IRAM_ATTR

Es una "etiqueta" que le dice al compilador: "Guarda esta función en la memoria RAM (rápida), no en la memoria Flash (lenta)".
Cuando ocurre una interrupción, el procesador debe saltar a la función inmediatamente. Si la función está en la Flash, tarda mucho en cargar y el sistema falla.
Regla: Toda función de interrupción debe llevar IRAM_ATTR en su nombre.

Variables Volatile

Normalmente, el compilador C++ optimiza el código y "olvida" releer variables que cree que no han cambiado. Como una interrupción ocurre fuera del flujo normal, el compilador puede no darse cuenta de que una variable cambió.
Regla: Cualquier variable global que modifiques dentro de una interrupción debe declararse como volatile.

Conexiones y Diagramas ⚙️

Vamos a usar el GPIO 18. No necesitamos resistencia externa porque activaremos la resistencia Pull-Up Interna del ESP32 mediante software.

Tabla de Conexiones

Botón Pulsador ESP32
Pata 1 GPIO 18
Pata 2 GND

Al presionar el botón, el pin 18 se conectará a GND (LOW). Al soltarlo, la resistencia interna lo subirá a 3.3V (HIGH).

[SUGERENCIA DIAGRAMA: Diagrama esquemático simple Botón a Pin 18 y GND]

Ejemplo 1: Interrupción Básica (Con Problema de Rebote)

Este código detecta cuándo se presiona el botón. Usaremos el modo FALLING (cuando el voltaje cae de 3.3V a 0V, es decir, al presionar).

// TUTORIAL INGTELECTO PRO - INTERRUPCIONES

// Ejemplo Básico (Sin filtro de rebote)
const int buttonPin = 18;
// Usamos 'volatile' porque esta variable se modifica dentro de la ISR

volatile int contador = 0;

volatile bool botonPresionado = false;
// --- RUTINA DE SERVICIO DE INTERRUPCIÓN (ISR) ---

// Esta función se ejecuta cuando se presiona el botón.

// Debe ser RAPIDÍSIMA. Nada de Serial.print ni delays aquí.

void IRAM_ATTR isr() {

  contador++;

  botonPresionado = true;

}
void setup() {

  Serial.begin(115200);
  // Configuramos el pin con resistencia interna (Pull-Up)

  // Pin en ALTO (3.3V) por defecto.

  pinMode(buttonPin, INPUT_PULLUP);
  // Adjuntamos la interrupción

  // Pin, Función a llamar, Modo de disparo (FALLING = al presionar)

  attachInterrupt(buttonPin, isr, FALLING);

}
void loop() {

  // Verificamos si la bandera se levantó

  if (botonPresionado) {

    Serial.printf("Botón presionado %u veces\n", contador);
    // Bajamos la bandera para esperar el siguiente evento

    botonPresionado = false;

  }

}

El Problema Invisible: "El Rebote" (Bouncing)

Si subes el código anterior y presionas el botón una sola vez, verás que el monitor serie dice:
Botón presionado 1 vecesBotón presionado 2 vecesBotón presionado 3 veces...¡todo en una fracción de segundo!

¿Por qué?
Porque un botón es una lámina de metal chocando con otra. Al juntarse, vibran microscópicamente durante unos milisegundos antes de quedarse quietas. El ESP32 es tan rápido que detecta cada vibración como una pulsación nueva.

Ejemplo 2: La Solución Profesional (Debounce por Software) ✅

Para arreglar esto, no necesitamos condensadores (hardware). Usaremos la lógica: "Si detecto una pulsación, ignora cualquier otra señal durante los siguientes 250 milisegundos".

// TUTORIAL INGTELECTO PRO - INTERRUPCIONES

// Ejemplo Avanzado (Con Debounce / Anti-rebote)
const int buttonPin = 18;
volatile int contador = 0;

volatile bool botonPresionado = false;
// Variables para el control de tiempo (Debounce)

unsigned long tiempoUltimaInterrupcion = 0;

const unsigned long intervaloDebounce = 250; // 250ms de "ceguera"
// --- ISR CON FILTRO ---

void IRAM_ATTR isr() {

  // Tomamos el tiempo actual

  unsigned long tiempoActual = millis();
  // Si ha pasado más tiempo que el intervalo de seguridad...

  if (tiempoActual - tiempoUltimaInterrupcion > intervaloDebounce) {

    contador++;

    botonPresionado = true;
    // Actualizamos el tiempo de la última pulsación válida

    tiempoUltimaInterrupcion = tiempoActual;

  }

}
void setup() {

  Serial.begin(115200);

  pinMode(buttonPin, INPUT_PULLUP);
  // Interrupt en modo FALLING (Al bajar el voltaje)

  attachInterrupt(buttonPin, isr, FALLING);

}
void loop() {

  if (botonPresionado) {

    Serial.printf("¡Click Válido! Total: %u\n", contador);

    botonPresionado = false;

  }

}

Análisis del Código Anti-Rebote

  • millis(): Es el reloj interno del Arduino. Nos dice cuántos milisegundos han pasado desde que se encendió.
  • La Lógica: Restamos el tiempo actual menos el tiempo de la última pulsación. Si la diferencia es pequeña (ej. 10ms), significa que es ruido (rebote) y lo ignoramos. Si es grande (>250ms), es un dedo humano presionando de nuevo.

Modos de Interrupción: El Menú de Opciones

En la función attachInterrupt, el tercer parámetro decide cuándo se dispara la alarma:

  • LOW: Se dispara continuamente mientras el botón esté presionado.
  • HIGH: Se dispara continuamente mientras el botón esté suelto (si usas pull-down).
  • CHANGE: Se dispara dos veces: una al presionar y otra al soltar.
  • FALLING (Recomendado para Pull-Up): Se dispara justo en el instante que presionas.
  • RISING: Se dispara justo en el instante que sueltas el botón.

Conclusión

¡Programación Asíncrona Desbloqueada! 🔓

Acabas de aprender a escribir código que no bloquea el procesador. Ahora tu ESP32 puede estar controlando un robot y, al mismo tiempo, "escuchando" sensores de choque o botones de paro de emergencia sin perder ni un milisegundo.

Tu Próximo Reto:
Usa una interrupción para "despertar" al ESP32 del modo Deep Sleep. Imagina un control remoto que no gasta batería hasta que presionas un botón. ¡Ese es el poder real de las interrupciones!

Carlos Julián

Carlos Julián es el fundador de Ingtelecto, es Ingeniero Mecatrónico, Profesor y Programador, cuenta con una Maestria en Ciencias de la Educación, creador de contenido educativo en redes sociales. Lee más sobre mi trayectoria aquí.

Estos temas te pueden interesar

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Tu puntuación: Útil

Subir