Цифровой вход: кнопка и события

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

Рука нажимает кнопку на макетной плате рядом с платой Arduino

После урока сможешь: подключить кнопку к Arduino, считать её состояние командой digitalRead, менять поведение программы по событию через if/else. В конце — «переключатель режима»: станция меняет режим по нажатию.

Подключаем кнопку: pinMode и INPUT_PULLUP

В Wokwi добавь на схему компонент «Pushbutton». Подключи одну его ножку к пину 2 платы, вторую — к GND (общий провод). В setup() настрой пин командой pinMode(2, INPUT_PULLUP) — это вход с включённым внутренним подтягивающим резистором: пока кнопка не нажата, пин сам держит сигнал HIGH; как только кнопка нажата, она замыкает пин на GND, и сигнал становится LOW.

Подключение кнопки Pushbutton к плате Arduino: провода к пину 2 и GND, кнопка добавления компонента
void setup() {
  pinMode(2, INPUT_PULLUP);
  Serial.begin(9600);
}
  INPUT_PULLUP — важная инверсия:

   кнопка НЕ нажата     кнопка нажата
   digitalRead = HIGH    digitalRead = LOW
        (по умолчанию)      (замкнуто на GND)

  Так у большинства кнопок в Arduino:
  LOW  = кнопка НАЖАТА
  HIGH = кнопка ОТПУЩЕНА

Это частая ловушка новичков: интуитивно кажется, что нажатие = HIGH. С INPUT_PULLUP всё наоборот: нажатие даёт LOW. Держи эту инверсию в голове весь урок.

digitalRead — считать сигнал со входа

Команда digitalRead(пин) возвращает текущий сигнал: HIGH или LOW. Как и в Python, значение можно сохранить в переменную и сравнить в условии — if/else работают точно так же, как ты уже писал.

void loop() {
  int sostoyanie = digitalRead(2);
  if (sostoyanie == LOW) {
    Serial.println("Кнопка нажата");
  } else {
    Serial.println("Кнопка отпущена");
  }
  delay(200);
}
Кнопка отпущена
Кнопка отпущена
Кнопка нажата
...
  Развилка if/else по значению входа:

  digitalRead(2)
        |
        v
  sostoyanie == LOW? ---- да ----> "Кнопка нажата"
        |
        нет
        |
        v
  "Кнопка отпущена"

Сравнение == (два знака) проверяет равенство, а одиночный = — присваивает значение. Перепутать их в условии — рабочая, но неверная программа: она соберётся, но поведение будет сломано (подробно разберём на занятии про отладку).

Миссия: переключатель режима

Собери в Wokwi: светодиод на пине 13 и кнопку на пине 2 (INPUT_PULLUP). Пока кнопка отпущена — светодиод горит и печатается «Режим: мониторинг»; пока нажата — светодиод гаснет и печатается «Режим: диагностика».

void setup() {
  pinMode(13, OUTPUT);
  pinMode(2, INPUT_PULLUP);
  Serial.begin(9600);
}

void loop() {
  int knopka = digitalRead(2);
  if (knopka == LOW) {
    digitalWrite(13, LOW);
    Serial.println("Режим: диагностика");
  } else {
    digitalWrite(13, HIGH);
    Serial.println("Режим: мониторинг");
  }
  delay(200);
}

Проверь себя

Контрольный вопрос. Что делает команда digitalRead(2)?

АСчитывает текущий сигнал на пине 2: HIGH или LOW
БПодаёт сигнал HIGH на пин 2
ВНастраивает пин 2 как выход

Подсказка: Read по-английски — «читать». Речь о получении данных со входа, не о подаче сигнала.

Проверить ответ →

Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →

Контрольный вопрос. Что делает pinMode(2, INPUT_PULLUP)?

АНастраивает пин 2 как вход с внутренним подтягивающим резистором к HIGH
БНастраивает пин 2 как выход для светодиода
ВСразу считывает состояние кнопки

Подсказка: Обратись к блоку «Подключаем кнопку» — там объясняется именно эта команда.

Проверить ответ →

Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →

Контрольный вопрос. Пин настроен как INPUT_PULLUP. Кнопка НЕ нажата. Что вернёт digitalRead?

АHIGH
Б0
ВLOW

Подсказка: Внутренний резистор держит на пине активный (высокий) уровень сигнала, пока кнопка не замкнула его на GND.

Проверить ответ →

Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →

Контрольный вопрос. Пин настроен как INPUT_PULLUP. Кнопка нажата (замкнута на GND). Что вернёт digitalRead?

АOUTPUT
БLOW
ВHIGH

Подсказка: Нажатие соединяет пин с GND — это и есть низкий уровень сигнала.

Проверить ответ →

Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →

Контрольный вопрос. Кнопка сейчас ОТПУЩЕНА. Что выведет один проход loop()?

Исходный код для этого задания:

void loop() {
  int sostoyanie = digitalRead(2);
  if (sostoyanie == LOW) {
    Serial.println("Кнопка нажата");
  } else {
    Serial.println("Кнопка отпущена");
  }
  delay(200);
}
АОшибка чтения
БКнопка отпущена
ВКнопка нажата

