Кнопка на ESP32: INPUT_PULLUP, антидребезг і перемикання світлодіода
Кнопка без жодних резисторів завдяки внутрішній підтяжці, чому контакти «деренчать» і як програмно відрізнити одне натискання від двадцяти. Одне натискання — світлодіод увімкнено, наступне — вимкнено.
Про проєкт
Кнопка — найпростіший вхід, але саме тут з'являються два підступні ефекти: «плаваючий» вхід і брязкіт контактів. Зберемо перемикач: одне натискання вмикає світлодіод, наступне вимикає.
Що знадобиться
- ESP32 DevKit
- Тактова кнопка 6×6 мм
- Світлодіод і резистор 220 Ом
- Макетна плата й перемички
Схема
| Деталь | Підключення |
|---|---|
| Кнопка | один контакт → GPIO4, інший → GND |
| Світлодіод | GPIO23 → резистор 220 Ом → анод; катод → GND |
Зовнішній резистор для кнопки не потрібен: використаємо вбудовану підтяжку.
Чому вхід «плаває»
Коли кнопку відпущено, GPIO4 не з'єднаний ні з чим. Такий вхід ловить наводки від руки чи сусідніх проводів і читається то як 0, то як 1. Рішення — підтягувальний резистор до 3.3 В: у спокої він тримає вхід у HIGH, а натиснута кнопка замикає його на землю і дає LOW.
В ESP32 такий резистор (~45 кОм) уже вбудовано, його вмикає pinMode(pin, INPUT_PULLUP). Звідси «інверсна» логіка: натиснуто = LOW.
GPIO34–39 не мають внутрішніх підтяжок і працюють лише як входи. Для кнопок на цих виводах потрібен зовнішній резистор 10 кОм.
Брязкіт контактів
Механічні контакти не замикаються одразу: протягом 1–10 мс вони кілька разів підскакують. Без захисту одне натискання перетворюється на кілька перемикань, і світлодіод вмикається та одразу вимикається.
Антидребезг ігнорує зміни, що сталися раніше ніж через 30 мс після попередньої. Час беремо з millis(), а не з delay(), тож loop() не блокується.
Код
// Кнопка перемикає світлодіод: INPUT_PULLUP + антидребезг
const int BUTTON_PIN = 4;
const int LED_PIN = 23;
bool ledOn = false;
int lastState = HIGH;
unsigned long lastChange = 0;
void setup() {
Serial.begin(115200);
pinMode(BUTTON_PIN, INPUT_PULLUP); // натиснуто = LOW
pinMode(LED_PIN, OUTPUT);
}
void loop() {
int state = digitalRead(BUTTON_PIN);
if (state != lastState && millis() - lastChange > 30) { // антидребезг
lastChange = millis();
lastState = state;
if (state == LOW) { // реагуємо лише на момент натискання
ledOn = !ledOn;
digitalWrite(LED_PIN, ledOn ? HIGH : LOW);
Serial.printf("Світлодіод %s\n", ledOn ? "УВІМК" : "ВИМК");
}
}
}
Типові помилки
INPUTзамістьINPUT_PULLUPбез зовнішнього резистора: вхід плаває, і симулятор про це попередить.- Кнопка між 3.3 В і GND без резистора: натискання замикає живлення накоротко.
- Кнопка на GPIO0, GPIO2 чи GPIO12, затиснута під час увімкнення, змінює режим завантаження ESP32.
Що далі
- Розпізнавайте довге натискання: якщо
LOWтримається понад 1 с, робіть іншу дію. - Коли кнопок стане кілька, винесіть антидребезг в окремий клас, як у статті «Класи C++: Led і Button».