Практическая работа 5. Кнопочный переключатель. Arduino

Список деталей для эксперимента

Для дополнительного задания

  • еще 1 кнопка
  • еще 2 провода

Принципиальная схема

Схема на макетке

Обратите внимание

  • Мы могли бы один из контактов кнопки соединить проводом напрямую с одним из входов GND, но мы сначала «раздали» «землю» на длинную рельсу макетки. Если мы работаем с макетной платой, так поступать удобнее, т.к. в схеме могут появляться новые участки, которые тоже нужно будет соединить с «землей»
  • Также полезно руководствоваться соображениями аккуратности изделия, поэтому катод светодиода мы соединяем с другим входом GND отдельным проводом, который не мешает нам работать в середине макетки.

Скетч

p100_led_toggle.ino
#define BUTTON_PIN  3
#define LED_PIN     13

boolean buttonWasUp = true;  // была ли кнопка отпущена?
boolean ledEnabled = false;  // включен ли свет?

void setup()
{
  pinMode(LED_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
}

void loop()
{
  // определить момент «клика» несколько сложнее, чем факт того,
  // что кнопка сейчас просто нажата. Для определения клика мы
  // сначала понимаем, отпущена ли кнопка прямо сейчас...
  boolean buttonIsUp = digitalRead(BUTTON_PIN);

  // ...если «кнопка была отпущена и (&&) не отпущена сейчас»...
  if (buttonWasUp && !buttonIsUp) {
    // ...может это «клик», а может и ложный сигнал (дребезг),
    // возникающий в момент замыкания/размыкания пластин кнопки,
    // поэтому даём кнопке полностью «успокоиться»...
    delay(10);
    // ...и считываем сигнал снова
    buttonIsUp = digitalRead(BUTTON_PIN);
    if (!buttonIsUp) {  // если она всё ещё нажата...
      // ...это клик! Переворачиваем сигнал светодиода
      ledEnabled = !ledEnabled;
      digitalWrite(LED_PIN, ledEnabled);
    }
  }

  // запоминаем последнее состояние кнопки для новой итерации
  buttonWasUp = buttonIsUp;
}

Пояснения к коду

  • Поскольку мы сконфигурировали вход кнопки как INPUT_PULLUP, при нажатии на кнопку на данном входе мы будем получать 0. Поэтому мы получим значение true («истина») в булевой переменнойbuttonIsUp («кнопка отпущена»), когда кнопка отпущена.
  • Логический оператор && («и») возвращает значение «истина» только в случае истинности обоих его операндов. Взглянем на так называемую таблицу истинности для выражения buttonWasUp && !buttonIsUp («кнопка была отпущена и кнопка не отпущена»):
buttonWasUp buttonIsUp !buttonIsUp buttonWasUp && !buttonIsUp
0 0 1 0
0 1 0 0
1 0 1 1
1 1 0 0

Здесь рассмотрены все возможные сочетания предыдущего и текущего состояний кнопки и мы видим, что наш условный оператор if сработает только в случае, когда кнопка нажата только что: предыдущее состояние 1 («была отпущена»), а текущее 0 («не отпущена»).

  • Через 10 миллисекунд мы проверяем еще раз, нажата ли кнопка: этот интервал больше, чем длительность «дребезга», но меньше, чем время, за которое человек успел бы дважды нажать на кнопку. Если кнопка всё еще нажата, значит, это был не дребезг.
  • Мы передаем в digitalWrite не конкретное значение HIGH или LOW, а просто булеву переменнуюledEnabled. В зависимости от того, какое значение было для нее вычислено, светодиод будет зажигаться или гаситься.
  • Последняя инструкция в buttonWasUp = buttonIsUp сохраняет текущее состояние кнопки в переменную предыдущего состояния, ведь на следующей итерации loop текущее состояние уже станет историей.

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

  1. В каком случае оператор && возвращает значение «истина»?
  2. Что такое «дребезг»?
  3. Как мы с ним боремся в программе?
  4. Как можно избежать явного указания значения уровня напряжения при вызове digitalWrite?

Задания для самостоятельного решения

  1. Измените код так, чтобы светодиод переключался только после отпускания кнопки.
  2. Добавьте в схему еще одну кнопку и доработайте код, чтобы светодиод зажигался только при нажатии обеих кнопок.

4 комментария к записи «Практическая работа 5. Кнопочный переключатель. Arduino»

    • В общем-то разница будет не большая, но мы так не пробовали делать. Пользовались только кнопками, которые подключены к макетке.

  1. const
    int BUTTON_PIN=2;
    int LED_PIN1=3, LED_PIN2=4, LED_PIN3=5, State=0;

    boolean buttonWasUp = true; // была ли кнопка отпущена?
    boolean ledEnabled = false; // включен ли свет?

    void setup()
    {
    pinMode(LED_PIN1, OUTPUT);
    pinMode(LED_PIN2, OUTPUT);
    pinMode(LED_PIN3, OUTPUT);
    pinMode(BUTTON_PIN, INPUT_PULLUP);
    }

    void loop()
    {
    boolean buttonIsUp = digitalRead(BUTTON_PIN);
    if (buttonWasUp && !buttonIsUp) {
    delay(10);
    buttonIsUp = digitalRead(BUTTON_PIN);
    if (!buttonIsUp) {
    State = (State+1) % 3;
    switch (State)
    {

    case 0:
    digitalWrite(LED_PIN1,HIGH);
    digitalWrite(LED_PIN2,LOW);
    digitalWrite(LED_PIN3,LOW);
    break;
    case 1:
    digitalWrite(LED_PIN2,HIGH);
    digitalWrite(LED_PIN1,LOW);
    digitalWrite(LED_PIN3,LOW);
    break;
    case 2:
    digitalWrite(LED_PIN3,HIGH);
    digitalWrite(LED_PIN2,LOW);
    digitalWrite(LED_PIN1,LOW);
    break;
    }
    }
    }

    buttonWasUp = buttonIsUp;
    }

  2. const
    int BUTTON_PIN=2,BUTTON_PIN1=6;
    int LED_PIN1=3, LED_PIN2=4, LED_PIN3=5, State=0;

    boolean buttonWasUp = true; // была ли кнопка отпущена?
    boolean ledEnabled = false; // включен ли свет?
    boolean buttonWasUp1 = true; // была ли кнопка отпущена?
    boolean ledEnabled1 = false;

    void setup()
    {
    pinMode(LED_PIN1, OUTPUT);
    pinMode(LED_PIN2, OUTPUT);
    pinMode(LED_PIN3, OUTPUT);
    pinMode(BUTTON_PIN, INPUT_PULLUP);
    pinMode(BUTTON_PIN1, INPUT_PULLUP);
    }

    void loop()
    {
    boolean buttonIsUp = digitalRead(BUTTON_PIN);
    if (buttonWasUp && !buttonIsUp) {
    delay(10);
    buttonIsUp = digitalRead(BUTTON_PIN);
    if (!buttonIsUp) {
    State = (State+1) % 3;
    switch (State)
    {

    case 0:
    digitalWrite(LED_PIN1,HIGH);
    digitalWrite(LED_PIN2,LOW);
    digitalWrite(LED_PIN3,LOW);
    break;
    case 1:
    digitalWrite(LED_PIN2,HIGH);
    digitalWrite(LED_PIN1,LOW);
    digitalWrite(LED_PIN3,LOW);
    break;
    case 2:
    digitalWrite(LED_PIN3,HIGH);
    digitalWrite(LED_PIN2,LOW);
    digitalWrite(LED_PIN1,LOW);
    break;
    }
    }

    }
    boolean buttonIsUp1 = digitalRead(BUTTON_PIN1);
    if (buttonWasUp1 && !buttonIsUp1) {
    delay(10);
    buttonIsUp1 = digitalRead(BUTTON_PIN1);
    if (!buttonIsUp1) {
    State = (State+1) % 3;
    switch (State)
    {

    case 2:
    digitalWrite(LED_PIN1,HIGH);
    digitalWrite(LED_PIN2,LOW);
    digitalWrite(LED_PIN3,LOW);
    break;
    case 1:
    digitalWrite(LED_PIN2,HIGH);
    digitalWrite(LED_PIN1,LOW);
    digitalWrite(LED_PIN3,LOW);
    break;
    case 0:
    digitalWrite(LED_PIN3,HIGH);
    digitalWrite(LED_PIN2,LOW);
    digitalWrite(LED_PIN1,LOW);
    break;
    }
    }

    }
    buttonWasUp = buttonIsUp;
    buttonWasUp1 = buttonIsUp1;
    }

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Анти-спам: выполните заданиеWordPress CAPTCHA