Подсказка: Отпущенная кнопка с INPUT_PULLUP даёт HIGH — какая ветвь if/else сработает при HIGH?

Проверить ответ →

Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →

Задание. Напиши код сам. Допиши команду вместо ___, которая считывает сигнал с пина 2 и сохраняет его в sostoyanie.

Исходный код для этого задания:

int sostoyanie = ___(2);

Подсказка: Эта команда была введена в материале, когда объяснялось, как считать текущий сигнал со входа — если не помнишь точное имя, перечитай тот раздел.

✅ Готово, если: программа запускается без ошибок и выводит то, что просят в задании.

Проверить ответ →

Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →

Контрольный вопрос. Программа компилируется, но кнопка перестала работать правильно — светодиод горит всегда, независимо от нажатия. В чём проблема?

Исходный код для этого задания:

int knopka = digitalRead(2);
if (knopka = LOW) {
  digitalWrite(13, HIGH);
}
АПеременная knopka объявлена неправильно
БВ условии стоит один знак = (присваивание) вместо == (сравнение)
ВdigitalRead нельзя использовать внутри if

Подсказка: Один знак = кладёт значение в переменную и делает условие всегда истинным. Сравнение — это два знака.

Проверить ответ →

Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →

Контрольный вопрос. За два прохода loop() кнопку сначала нажали, потом отпустили. Что выведется — впиши обе строки точно, как они появятся, каждую с новой строки.

Исходный код для этого задания:

// проход 1: кнопка нажата (LOW)
// проход 2: кнопка отпущена (HIGH)
void loop() {
  int s = digitalRead(2);
  if (s == LOW) {
    Serial.println("Авария: кнопка удержана");
  } else {
    Serial.println("Норма");
  }
  delay(200);
}

Подсказка: Разбери проходы по отдельности: LOW заходит в первую ветвь if, HIGH — в else.

Проверить ответ →

Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →

Задание. Напиши код сам (if/else, 5 строк). В переменной knopka уже сохранён результат digitalRead. Если knopka равен LOW — выведи «Тревога», иначе выведи «Тишина».

Исходный код для этого задания:

int knopka = digitalRead(2);
// напиши if/else по условию выше

Подсказка: Шаблон: if (условие) { Serial.println(…); } else { Serial.println(…); }

✅ Готово, если: программа запускается без ошибок и выводит то, что просят в задании.

Онлайн-проверка ответа появится позже

Задание. Напиши программу целиком (setup + loop, около 8 строк). Пин 2 — вход с INPUT_PULLUP, Serial на скорости 9600. В loop(): считай кнопку в переменную knopka; если нажата (LOW) — выведи «Событие: нажатие», иначе ничего не выводи. Пауза 100 миллисекунд в конце loop().

Исходный код для этого задания:

// напиши setup() и loop() целиком по описанию выше

Подсказка: В setup — pinMode с INPUT_PULLUP и Serial.begin; в loop — digitalRead в переменную, if без else, delay(100) в конце.

✅ Готово, если: программа запускается без ошибок и выводит то, что просят в задании.

Онлайн-проверка ответа появится позже

Контрольный вопрос. Что реально произойдёт при выполнении этой программы, если условие содержит присваивание вместо сравнения?

Исходный код для этого задания:

int knopka = digitalRead(2);
if (knopka = LOW) {
  Serial.println("Сработало");
} else {
  Serial.println("Не сработало");
}
АВ knopka запишется значение LOW, условие станет всегда ложным (LOW = 0), и напечатается «Не сработало» независимо от кнопки
БУсловие будет работать как обычное сравнение, ошибки не будет
ВПрограмма не соберётся — компилятор запретит присваивание внутри if

Подсказка: LOW равно числу 0. Присваивание if (x = 0) возвращает само присвоенное значение — подумай, ложное оно или истинное для if.

Онлайн-проверка ответа появится позже

Задание. Напиши программу целиком (около 10 строк). Пин 13 — светодиод (выход), пин 2 — кнопка (вход, INPUT_PULLUP), Serial на 9600. Пока кнопка НЕ нажата — светодиод горит и печатается «Режим: мониторинг». Пока нажата — светодиод не горит и печатается «Режим: диагностика». Пауза 150 миллисекунд в конце loop().

Исходный код для этого задания:

// напиши setup() и loop() целиком по описанию выше

Подсказка: Собери из уже знакомого: два pinMode в setup, в loop — digitalRead в переменную и if/else с digitalWrite + Serial.println в каждой ветке.

✅ Готово, если: программа запускается без ошибок и выводит то, что просят в задании.

Онлайн-проверка ответа появится позже

Что дальше

Теперь станция умеет реагировать на цифровой сигнал (нажато/не нажато). На следующем занятии добавим аналоговый вход — сигнал, который меняется не двумя состояниями, а плавно, как реальный датчик.

Итог: ты подключил кнопку, считываешь её состояние через digitalRead, помнишь про инверсию INPUT_PULLUP и умеешь менять поведение программы по событию. Дальше — аналоговый вход и настоящий датчик.

Назад  ·  ↑ В начало урока  ·  ⌂ В начало курса  ·  Вперёд →

Школа Виктора Комлева