В этой статье расскажу как с помощью одной кнопки выполнять два различных действия: одно при коротком нажатии на кнопку и второе при длительном удержании кнопки. Пример использования можно увидеть тут или посмотрев моё видео Таймер для фоторезиста на микроконтроллере ATtiny13 на YouTube.
Подключения кнопки к Arduino.
Прежде всего понадобиться собрать схему состоящею из кнопки, двух светодиодов и трех резисторов.


Резисторы R2 и R3 нужны для ограничения тока, проходящего через светодиоды. Сопративление R1 это резистор подтяжки, он необходим для того, что бы пин к которому подключена кнопка, не висел в воздухе. В теории от этого резистора можно отказаться, использовав внутренний резистор Ардуино (команда: pinMode(12, INPUT_PULLUP); ) и замыкать его на землю кнопкой.

Но, при таком подключении изменится логика работы программы: кнопка нажата на входе — 0, кнопка отпущена на входе +5V. Поэтому мы остановимся на первом варианте с использованием дополнительного резистора.
Обработка короткого нажатия на кнопку
Прежде всего дадим название пинам на которые подключены элементы схемы и создадим несколько переменных для обработки нажатия на кнопку и хранения состояния светодиодов. Затем в функции void Setup() сконфигурируем пины светодиодов как выходы, а кнопки как вход.
#define buttonPin 12 // пин на который поключена кнопка #define Green_LED_pin 2 // пин к которому подключен зеленый светодиод #define Red_lED_pin 7 // пин к которому подключен красный светодиод boolean Green_LED = false; // Переменная для хранения состояния зеленого светодиода boolean Red_lED = false; // Переменная для хранения состояния красного светодиода boolean button = false; // Логическая переменная для хранения состояние кнопки boolean press_flag = false; // Флажок нажатия кнопки boolean long_press_flag = false; // Флажок долгого нажатия на кнопку unsigned long last_press = 0; // переменная хранит момента последнего нажатия на кнопку void setup() { pinMode(buttonPin, INPUT); // пин кнопки как вход pinMode(Green_LED_pin, OUTPUT); // пин зеленого светодиода как выход pinMode(Red_lED_pin, OUTPUT); // пин красного светодиода как выход }
Далее для функции void loop() прописываем следующий код:
void loop() { digitalWrite(Green_LED_pin, Green_LED); // Вкл./Выкл. зеленый диод button = digitalRead(buttonPin); // считывает текущее состояние кнопки if (button == true && press_flag == false && millis() - last_press > 100) { // если кнопка была нажата и не была нажата до этого (флажок короткого нажатия = false) // и с последненго нажатия прошло более 100 миллисекунд (защита // от дребезга контактов) то... press_flag = !press_flag; //...поднять флажок короткого нажатия на кнопку и last_press = millis(); // присвоить текущее время переменной last_press // сюда вписываем события неоходимые при коротком нажатии на кнопку Green_LED = !Green_LED; // например меняем состояние зеленого диода } if (button == false && press_flag == true) { // если кнопка отпущена и была нажата, то... press_flag = !press_flag; // опустить флажок короткого нажатия на на кнопку } }
Первая строка зажигает и гасит зеленый светодиод руководствуясь логической переменной Green_LED, которая хранит его состояние. Затем микроконтроллер считывает состояние кнопки: нажата или отпущена.
Далее мы имеем два условия. В первом условие выполняется код если кнопка нажата, но не была нажата до этого. Второе условие будет выполнено если отпустить кнопку.
Таким образом при нажатии на кнопку код из первого условия выполниться один раз так как переменная press_flag поменяет свое значение на false только после того, как кнопка будет отпущена.
После загрузки скетча в Arduino светодиод будет включаться и выключаться при коротком нажатии на кнопку.
Обработка длительного нажатия на кнопку
Теперь изменим код функции void loop() так, что бы была реализована обработка длительного нажатия на кнопку:
void loop() { digitalWrite(Green_LED_pin, Green_LED); // Вкл./Выкл. зеленый диод digitalWrite(Red_lED_pin, Red_lED); // Вкл./Выкл. красный диод button = digitalRead(buttonPin); // считывает текущее состояние кнопки if (button == true && press_flag == false && millis() - last_press > 100) { // если кнопка была нажата и не была нажата до этого (флажок короткого нажатия = false) // и с последненго нажатия прошло более 100 миллисекунд (защита // от дребезга контактов) то... press_flag = !press_flag; //...поднять флажок короткого нажатия на кнопку и last_press = millis(); // присвоить текущее время переменной last_press } if (button == true && press_flag == true && millis() - last_press > 1000) { // если кнопку продолжают нажимать более 1 секунды, то... long_press_flag = !long_press_flag; // ...поднять флажок долгого нажатия и last_press = millis(); // присвоить текущее время переменной last_press // Сюда вписываем события неоходимые при длительном нажатии на кнопку Red_lED = !Red_lED; // например меняем состояние красного диода } if (button == false && press_flag == true && long_press_flag == true) { // если кнопка отпушена и была нажата длительное время, то... press_flag = !press_flag; // опустить флажок короткого нажатия long_press_flag = !long_press_flag; // и длинного нажатия } if (button == false && press_flag == true && long_press_flag == false) { // если кнопка отпущена и было только короткое нажатие, то... press_flag = !press_flag; // опустить флажок короткого нажатия // сюда вписываем события неоходимые при коротком нажатии на кнопку Green_LED = !Green_LED; // например меняем состояние зеленого диода } }
В начале кода добавлена строка зажигающая и госящая красный светодиод. Затем, как и в случае с коротким нажатием на кнопку, считываеться её состояние и при сохранении всех условий переменной press_flag присваиваеться еденица (true).
Далее, если кнопку продолжают удерживать более 1 секунды, то происходит обработка события, наступающего при длительном удержании кнопки и присвоение переменной long_press_flag еденицы.
Основное отличие в том, что обработка события, которое должно наступить при кратковременном нажатие на кнопку, перенесена в самый конец кода. В момент когда кнопка отпущена и была нажата кратковременно.
В том случае если произведено долговременное нажатие на кнопку, то при её отпускании переменным press_flag и long_press_flag просто присваиваються false, так как код события уже выплнен в момент длительного нажатия на кнопку.
Теперь при кратковременном нажатии на кнопку будет загораться и гаснуть зелёный светодиод. А при длительном нажатии на кнопку — красный. Вместе с тем эти события будут происходить независемо друг от друга.
Далее для удобства копирования и использования приведен весь код без разбивки на сегменты и без комментариев.
#define buttonPin 12 #define Green_LED_pin 2 #define Red_lED_pin 7 boolean Green_LED = false; boolean Red_lED = false; boolean button = false; boolean press_flag = false; boolean long_press_flag = false; unsigned long last_press = 0; void setup() { pinMode(buttonPin, INPUT); pinMode(Green_LED_pin, OUTPUT); pinMode(Red_lED_pin, OUTPUT); } void loop() { digitalWrite(Green_LED_pin, Green_LED); digitalWrite(Red_lED_pin, Red_lED); button = digitalRead(buttonPin); if (button == true && press_flag == false && millis() - last_press > 100) { press_flag = !press_flag; last_press = millis(); } if (button == true && press_flag == true && millis() - last_press > 1000) { long_press_flag = !long_press_flag; last_press = millis(); Red_lED = !Red_lED; } if (button == false && press_flag == true && long_press_flag == true) { press_flag = !press_flag; long_press_flag = !long_press_flag; } if (button == false && press_flag == true && long_press_flag == false) { press_flag = !press_flag; Green_LED = !Green_LED; } }