Список деталей для эксперимента
-
1 плата Arduino Uno
-
1 беспаечная макетная плата
-
1 тактовая кнопка
-
1 резистор номиналом 220 Ом
-
5 проводов «папа-папа»
Для дополнительного задания
-
еще 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
текущее состояние уже станет историей.
Вопросы для проверки себя
-
В каком случае оператор
&&
возвращает значение «истина»? -
Что такое «дребезг»?
-
Как мы с ним боремся в программе?
-
Как можно избежать явного указания значения уровня напряжения при вызове
digitalWrite
?
Задания для самостоятельного решения
-
Измените код так, чтобы светодиод переключался только после отпускания кнопки.
-
Добавьте в схему еще одну кнопку и доработайте код, чтобы светодиод зажигался только при нажатии обеих кнопок.
А если использовать кнопочный выключатель, который к люстре???
В общем-то разница будет не большая, но мы так не пробовали делать. Пользовались только кнопками, которые подключены к макетке.
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;
}
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;
}