База знаний · Примеры и обучение

Цифровые сигналы: кнопки и дребезг

Девять примеров про «да или нет»: кнопки, антидребезг, мигание без delay и первые мелодии.

Цифровой мир — это «да или нет»: кнопка нажата или отпущена, светодиод горит или погас. Девять примеров раздела «02. Цифровые сигналы» учат работать с этим миром по-настоящему: с защитой от дребезга, без блокирующих задержек и даже со звуком.

Главные примеры раздела

  • Button — кнопка включает светодиод: базовое «вход управляет выходом».
  • DigitalInputPullup — подтяжка входа: почему кнопка без резистора «плавает» и как встроенная подтяжка чинит это одной строчкой.
  • Debounce — дребезг: механическая кнопка на самом деле «стучит» десятки раз за нажатие, и пример показывает, как получить одно честное срабатывание. Знание, отделяющее любителя от понимающего.
  • StateChangeDetection — считаем нажатия: реагируем на смену состояния, а не на удержание.
  • BlinkWithoutDelay — мигание без delay(): программа успевает делать несколько дел сразу. Первый шаг к многозадачности — идее, на которой стоят все серьёзные проекты.
  • Тоны — несколько примеров со звуком: мелодия на пьезоизлучателе, клавиатура из кнопок, высота тона от датчика.
Раздел цифровых сигналов во встроенных примерах Trema IDE
Девять примеров — и кнопки перестают дребезжать, а мигание — блокировать программу.

Базовый скетч раздела — чтение кнопки. Обратите внимание на INPUT_PULLUP: с ним кнопку можно подключить двумя проводами, без резистора:

const int BUTTON = 2;

void setup() {
  // INPUT_PULLUP включает внутренний резистор: кнопку можно подключить
  // просто между выводом и землёй, без лишних деталей.
  pinMode(BUTTON, INPUT_PULLUP);
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  // С подтяжкой логика перевёрнута: нажата — LOW, отпущена — HIGH.
  bool pressed = (digitalRead(BUTTON) == LOW);

  digitalWrite(LED_BUILTIN, pressed ? HIGH : LOW);

  if (pressed) {
    Serial.println("Кнопка нажата");
    delay(200);  // простая защита от дребезга контактов
  }
}

А это тот же ввод, но по-взрослому — с защитой от дребезга контактов. Именно из-за дребезга одно нажатие иногда считается тремя:

const int BUTTON = 2;
bool lastState = HIGH;          // прошлое показание кнопки
unsigned long lastChange = 0;   // когда показание изменилось
const unsigned long BOUNCE = 30;  // сколько ждать успокоения, мс
int presses = 0;

void setup() {
  pinMode(BUTTON, INPUT_PULLUP);
  Serial.begin(9600);
}

void loop() {
  bool state = digitalRead(BUTTON);

  // Контакты кнопки «звенят» несколько миллисекунд. Считаем нажатие
  // настоящим, только если показание держится дольше BOUNCE.
  if (state != lastState) {
    lastChange = millis();
    lastState = state;
  }

  if (millis() - lastChange > BOUNCE && state == LOW) {
    presses++;
    Serial.print("Нажатий: ");
    Serial.println(presses);
    lastChange = millis();
    while (digitalRead(BUTTON) == LOW) {
      // ждём, пока кнопку отпустят, чтобы не считать одно нажатие много раз
    }
  }
}

Что вы умеете после раздела

Надёжно читать кнопки и датчики-«контакты», считать события, вести несколько процессов без замираний и озвучивать устройства. Этого достаточно для доброй половины бытовых проектов — от дверного звонка с мелодией до счётчика посетителей. Дальше — аналоговый мир, где сигналы становятся плавными.

Обновлено: 19 июля 2026