В данном уроке рассматривается проблема дребезга контактов, возникающая при использовании механических кнопок и переключателей с микроконтроллером 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 | 99 | Скачать | |
| Пример 2: Чтение состояния кнопки с подавлением дребезга.ino | 2 Kb | 96 | Скачать | |
| Пример 3: Использование библиотеки EZButton (одна кнопка).ino | 4 Kb | 96 | Скачать | |
| Пример 4: Использование библиотеки EZButton (несколько кнопок).ino | 3 Kb | 97 | Скачать |
Уроки ESP32 (заметки)
13 марта , 2025
Комментариев:0
Файлов для скачивания:4
Фото:3
Понравилась статья? Нажми
Читайте также
Мы в соц сетях
Комментарии