С кнопкой, подключенной к цифровому пину проблем нет, есть много работающих примеров и я их использую. Возникла задача организовать на кнопках, подключённых к аналоговому входу, короткое и длительное нажатие. Кнопки подключаются как на lcd шилде и код оттуда же Код (Text): #define btnPOS1 0 #define btnPOS2 1 #define btnPOS3 2 #define btnPOS4 3 #define btnSpeed 4 #define btnNO 5 int key = 0; int adc_key_in = 0; int adc_key_prev = 0; int read_buttons() { adc_key_in = analogRead(1); delay(15); int k = (analogRead(1) - adc_key_in); if (5 < abs(k)) return btnNO; if (adc_key_in > 1000) return btnNO; if (adc_key_in < 50) return btnPOS1; if (adc_key_in < 195) return btnPOS2; if (adc_key_in < 380) return btnPOS3; if (adc_key_in < 555) return btnPOS4; if (adc_key_in < 780) return btnSpeed; return btnNO; } void setup() { Serial.begin(9600); } void loop() { adc_key_prev = key ; key = read_buttons(); if(key == btnPOS1 ) { Serial.println("POS1"); } if(key == btnNO ) { Serial.println("0 POS"); } } Логика вроде понятна - при нажатии key == btnPOS1 кнопки вкл таймер, при отпускании key == btnNO таймер обнуляется. По прошедшему времени определяем короткое или длительное нажатие. Попробовал Код (Text): if(key == btnPOS1 ) { Time = millis(); Serial.println(Time); } if(key == btnNO ) { Time = 0; } Значения таймера не обнуляются. Куда копать дальше?
Решил проблему. Нашёл статью http://alxarduino.blogspot.com/2013/09/ReadAnalogKeys.html и на основании её завёл аналоговые кнопки как цифровые. Спасибо автору !!!
Прерывание по CHANGE, в прерывании смотреть текущее значение на пине, чтобы определить, было это нажатие или отпускание. А дальше засекать нажатие, запоминать millis(), засекать отпускание, проверять, сколько времени прошло с последнего нажатия или выполнять действие по длинному нажатию, если с нажатия прошло достаточно времени, но отпускания еще не было. Примерно так..
Вот это я делал так Код (Text): #include <DI.h> //подключаем библиотеку DI - обработка дискретного входа из набора библиотек от X-Dron #include <Timer_P.h> //подключаем библиотеку Timer_P - работа с таймерами из набора библиотек от X-Dron #include <TM1637.h> //подключаем библиотеку цифрового четырехзначного индикатора #define Key_P_PIN 2 #define Key_M_PIN 3 #define DISPLAY_CLK_PIN 12 //PIN контакта CLK индикатора #define DISPLAY_DIO_PIN 13 //PIN контакта DIO индикатора // Создание объектов типа "Дистретный вход" они посажены описанные выше пины. Фильтр антидребезга 20мс. DI Key_P(Key_P_PIN, 20); DI Key_M(Key_M_PIN, 20); TM1637 display(DISPLAY_CLK_PIN, DISPLAY_DIO_PIN); //создание и инициализация объекта display класса TM1637 Timer_P Period_T, Delay_T_P, Delay_T_M; int Value; long Period; boolean Key_P_Old, Key_M_Old; void setup() { //делать pinMode для входов не нужно. Они инициализируются при создании объекта класса DI //при работе со входами используется INPUT_PULLUP-режим. Значения входов нормализовываются во время обработки класса. //замкнутая кнопка - логическая 1. //Включаем и настраиваем индикатор display.set(); display.init(); } void loop() { // Обновляем значение дискретных входов // Производится их считывание с пинов и фильтрация через внутреннюю переменную класса. Key_P.DI_Refresh(); Key_M.DI_Refresh(); Delay_T_P.TimerV(Key_P.DI_Read() && !Key_M.DI_Read(), 0, 2, 2500); // если нажата клавиша + запускаем таймер задержки Delay_T_M.TimerV(Key_M.DI_Read() && !Key_P.DI_Read(), 0, 2, 2500); // если нажата клавиша - запускаем таймер задержки if (!Key_P.DI_Read() && !Key_M.DI_Read()) Period=500; //Инициализируем период, если ничего не нажато // Запускаем самосбрасывающийся таймер, если нажата одна из клавиш. Period_T.TimerV((!Period_T.Q0() && (Key_P.DI_Read() || Key_M.DI_Read()) && !(Key_P.DI_Read() && Key_M.DI_Read())), 0, 2, Period); // Самосбрасывающийся таймер периода if ((Key_P.DI_Read() || Key_M.DI_Read()) && !(Key_P.DI_Read() && Key_M.DI_Read())) { if ((Key_P.DI_Read() && Delay_T_P.Q0()) || (Key_M.DI_Read() && Delay_T_M.Q0())) Period=100; if (Key_P.DI_Read() && (!Key_P_Old || Period_T.Q0())) Value+=1; if (Key_M.DI_Read() && (!Key_M_Old || Period_T.Q0())) Value-=1; } Key_P_Old = Key_P.DI_Read(); Key_M_Old = Key_M.DI_Read(); //Значения для отображения на каждом из 4 разрядов int8_t Disp[4]; //Выводим значение отсрочки срабатывания таймера на дисплей Disp[0] = Value/1000; Disp[1] = (Value/100)%10; Disp[2] = (Value/10)% 10; Disp[3] = Value% 10; display.display(Disp); } Для кнопок с LCD Shield, но без индикатора так: Код (Text): #include <Timer_P.h> //подключаем библиотеку Timer_P - работа с таймерами из набора библиотек от X-Dron #include <AnalogKey5.h> AnalogKey5 AKeys(10, 144, 329, 505, 742, 10); // установить пороги для срабатывания каждой кнопки, последний параметр зона отклонения Timer_P Period_T, Delay_T_P, Delay_T_M; // Таймеры периода и задедержек перехода на ускоренный набор int Value; long Period; boolean Key_P_Old, Key_M_Old; void setup() { pinMode(A0, INPUT); } void loop() { AKeys.Refresh (analogRead(A0)); Delay_T_P.TimerV(AKeys.Key1() && !AKeys.Key2(), 0, 2, 2500); // если нажата клавиша + запускаем таймер задержки Delay_T_M.TimerV(AKeys.Key2() && !AKeys.Key1(), 0, 2, 2500); // если нажата клавиша - запускаем таймер задержки if (!AKeys.Key1() && !AKeys.Key2()) Period=500; //Инициализируем период, если ничего не нажато // Запускаем самосбрасывающийся таймер, если нажата одна из клавиш. Period_T.TimerV((!Period_T.Q0() && (AKeys.Key1() || AKeys.Key2()) && !(AKeys.Key1() && AKeys.Key2())), 0, 2, Period); // Самосбрасывающийся таймер периода if ((AKeys.Key1() || AKeys.Key2()) && !(AKeys.Key1() && AKeys.Key2())) { if ((AKeys.Key1() && Delay_T_P.Q0()) || (AKeys.Key2() && Delay_T_M.Q0())) Period=100; if (AKeys.Key1() && (!Key_P_Old || Period_T.Q0())) Value+=1; if (AKeys.Key2() && (!Key_M_Old || Period_T.Q0())) Value-=1; } Key_P_Old = AKeys.Key1(); Key_M_Old = AKeys.Key2(); } Понадобится библиотека класса AnalogKey5. Она по ссылке. https://yadi.sk/d/WrKRyFqLeSprm В общую библиотеку пока не включил.