В данном уроке рассматривается проблема дребезга контактов, возникающая при использовании механических кнопок и переключателей с микроконтроллером ESP32. Описаны причины возникновения дребезга, его влияние на работу микроконтроллера и представлены программные методы его устранения. Статья ориентирована на техническую аудиторию и содержит примеры кода на языке C/C++ для среды разработки Arduino IDE. Дребезг контактов это паразатный эффект, усложняющий разработку и отладку проекта.
При нажатии или отпускании механической кнопки (или переключении тумблера) ее состояние не изменяется мгновенно с LOW на HIGH (или наоборот). Вместо этого, из-за физических свойств материалов и конструкции кнопки, происходит кратковременное многократное замыкание и размыкание контакта. Это явление называется "дребезгом контактов" (chattering). В результате микроконтроллер (например, ESP32) может воспринять одно физическое нажатие как несколько последовательных нажатий, что приводит к некорректной работе устройства.
В данном примере используется простая схема подключения кнопки к ESP32. Один контакт кнопки подключается к цифровому выводу ESP32 (в примерах используется вывод 21), а другой контакт - к общему проводу (GND). Для корректной работы необходимо использовать подтягивающий резистор (pull-up). Он может быть как внешним (подключенным между выводом кнопки и питанием VCC), так и внутренним, активируемым программно (см. примеры кода).
Пример 1: Чтение состояния кнопки без подавления дребезга.
/* * ESP32 Arduino IDE. Подавление дребезга контактов кнопки. * https://arduino-tex.ru/news/204/esp32-podavlenie-drebezga-kontaktov-knopki.html */ #define BUTTON_PIN 21 // GIOP21 пин подключен к кнопке // Переменные, которые будут изменяться: int lastState = LOW; // предыдущее состояние от пина входа int currentState; // текущее состояние считываемое с пина void setup() { // инициализация последовательного соединения на скорости 115200 бит в секунду: Serial.begin(115200); // инициализировать пин кнопки как вход с подтяжкой, // пин входа с подтяжкой будет иметь состояние HIGH когда переключатель открыт и LOW когда переключатель закрыт. pinMode(BUTTON_PIN, INPUT_PULLUP); } void loop() { // считать состояние переключателя/кнопки: currentState = digitalRead(BUTTON_PIN); if (lastState == HIGH && currentState == LOW) Serial.println("Кнопка нажата"); else if (lastState == LOW && currentState == HIGH) Serial.println("Кнопка отпущена"); // сохранить последнее состояние lastState = currentState; }
В этом примере при каждом изменении состояния кнопки (нажатие или отпускание) в последовательный порт выводится соответствующее сообщение. Однако, из-за дребезга контактов, при одном нажатии можно увидеть несколько сообщений "Кнопка нажата" и "Кнопка отпущена".
После загрузки откройте Монитор порта на скорости 115200.
Пример 2: Чтение состояния кнопки с подавлением дребезга (программный метод).
/* * ESP32 Arduino IDE. Подавление дребезга контактов кнопки. * https://arduino-tex.ru/news/204/esp32-podavlenie-drebezga-kontaktov-knopki.html */ #define BUTTON_PIN 21 // Пин GIOP21, подключенный к кнопке #define DEBOUNCE_TIME 50 // Время подавления дребезга в миллисекундах, увеличьте это время, если дребезг остается // Переменные, которые будут изменяться: int lastSteadyState = LOW; // Предыдущее устойчивое состояние пина кнопки int lastFlickerableState = LOW; // Предыдущее состояние пина кнопки, которое может быть нестабильным (дребезг) int currentState; // Текущее состояние пина кнопки // Следующие переменные имеют тип unsigned long, потому что время, измеряемое в // миллисекундах, быстро станет большим числом, которое не может быть сохранено в int. unsigned long lastDebounceTime = 0; // Время последнего изменения состояния кнопки void setup() { // Инициализация последовательной связи на скорости 115200 бит в секунду: Serial.begin(115200); // Инициализация пина кнопки как входа с подтяжкой (pull-up): // Вход с подтяжкой будет иметь состояние HIGH, когда переключатель разомкнут, и LOW, когда переключатель замкнут. pinMode(BUTTON_PIN, INPUT_PULLUP); } void loop() { // Чтение состояния переключателя/кнопки: currentState = digitalRead(BUTTON_PIN); // Проверка, была ли только что нажата кнопка // (т.е. вход изменился с LOW на HIGH), и прошло ли достаточно времени // с момента последнего нажатия, чтобы игнорировать любой шум: // Если состояние переключателя/кнопки изменилось из-за шума или нажатия: if (currentState != lastFlickerableState) { // Сброс таймера подавления дребезга lastDebounceTime = millis(); // Сохранение последнего нестабильного состояния lastFlickerableState = currentState; } if ((millis() - lastDebounceTime) > DEBOUNCE_TIME) { // Если с момента последнего изменения прошло больше времени, чем DEBOUNCE_TIME, // то текущее значение считавается устойчивым. // Если состояние кнопки изменилось: if (lastSteadyState == HIGH && currentState == LOW) Serial.println("Кнопка нажата"); else if (lastSteadyState == LOW && currentState == HIGH) Serial.println("Кнопка отпущена"); // Сохранить последнее устойчивое состояние lastSteadyState = currentState; } }
В этом примере используется метод "таймера". При обнаружении изменения состояния кнопки запускается таймер ( lastDebounceTime = millis();
). Если в течение заданного времени (DEBOUNCE_TIME
, обычно 50-100 мс) состояние кнопки остается стабильным, то считается, что дребезг закончился, и новое состояние кнопки регистрируется.
После загрузки откройт Монитор порта на скорости 115200.
Для упрощения работы с кнопками, особенно при использовании нескольких кнопок, можно использовать библиотеку EZButton
. Она предоставляет удобные функции для обработки нажатий и отпусканий кнопок с учетом дребезга.
/* * ESP32 Arduino IDE. Подавление дребезга контактов кнопки. * https://arduino-tex.ru/news/204/esp32-podavlenie-drebezga-kontaktov-knopki.html */ #include <EZButton.h> // Подключение библиотеки EZButton для упрощения работы с кнопкой #define DEBOUNCE_TIME 50 // Время подавления дребезга в миллисекундах, увеличьте это время, если дребезг все еще присутствует #define BTN_1_PIN 21 //пину GPIO21 #define BTN_1 0 void ReadButtons(bool *states, int num) { //Read all button states however you want states[BTN_1] = !digitalRead(BTN_1_PIN); } //Считывайте состояния кнопок с помощью функции 'ReadButtons' //Порог удержания: 500 мс //Интервал удержания: 300 мс //Время ожидания: 50 мс DEBOUNCE_TIME EZButton _ezb(1, ReadButtons, 1000, 200, DEBOUNCE_TIME); void setup() { Serial.begin(115200); // Инициализация последовательного соединения на скорости 115200 бит/с pinMode(BTN_1_PIN, INPUT_PULLUP); //subscribe to needed events _ezb.Subscribe(BTN_1, Btn1Pressed, PRESSED); _ezb.Subscribe(BTN_1, Btn1Released, RELEASED); } void loop() { _ezb.Loop(); // Необходимо вызывать функцию loop() для обработки состояний кнопки } void Btn1Pressed() { // Проверка, была ли кнопка нажата (переход из отпущенного состояния в нажатое) Serial.println("Кнопка нажата"); // Вывод сообщения в последовательный порт } void Btn1Released() { // Проверка, была ли кнопка отпущена (переход из нажатого состояния в отпущенное) Serial.println("Кнопка отпущена"); // Вывод сообщения в последовательный порт }
После загрузки откройте Монитор порта на скорости 115200.
/* * ESP32 Arduino IDE. Подавление дребезга контактов кнопки. * https://arduino-tex.ru/news/204/esp32-podavlenie-drebezga-kontaktov-knopki.html */ #include <EZButton.h> // Подключение библиотеки ezButton для упрощения работы с кнопкой #define DEBOUNCE_TIME 50 // Время подавления дребезга в миллисекундах, увеличьте это время, если дребезг все еще присутствует #define BTN_1_PIN 21 //пину GPIO21 #define BTN_2_PIN 22 //пину GPIO22 #define BTN_3_PIN 23 //пину GPIO23 #define BTN_1 0 #define BTN_2 1 #define BTN_3 2 void ReadButtons(bool *states, int num) { //Read all button states however you want states[BTN_1] = !digitalRead(BTN_1_PIN); states[BTN_2] = !digitalRead(BTN_2_PIN); states[BTN_3] = !digitalRead(BTN_3_PIN); } //Считывайте состояния кнопок с помощью функции 'ReadButtons' //Порог удержания: 500 мс //Интервал удержания: 300 мс //Время ожидания: 50 мс DEBOUNCE_TIME EZButton _ezb(3, ReadButtons, 1000, 200, DEBOUNCE_TIME); void setup() { Serial.begin(115200); // Инициализация последовательного соединения на скорости 115200 бит/с pinMode(BTN_1_PIN, INPUT_PULLUP); pinMode(BTN_2_PIN, INPUT_PULLUP); pinMode(BTN_3_PIN, INPUT_PULLUP); //subscribe to needed events _ezb.Subscribe(BTN_1, Btn1Pressed, PRESSED); _ezb.Subscribe(BTN_1, Btn1Released, RELEASED); _ezb.Subscribe(BTN_2, Btn2Pressed, PRESSED); _ezb.Subscribe(BTN_2, Btn2Released, RELEASED); _ezb.Subscribe(BTN_3, Btn3Pressed, PRESSED); _ezb.Subscribe(BTN_3, Btn3Released, RELEASED); } void loop() { _ezb.Loop(); // Необходимо вызывать функцию loop() для обработки состояний кнопки } void Btn1Pressed() { // Проверка, была ли кнопка нажата (переход из отпущенного состояния в нажатое) Serial.println("Кнопка 1 нажата"); // Вывод сообщения в последовательный порт } void Btn1Released() { // Проверка, была ли кнопка отпущена (переход из нажатого состояния в отпущенное) Serial.println("Кнопка 1 отпущена"); // Вывод сообщения в последовательный порт } void Btn2Pressed() { // Проверка, была ли кнопка нажата (переход из отпущенного состояния в нажатое) Serial.println("Кнопка 2 нажата"); // Вывод сообщения в последовательный порт } void Btn2Released() { // Проверка, была ли кнопка отпущена (переход из нажатого состояния в отпущенное) Serial.println("Кнопка 2 отпущена"); // Вывод сообщения в последовательный порт } void Btn3Pressed() { // Проверка, была ли кнопка нажата (переход из отпущенного состояния в нажатое) Serial.println("Кнопка 3 нажата"); // Вывод сообщения в последовательный порт } void Btn3Released() { // Проверка, была ли кнопка отпущена (переход из нажатого состояния в отпущенное) Serial.println("Кнопка 3 отпущена"); // Вывод сообщения в последовательный порт }
После загрузки откройте Монитор порта на скорости 115200.
Дополнительные замечания:
DEBOUNCE_TIME
зависит от конкретного типа кнопки и может потребоваться его подстройка для достижения оптимального результата.Дребезг контактов – распространенная проблема при работе с механическими кнопками и переключателями. Программные методы подавления дребезга, описанные в данной статье, позволяют эффективно устранить этот эффект и обеспечить надежную работу устройства на базе микроконтроллера ESP32. Использование библиотеки EZButton
значительно упрощает реализацию подавления дребезга, особенно при работе с несколькими кнопками.
Дополнительная информация к данному уроку:
Понравился урок: Как избежать дребезга контактов на ESP32: полное руководство? Не забудь поделиться с друзьями в соц. сетях.
А также подписаться на наш канал на YouTube, вступить в группу Вконтакте, в Telegram.
Спасибо за внимание!
Технологии начинаются с простого!
Фотографии к статье
Файлы для скачивания
![]() |
Пример 1: Чтение состояния кнопки без подавления дребезга.ino | 3 Kb | 18 | Скачать |
![]() |
Пример 2: Чтение состояния кнопки с подавлением дребезга.ino | 2 Kb | 19 | Скачать |
![]() |
Пример 3: Использование библиотеки EZButton (одна кнопка).ino | 4 Kb | 18 | Скачать |
![]() |
Пример 4: Использование библиотеки EZButton (несколько кнопок).ino | 3 Kb | 18 | Скачать |
Уроки ESP32 (заметки)
13 марта , 2025
Комментариев:0
Файлов для скачивания:4
Фото:3
Понравилась статья? Нажми
Виджеты для Easy HMI
Читайте также
Мы в соц сетях
Комментарии