Урок 10. Кнопочный переключатель


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

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

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

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

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

Урок 10. Кнопочный переключатель. Принципиальная схема

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

Урок 10. Кнопочный переключатель. Схема на макетке

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

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

Скетч

  1. define BUTTON_PIN  3
  2. #define LED_PIN     13
  3.  
  4. boolean buttonWasUp = true;  // была ли кнопка отпущена?
  5. boolean ledEnabled = false;  // включен ли свет?
  6.  
  7. void setup()
  8. {
  9.   pinMode(LED_PIN, OUTPUT);
  10.   pinMode(BUTTON_PIN, INPUT_PULLUP);
  11. }
  12.  
  13. void loop()
  14. {
  15.   // определить момент «клика» несколько сложнее, чем факт того,
  16.   // что кнопка сейчас просто нажата. Для определения клика мы
  17.   // сначала понимаем, отпущена ли кнопка прямо сейчас...
  18.   boolean buttonIsUp = digitalRead(BUTTON_PIN);
  19.  
  20.   // ...если «кнопка была отпущена и (&&) не отпущена сейчас»...
  21.   if (buttonWasUp && !buttonIsUp) {
  22.     // ...может это «клик», а может и ложный сигнал (дребезг),
  23.     // возникающий в момент замыкания/размыкания пластин кнопки,
  24.     // поэтому даём кнопке полностью «успокоиться»...
  25.     delay(10);
  26.     // ...и считываем сигнал снова
  27.     buttonIsUp = digitalRead(BUTTON_PIN);
  28.     if (!buttonIsUp) {  // если она всё ещё нажата...
  29.       // ...это клик! Переворачиваем сигнал светодиода
  30.       ledEnabled = !ledEnabled;
  31.       digitalWrite(LED_PIN, ledEnabled);
  32.     }
  33.   }
  34.  
  35.   // запоминаем последнее состояние кнопки для новой итерации
  36.   buttonWasUp = buttonIsUp;
  37. }

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

  • Поскольку мы сконфигурировали вход кнопки как 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 текущее состояние уже станет историей.

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

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

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

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

wiki.amperka.ru