#105Новичок

Управление светодиодом кнопкой на ESP32 (переключение)

При каждом нажатии кнопки состояние светодиода меняется: если горел — гаснет, если не горел — загорается. Классический шаблон переключения. Антидребезг убирает механический шум кнопки, чтобы одно нажатие давало одно переключение.

4.6(39)
57 собрано
Управление светодиодом кнопкой на ESP32 (переключение)
Нажми кнопку один раз — светодиод загорится, нажми ещё раз — погаснет, совсем как выключатель дома. ESP32 ловит точный момент нажатия и игнорирует крошечные дрожания внутри кнопки, поэтому каждое нажатие даёт только одно изменение. Здесь ты осваиваешь идею кнопки «вкл/выкл», которая есть почти в каждом устройстве.

Видео

Схема

Управление светодиодом кнопкой на ESP32 (переключение) - Circuit

Исходный код

C++ (Arduino IDE)
1// ─────────────────────────────────────────
2//   BlueGrays · bluegrays.com
3//   Управление светодиодом кнопкой на ESP32 (переключение)
4// ─────────────────────────────────────────
5// Каждое нажатие кнопки переключает светодиод: горел — гаснет, не горел —
6// загорается. Антидребезг 50 мс гарантирует, что одно нажатие даёт ровно
7// одно переключение.
8//
9// Пины:
10//   GPIO 5 -> Красный светодиод (с резистором 220 ohm)
11//   GPIO 4 -> Кнопка (другая ножка к GND)
12
13const int LED_PIN = 5;      // Выход светодиода
14const int BUTTON_PIN = 4;   // Вход кнопки
15
16bool ledState = false;               // Горит ли светодиод сейчас
17bool lastButton = HIGH;              // Предыдущее чтение кнопки
18bool stableButton = HIGH;            // Устойчивое (без дребезга) состояние кнопки
19unsigned long lastChange = 0;        // Время последнего изменения показания (мс)
20const unsigned long DEBOUNCE = 50;   // Время антидребезга (мс)
21
22void setup() {
23  pinMode(LED_PIN, OUTPUT);
24  pinMode(BUTTON_PIN, INPUT_PULLUP);  // Без нажатия читается HIGH
25}
26
27void loop() {
28  bool buttonState = digitalRead(BUTTON_PIN);
29
30  // Перезапускать таймер при каждом изменении показания
31  if (buttonState != lastButton) lastChange = millis();
32
33  // Показание, которое не меняется DEBOUNCE мс, считается устойчивым. Светодиод переключается один
34  // раз, только когда устойчивое состояние становится LOW (новое нажатие).
35  if (millis() - lastChange > DEBOUNCE && buttonState != stableButton) {
36    stableButton = buttonState;
37    if (stableButton == LOW) {
38      ledState = !ledState;
39      digitalWrite(LED_PIN, ledState);
40    }
41  }
42  lastButton = buttonState;
43}
44

Частые вопросы

Какой должна быть длительность антидребезга?

Для большинства кнопок достаточно 20–50 ms. Если пауза слишком короткая, дребезг всё равно будет замечен; если слишком длинная, быстрые нажатия подряд будут пропадать.

Какой момент ловить для переключения?

Лови только момент «нажатия» (переход из HIGH в LOW при INPUT_PULLUP). Чтобы светодиод не переключался снова и снова, пока кнопка зажата, храни прежнее состояние кнопки в переменной.

Правильно ли использовать `delay()` для антидребезга?

Для простых проектов работает, но delay() приостанавливает текущее выполнение loop(), задерживая другие операции в том же потоке. Другие задачи на ESP32 при этом могут выполняться. Отсчёт времени на millis() подходит, чтобы выполнять операции в loop() без блокировки.

Может ли светодиод помнить последнее состояние после выключения и включения?

Да, на ESP32 можно с помощью библиотеки Preferences записывать состояние в энергонезависимую память и читать его при запуске. Тогда даже после отключения и возврата питания светодиод начнёт с последнего состояния.