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!
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!).
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
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
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.
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!
Deja una respuesta

Estos temas te pueden interesar