4.01.3. Лабораторная работа №4.1.3.md


Обработка событий

Тема работы

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

Пример из жизни: Попробуйте нажать на кнопку «Свернуть» у окна на вашем компьютере и, не отпуская, отведите курсор в сторону. Окно не свернётся. Действие произойдёт только в тот момент, когда вы отпустите кнопку мыши над этой иконкой.

В этой лабораторной работе мы научимся отлавливать именно такие события и создадим программу, которая будет переключать светодиод ровно в тот момент, когда вы отпускаете кнопку.

Цель

  • Понять разницу между состоянием кнопки и событием нажатия/отпускания.
  • Научиться отслеживать изменение состояния кнопки с помощью переменных.
  • Реализовать классический алгоритм «переключателя» (toggle switch) для управления светодиодом.

Оборудование и материалы

  • Отладочная плата Рудирон.
  • USB-кабель для подключения Рудирона к компьютеру.
  • Компьютер с настроенной средой Arduino IDE.

Ход работы

  1. Как поймать момент?

    Давайте посмотрим на график сигнала, который приходит с кнопки, настроенной как INPUT_PULLDOWN (как встроенные кнопки Рудирона).

    Рис. 1. График состояний кнопки

    Мы, как люди, легко видим на графике моменты нажатия и отпускания — это переходы между уровнями. Но как это «увидеть» микроконтроллеру, который проверяет состояние миллионы раз в секунду?

    Чтобы обнаружить изменение, нужно сравнить то, что есть сейчас, с тем, что было в прошлом.

    Для этого мы будем использовать переменные:

    • Одна переменная будет хранить текущее состояние кнопки (currentState).
    • Другая — состояние кнопки из предыдущей проверки (lastState).

    Если currentState не равно lastState, значит, произошло событие! А если мы знаем, что currentState стало LOW, а lastState было HIGH, значит, это и есть момент отпускания кнопки.

  2. Настройка и подключение

    Для этого эксперимента нам понадобятся только встроенные компоненты Рудирона. Давайте вспомним, к каким пинам они подключены.

    Компонент Маркировка Пин Константа в коде
    Светодиод 1 L1 5 LED_BUILTIN_1
    Светодиод 2 L2 7 LED_BUILTIN_2
    Кнопка 1 B1 35 BUTTON_BUILTIN_1
    Кнопка 2 B2 31 BUTTON_BUILTIN_2
    Кнопка 3 B3 32 BUTTON_BUILTIN_3

    Подготовка платы к работе стандартная:

    • Установите перемычку PRG | RUN в положение PRG.
    • Подключите плату к компьютеру и настройте Arduino IDE (плата Rudiron Buterbrod R9_16MHz и правильный COM-порт).
  3. Написание и загрузка кода

    Напишем программу, которая будет переключать светодиод L1 по событию отпускания кнопки B1.

    • В Arduino IDE создайте новый скетч и введите следующий код:

      // Переменная для хранения состояния светодиода (включен/выключен)
      bool ledState = false;
      
      // Переменная для хранения ПРЕДЫДУЩЕГО состояния кнопки
      bool lastButtonState = false; 
      
      void setup() {
        pinMode(LED_BUILTIN_1, OUTPUT);
        // Настраиваем встроенную кнопку с внутренним стягивающим резистором
        pinMode(BUTTON_BUILTIN_1, INPUT_PULLDOWN);
      }
      
      void loop() {
        // 1. Считываем ТЕКУЩЕЕ состояние кнопки
        bool currentButtonState = digitalRead(BUTTON_BUILTIN_1);
      
        // 2. Сравниваем текущее состояние с предыдущим
        if (currentButtonState != lastButtonState) {
        // Если они отличаются, значит, произошло событие.
        // Проверяем, было ли это событие «ОТПУСКАНИЕ»
        if (currentButtonState == LOW) { 
            // Кнопку только что отпустили!
            // Меняем состояние светодиода на противоположное
            ledState = !ledState;
            digitalWrite(LED_BUILTIN_1, ledState);
        }
        }
      
        // 3. Запоминаем текущее состояние, чтобы на следующем шаге оно стало «прошлым»
        lastButtonState = currentButtonState;
      
        // Небольшая задержка, чтобы уменьшить дребезг и нагрузку на процессор
        delay(10);
      }
      
    • Нажмите кнопку «Upload», чтобы загрузить код на плату.
  4. Проверка работы

    После загрузки программы светодиод L1 будет выключен.

    • Нажмите и удерживайте кнопку B1. Ничего не произойдёт. Светодиод не загорится.
    • Теперь отпустите кнопку. В этот самый момент светодиод L1 должен загореться.
    • Нажмите и отпустите кнопку ещё раз. Светодиод погаснет.

Результаты

Вы создали программу, которая реагирует не на состояние, а на событие. Светодиод меняет своё состояние только в момент отпускания кнопки, что делает управление более чётким и предсказуемым, как в интерфейсах компьютерных программ.

Анализ результатов

Ключевой момент нашего алгоритма — это сравнение currentButtonState и lastButtonState. Цикл loop() выполняется очень быстро.

  • Пока кнопка не нажата, обе переменные равны LOW.
  • Когда вы нажимаете кнопку, currentButtonState становится HIGH. В этот момент if (currentButtonState != lastButtonState) срабатывает, но вложенное условие if (currentButtonState == LOW) — нет.
  • Пока вы держите кнопку, обе переменные равны HIGH.
  • Когда вы отпускаете кнопку, currentButtonState становится LOW. Снова срабатывает if (currentButtonState != lastButtonState), и на этот раз вложенное условие if (currentButtonState == LOW) тоже истинно! Происходит переключение светодиода.
  • Наконец, строка lastButtonState = currentButtonState; обновляет «прошлое» состояние для следующей итерации цикла.

Выводы

В этой лабораторной работе вы освоили мощный программный приём — отслеживание изменения состояния. Вы научились отличать состояние от события и реализовали алгоритм, который позволяет микроконтроллеру реагировать на конкретные действия пользователя, такие как отпускание кнопки. Этот принцип лежит в основе создания многих сложных интерфейсов.

Вопросы для самопроверки

  1. В чём разница между состоянием и событием при работе с кнопкой?
  2. Зачем в коде нужны две переменные для хранения состояния кнопки (currentButtonState и lastButtonState)?
  3. Что произойдёт, если убрать строку lastButtonState = currentButtonState;?
  4. Как изменить код, чтобы светодиод реагировал на момент нажатия, а не отпускания?
  5. Для чего используется оператор ! в строке ledState = !ledState;?

Вы научились отлавливать события, и теперь ваши проекты могут стать гораздо более отзывчивыми! Переходите к следующей лабораторной работе, чтобы научиться работать с датчиком, который реагирует на положение в пространстве.