01 · Punto de partida
Presionás 1, cuenta 20
El contacto mecánico rebota 5–50 ms generando decenas de flancos: un contador ve 20 pulsaciones donde tu dedo hizo 1. Tres remedios: pull bien puesto, filtro RC + Schmitt, o debounce por software.
- ¿Pull-up o pull-down, y de qué valor?
- ¿Cuánto dura un rebote?
- ¿Cómo se filtra en hardware?
- ¿Y en software?
02 · Pull
Reposo definido
Botón entre entrada y masa, pull-up 10k a Vcc: suelto lee 1 (0,5 mA por el pull), presionado lee 0. Nunca botón directo a Vcc (al presionar, corto Vcc-masa por el pull… o peor, sin pull: corto franco).
03 · Rebote
20 flancos por 1 dedo
| Víctima | Síntoma | Remedio |
|---|---|---|
| Contador | Suma 20 por presión | Debounce sí o sí |
| Interrupción | 20 ISR por presión | Debounce por tiempo |
| Reloj manual | Avanza varios pasos | RC + Schmitt (74HC14) |
| LED simple | Nada visible | Ninguno (el ojo promedia) |
Regla: si el circuito cuenta flancos, el rebote lo rompe. Si solo muestra niveles, ni se nota.
04 · Filtros
RC + Schmitt o latch
- RC + 74HC14
- R = 10k, C = 1 µF → τ = 10 ms: el capacitor no sigue los rebotes y el Schmitt (histéresis) entrega flanco único. Clásico universal.
- Latch SR
- Conmutador + 2 NAND/NOR cruzadas: el primer contacto traba, los rebotes no destaban. Ideal con switch SPDT.
- Software
- Al detectar cambio, ignorar 20–50 ms: dos líneas cuestan cero hardware. Para teclados de micro, el favorito.
- Pull interno
- Muchos micros traen pull-up programable (20–50k): ahorra la R externa, no el debounce.
05 · Rebote en código
Contar bien
Tren de rebotes simulado: contador crudo vs con debounce.
Python en tu navegador. Achicá el debounce y mirá colarse los rebotes.
import random
random.seed(11)
rebotes = [0] + [random.choice([0, 1]) for _ in range(14)] + [1] * 6
print("tren:", "".join(map(str, rebotes)))
flancos = sum(1 for a, b in zip(rebotes, rebotes[1:]) if a != b)
print(f"flancos={flancos} (el dedo hizo 1)")
Un tren típico da 7 flancos por una presión. ¿Cuántos da tu seed si lo cambiás?
Debounce por tiempo
def debounce(tren, ms_por_muestra=1, ventana_ms=20):
cuenta, ultimo, i = 0, 0, 0
while i < len(tren):
if tren[i] != ultimo:
cuenta += tren[i] == 1
ultimo = tren[i]
i += ventana_ms // ms_por_muestra
i += 1
print(f"con ventana {ventana_ms}ms: cuenta={cuenta}")
return cuenta
debounce(rebotes)
debounce(rebotes, ventana_ms=2)
06 · Analogía programador
Usuario impaciente
- 1Rebote = doble-click.
El usuario clickea 5 veces el botón que tarda: se atiende el primero, se ignoran los siguientes 500 ms.
- 2Pull = default.
Valor cuando nadie escribe: como un parámetro con default ante input ausente.
- 3Schmitt = histéresis.
La misma del curso 4 (Tema 20): dos umbrales ignoran el tembleque del borde.
07 · Exploración
Laboratorio: presionar sin mentir
Presioná el botón virtual: genera un tren de rebotes realista. Compará cuenta cruda vs con debounce de 20 ms.
Presionómetro
Sin presiones aún
Presioná para generar rebotes.
Preguntas para explorar
- Presioná 3 veces en crudo. ¿Cuenta? Cambiá a debounce y presioná 3 más. ¿Cuenta?
- ¿Por qué el debounce da exactamente 1 por presión aunque el tren varíe?
- ¿Qué pasaría con ventana de 2 ms? (Ver código.)
Ver respuestas sugeridas
- Crudo: ~15–30 total (~5–10 por presión). Debounce: +3 exactos. Total = crudo + 3.
- Porque la ventana de 20 ms cubre todo el tren (≤ 15 ms): solo el primer flanco cuenta.
- Se cuelan rebotes tardíos: ventana menor que el tren. Ventana ≥ tren, siempre.
08 · Comprensión
Confusiones frecuentes
«Botón a Vcc, total es lo mismo»
No: a Vcc necesita pull-down, y sin pull hay corto al presionar. Convención: a masa + pull-up.
«Pull de 1 MΩ, total gasta menos»
Gasta menos pero es antena: 1 MΩ + ruido = flancos fantasma. 10k es el punto justo.
«Software arregla todo»
Para relojes manuales y contadores discretos no hay software: RC + Schmitt o latch. El micro no siempre está.
«Mi botón no rebota»
Todos rebotan (hasta los caros): si tu contador anda, es que algo ya filtra. Verificar con osciloscopio asusta.
09 · Práctica guiada
Ejercicios de botones
Ejercicio 1: RC correcto
Rebote medido de 15 ms. Elegí R y C con τ ≈ 15 ms y verificá el cruce de 1,5/3,5 V. ¿10k + 1,5 µF?
Ver solución razonada
τ = 15 ms ✓ (10k×1,5 µF): el capacitor promedia el tren y el HC14 entrega un flanco. E12: 1,5 µF existe ✓.
Ejercicio 2: latch SR
Conmutador SPDT + 2 NAND cruzadas. Dibujá set/reset y explicá por qué los rebotes no afectan.
Ver solución
El primer contacto traba Q; rebotes del mismo lado no cambian nada; solo el lado opuesto conmuta. Debounce perfecto sin RC.
Ejercicio 3: medir tu botón
Osciloscopio en el botón con pull-up: presioná 5 veces. ¿Duración del tren? ¿Flancos por presión?
Ver solución
Típico 5–20 ms y 5–15 flancos: cada botón tiene su firma. Diseñar la ventana con la medida, no con el datasheet.
10 · Síntesis
Ideas para recordar
- Botón a masa + pull-up 10k (0,5 mA).
- Rebote 5–50 ms: si cuenta flancos, filtra.
- RC (10k + 1 µF) + HC14, latch SR, o software 20–50 ms.
- Ventana ≥ tren medido.
- Todos los botones rebotan: el tuyo también.
Entradas domesticadas. Ahora los chips que las leen: en el próximo tema, 74HCxx en mesa.