Skip to main content

Дребезг кнопки и антидребезг

Нажал кнопку один раз — а робот сделал это три раза? Знакомо? 😅

Это не баг в коде и не сломанная кнопка. Это дребезг контактов.

🎓 В курсе 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 мс

Как проверить что всё работает

  1. Без антидребезга: нажми кнопку 10 раз, посчитай сколько раз сработало
  2. С антидребезгом: должно быть ровно 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

Связь с другими темами

Мини‑задания

  1. Почему одно нажатие может стать тремя?

  2. Какая минимальная задержка антидребезга обычно работает?

  3. Зачем нужна подтяжка на входе кнопки?

  4. Посчитай τ для R=47 кОм и C=100 нФ.

  5. Какой способ антидребезга самый простой?

Details
  1. Контакты кнопки «подпрыгивают» — микроконтроллер видит несколько переключений за миллисекунды

  2. 10–20 мс (обычно хватает 20 мс с запасом)

  3. Без подтяжки вход «висит в воздухе» и может показывать случайные 0/1 от помех

  4. $\tau = 47000 \times 0.0000001 = 4.7$ мс

  5. Задержка после нажатия: увидел → подождал 20 мс → проверил ещё раз