Согласно вездесущей википедии:
Дребезг контактов — явление, происходящее в электромеханических коммутационных устройствах и аппаратах (кнопках, реле, герконах, переключателях, контакторах, магнитных пускателях и др.), длящееся некоторое время после замыкания электрических контактов. После замыкания происходят многократные неконтролируемые замыкания и размыкания контактов за счет упругости материалов и деталей контактной системы — некоторое время контакты отскакивают друг от друга при соударениях, размыкая и замыкая электрическую цепь.
Чтобы лучше понять, что означает весь этот набор слов, возьмем какой нибудь микроконтроллер (Arduino, ESP) и попробуем решить простенькую задачку. Соберем устройство которое будет подсчитывать сколько раз мы нажали на кнопку и выводить данное значение в монитор порта. У меня под рукой есть плата ESP32, ну соответственно потребуется кнопка. (на Arduino данный код также будет работать). Внешний подтягивающий резистор мы использовать не будем, подключим внутренний с помощью команды INPUT_PULLUP в функции pinMode(). Соответственно при чтении состояний кнопки не забываем добавлять оператор отрицания "!" так как HIGH будет означать что кнопка не нажата, а LOW - нажата. Во всем остальном все будет работать точно также как если бы мы использовали внешнюю подтяжку.
Перед тем как копипасить чужой код из интернет, начинать разрабатывать свою программу необходимо составить алгоритм её работы. Для того, чтобы считалось именно одно нажатие, заведем дополнительную логическую переменную buttonPressed, (кнопка нажата?) чтобы счетчик не считал все то время, пока мы удерживаем кнопку.
Пишем код и прошиваем им плату:
Открываем монитор порта и один раз клацаем по кнопке
Вместо увеличения счетчика на единицу, программа посчитала целых 8 нажатий. Причем результат за одно нажатие абсолютно не предсказуем
Причина была озвучена в начале этой статьи, микроконтроллер опрашивает кнопку много много много раз в секунду, и поэтому в момент замыкания(размыкания) механических контактов мы видим, что микроконтроллер посчитал заодно и весь дребезг. Простая на первый взгляд задача оказалась не такой уж и простой.
В таком виде в практических целях программу разумеется использовать не получится. Для устранения данной проблемы можно использовать и аппаратное решение, но в этой статье речь пойдет о программной реализации.
Самый простой способ - обнаружив изменение состояние входа к которому подключена кнопка, спросить еще раз: "а что это было?" дребезг или действительно на кнопку нажали. Задержка должна быть такой, чтобы контакты кнопки полностью успокоились. Перерисуем наш алгоритм.
Код:
Теперь все работает как нужно: при одном нажатии счетчик увеличивается на одну единицу.
Данный код легко превратить в кнопочный переключатель:
один раз нажали - нагрузка включилась
второй раз нажали - нагрузка выключилась.
Разберем на примере переключения встроенного светодиода.
Нажимая на кнопку можно включать и выключать встроенный в плату светодиод.
Плюсы данного решения: простота реализации, отсутствие необходимости применять дополнительные электронные компоненты.
Минусы, дополнительная нагрузка на микроконтроллер, дополнительный код, невозможность использовать данный механизм при работе с прерываниями.
Является или нет критичной задержка в 10....20 мс зависит от решаемой Вами задачи. Естественно можно применить более сложное программное решение на основе классического алгоритма (Blink Without Delay) или аппаратный таймер микроконтроллера, чтобы избавиться от ненужного в программе простоя (команды (delay()). Еще один из способов избежать "тормозов" в программе разобран в моей второй статье.
Также вы можете ознакомиться с полным списком статей на моем канале.
Всем удачи!