====== Эксперимент 10. Кнопочный переключатель ====== [[миксер|← Миксер]] | [[конспект-arduino:|Оглавление]] | [[светильник-с-кнопочным-управлением|Светильник с кнопочным управлением →]] В этом эксперименте мы делаем из тактовой кнопки триггер, борясь с «дребезгом». ===== Список деталей для эксперимента ===== * 1 плата [[amp>product/arduino-uno|Arduino Uno]] * 1 беспаечная [[amp>collection/breadboards|макетная плата]] * 1 тактовая [[amp>product/tactile-button|кнопка]] * 1 [[amp>product/resistor-220r|резистор]] номиналом 220 Ом * 1 [[amp>product/led-5mm|светодиод]] * 5 проводов [[amp>product/wire-mm|«папа-папа»]] ====Для дополнительного задания==== * еще 1 кнопка * еще 2 провода ===== Принципиальная схема ===== {{ :конспект-arduino:10_led_toggle_scheme.svg.png?nolink& |}} ===== Схема на макетке ===== {{ :конспект-arduino:10_led_toggle_bread.svg.png?nolink& |}} ===== Обратите внимание ===== * Мы могли бы один из контактов кнопки соединить проводом напрямую с одним из входов GND, но мы сначала «раздали» «землю» на длинную рельсу макетки. Если мы работаем с макетной платой, так поступать удобнее, т.к. в схеме могут появляться новые участки, которые тоже нужно будет соединить с «землей» * Также полезно руководствоваться соображениями аккуратности изделия, поэтому катод светодиода мы соединяем с другим входом GND отдельным проводом, который не мешает нам работать в середине макетки. ===== Скетч ===== #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''? ===== Задания для самостоятельного решения ===== - Измените код так, чтобы светодиод переключался только после отпускания кнопки. - Добавьте в схему еще одну кнопку и доработайте код, чтобы светодиод зажигался только при нажатии обеих кнопок. ---- [[миксер|← Миксер]] | [[конспект-arduino:|Оглавление]] | [[светильник-с-кнопочным-управлением|Светильник с кнопочным управлением →]]