Дребезг кнопки и антидребезг
Нажал кнопку один раз — а робот сделал это три раза? Знакомо? 😅
Это не баг в коде и не сломанная кнопка. Это дребезг контактов.
🎓 В курсе nand2cpuТриггеры помогают «запомнить» состояние: Урок 19: SR-защёлка
Что происходит внутри кнопки
Когда нажимаешь кнопку, контакты не соединяются сразу намертво. Они подпрыгивают как мячик — это механика!
Ты думаешь: На самом деле:
нажал нажал
│ │
▼ ▼
─────┐ ────┐ ┌┐┌┐
│ └─┘└┘└───────
└──────── ^^^^
дребезг
(1-20 мс)
За эти миллисекунды контакт может «замкнуться-разомкнуться» 5-10 раз!
Почему микроконтроллер это видит
Микроконтроллер проверяет кнопку очень быстро — миллионы раз в секунду. Он успевает заметить каждый «прыжок» контакта:
Человек видит: [====нажато====]
Arduino видит: [0][1][0][1][1][0][1][1][1][1][1]...
↑ ↑ ↑ ↑
"О! Нажали! И ещё раз! И ещё!"
Три способа победить дребезг
Способ 1: Просто подождать (самый простой)
После того как заметили нажатие — ждём 20 мс и проверяем снова:
Увидел изменение → Подожди 20 мс → Проверь ещё раз
│
Если то же самое → ОК, это настоящее нажатие!
Псевдокод:
если кнопка_нажата:
подожди(20) # пропускаем дребезг
если кнопка_нажата: # всё ещё нажата?
сделай_действие()
✅ Плюс: очень просто
❌ Минус: программа «замирает» на 20 мс
Способ 2: Запоминать время (для продвинутых)
Не останавливаем программу, а запоминаем когда было изменение:
последнее_изменение = 0
стабильное_состояние = НЕ_НАЖАТА
каждый цикл:
если сырой_вход != предыдущий_сырой:
последнее_изменение = сейчас()
предыдущий_сырой = сырой_вход
если (сейчас() - последнее_изменение) > 20мс:
если сырой_вход != стабильное_состояние:
стабильное_состояние = сырой_вход
# Вот тут настоящее событие!
✅ Плюс: программа не тормозит
❌ Минус: чуть сложнее
Способ 3: RC-фильтр (железом)
Конденсатор «сглаживает» быстрые скачки:
┌─────────────────┐
Кнопка ─┤ │
│ ┌───┐ │
VCC ────┼───┤10k├───┬─────┼──► К пину МК
│ └───┘ │ │
│ ──┴── │
│ ──┬── 100нФ
│ │ │
GND ────┼───────────┴─────┘
└─────────────────┘
Постоянная времени: $\tau = R \times C = 10000 \times 0.0000001 = 1$ мс
Это «размазывает» дребезг, делая его менее заметным.
Не забудь про подтяжку!
Главная ошибка новичков: вход без подтяжки «висит в воздухе» и ловит помехи.
НЕПРАВИЛЬНО: ПРАВИЛЬНО:
Кнопка VCC
│ │
│ [10k] ← подтяжка
│ │
МК ────┴── ??? МК ┼───── = 1 (по умолчанию)
│
Вход «плавает» Кнопка
0? 1? помехи? │
GND ─── при нажатии = 0
Многие МК имеют встроенную подтяжку — включи её в коде!
Типичные значения
| Параметр | Значение | Почему |
|---|---|---|
| Время дребезга | 1–20 мс | Зависит от кнопки |
| Задержка антидребезга | 20–50 мс | С запасом |
| Резистор подтяжки | 10 кОм | Стандарт |
| Конденсатор фильтра | 100 нФ | Даёт τ ≈ 1 мс |
Как проверить что всё работает
- Без антидребезга: нажми кнопку 10 раз, посчитай сколько раз сработало
- С антидребезгом: должно быть ровно 10 срабатываний
Тест:
Нажатий: 10
Без фильтра: 23 срабатывания 😱
С фильтром: 10 срабатываний ✅
Типичные ошибки
| Ошибка | Симптом | Решение |
|---|---|---|
| Нет подтяжки | Случайные срабатывания | Добавь pullup |
| Задержка 1-2 мс | Всё ещё дребезжит | Увеличь до 20 мс |
| Задержка 500 мс | Кнопка «тормозит» | Уменьши до 20-50 мс |
| Фильтр только в железе | Иногда пробивает | Добавь и в софте |
Антидребезг на SR-защёлке
В курсе nand2cpu мы строим SR-защёлку — она тоже убирает дребезг!
┌─────┐
Кнопка A ─┤ NAND├─┬─► Q (стабильный выход)
┌────┤ │ │
│ └─────┘ │
│ │
│ ┌─────┐ │
└────┤ NAND├─┘
Кнопка B ─┤ │
└─────┘
Это аппаратный способ «запомнить» первое нажатие и игнорировать дребезг.
Подробнее: Урок 19: SR-защёлка
Что использовать?
| Ситуация | Рекомендация |
|---|---|
| Школьный проект | Программный антидребезг 20 мс |
| Длинные провода | RC-фильтр + программный |
| Много помех (моторы) | RC-фильтр обязательно |
| Супернадёжность | SR-защёлка на 74HC00 |
Связь с другими темами
- Логические уровни — что такое 0 и 1: logic_levels
- SR-защёлка — аппаратный антидребезг: nand2cpu урок 19
- Резисторы — как работает подтяжка: резисторы
Мини‑задания
Почему одно нажатие может стать тремя?
Какая минимальная задержка антидребезга обычно работает?
Зачем нужна подтяжка на входе кнопки?
Посчитай τ для R=47 кОм и C=100 нФ.
Какой способ антидребезга самый простой?
Details
Контакты кнопки «подпрыгивают» — микроконтроллер видит несколько переключений за миллисекунды
10–20 мс (обычно хватает 20 мс с запасом)
Без подтяжки вход «висит в воздухе» и может показывать случайные 0/1 от помех
$\tau = 47000 \times 0.0000001 = 4.7$ мс
Задержка после нажатия: увидел → подождал 20 мс → проверил ещё раз
