Antirrebote de Pulsadores (Debounce)
Al trabajar con componentes mecánicos como pulsadores, interruptores o finales de carrera, nos encontramos con un fenómeno físico inevitable denominado rebote (bouncing).
Cuando presionas o sueltas un botón, las láminas metálicas internas chocan y rebotan entre sí durante un intervalo de entre 5 y 50 milisegundos antes de estabilizarse. Aunque para el ser humano es un único clic instantáneo, para un microcontrolador que ejecuta 16 millones de instrucciones por segundo (16 MHz) se interpretan decenas de transiciones rápidas HIGH y LOW, provocando múltiples pulsaciones falsas.
1. El Problema del Rebote Mecánico #
1Presión física del botón 2 │ 3 ▼ 4 ┌───────┐ 5 │ │ Rebotes mecánicos (5-50 ms) Estado estable final 6───┘ └───/\/\/\/\/\/\/\/\───────────────► ──────────────────── (GND o 5V) 7 ▲ 8 │ Arduino lee múltiples transiciones falsas
2. Solución por Hardware: Filtro RC #
Una solución física consiste en añadir un condensador cerámico de en paralelo con el pulsador:
- El condensador absorbe los picos de voltaje transitorios y suaviza la caída/subida de la señal.
- Se recomienda complementar con un inversor Schmitt-Trigger (como el 74HC14) para entregar una señal cuadrada limpia al pin digital.
3. Solución por Software: Algoritmo No Bloqueante con millis() #
La técnica más habitual y económica es el filtrado por software: no aceptar un cambio de estado hasta que la señal se mantenga constante durante un tiempo superior al tiempo de rebote (típicamente ).
1const int pinBoton = 2; 2const int pinLED = 13; 3 4int estadoLED = LOW; 5int estadoBotonActual; 6int ultimoEstadoBoton = HIGH; // en reposo con INPUT_PULLUP es HIGH 7 8unsigned long ultimoTiempoRebote = 0; 9const unsigned long retardoDebounce = 50; // 50 milisegundos de filtro 10 11void setup() { 12 pinMode(pinBoton, INPUT_PULLUP); 13 pinMode(pinLED, OUTPUT); 14 digitalWrite(pinLED, estadoLED); 15} 16 17void loop() { 18 int lectura = digitalRead(pinBoton); 19 20 // Si la lectura cambió (por ruido o por pulsación real), reiniciar cronómetro 21 if (lectura != ultimoEstadoBoton) { 22 ultimoTiempoRebote = millis(); 23 } 24 25 // Si ha pasado más tiempo que el retardo del debounce, la lectura es estable 26 if ((millis() - ultimoTiempoRebote) > retardoDebounce) { 27 // Si el estado estable ha cambiado realmente 28 if (lectura != estadoBotonActual) { 29 estadoBotonActual = lectura; 30 31 // Al pulsar (flanco de bajada a LOW con INPUT_PULLUP) 32 if (estadoBotonActual == LOW) { 33 estadoLED = !estadoLED; 34 digitalWrite(pinLED, estadoLED); 35 } 36 } 37 } 38 39 ultimoEstadoBoton = lectura; 40}
Resumen del tema
Conceptos clave #
- Rebote Mecánico: oscilaciones transitorias de voltaje (5-50 ms) causadas por el contacto físico de las placas metálicas al presionar o soltar un botón.
- Filtro RC por Hardware: circuito con resistencia y condensador de que aplana las oscilaciones transitorias.
- Debounce por Software: técnica con
millis()que valida el cambio de estado únicamente si la señal se mantiene estable durante un intervalo mínimo (ej. 50 ms). - Ventaja No Bloqueante: a diferencia de usar
delay(50), el debounce conmillis()permite a Arduino seguir atendiendo otras tareas y sensores en paralelo.
Qué debes recordar #
Nunca leas botones mecánicos directamente sin filtrado; utiliza siempre un algoritmo de debounce con millis() o un circuito RC para evitar lecturas múltiples por cada pulsación.