Полный пакет здесь https://yadi.sk/d/XQJnIzg43HEeJa Ну головной файл тут Спойлер Код (C++): /* Cl_do_btn.ino кнопка */ void none() {} void f1() { Serial.println("knok1-knok1"); } void f2() { Serial.println("knok2-knok2"); } #include "Cl_do_btn.h" Cl_do_btn btn1(2, 0, none); //пин 2, 0 уров наж.кнопки , выполнить функцию none() Cl_do_btn btn2(3, 0, none); //пин 3, 0 уров наж.кнопки , выполнить функцию none() void setup() { Serial.begin(9600); btn1.setup(); btn1.Do_Btn = f1; btn2.setup(); btn2.Do_Btn = f2; } void loop() { btn1.loop(); btn2.loop(); } Здесь вы видете, что можно програмно задавать и менять действие при нажатии клавиши. Такая себе нежесткая логика. А поменяв подключаемый модуль можно подключить или аналоговую клавиатуру или ИК приемник.
Что делает это выражение? Код (C++): class Cl_do_btn { .... bool low; .... inline bool read() { return digitalRead(pin)^low; // ??? }; ....
Для инициализации членов класса в конструкторе есть специальный раздел. Код (C++): Cl_do_btn::Cl_do_btn(byte _pin, bool high, void (* _Do_Btn)()): pin(_pin), low (!high), Do_Btn (_Do_Btn) { } Если не делать так, то члены класса сначала принимают значения по умолчанию, а затем в теле конструктора им присваиваются новые значения. Двойная работа. Нужно учесть что инициализация происходит в порядке объявления членов в классе, а не как они перечислены в конструкторе.
То есть функция так же циклически вызывается, внутри ожидается факт отпускания кнопки с засеканием времени удержания. Собственно все это можно же сделать обычной функцией с парой-тройкой строк внутри. Разве что библиотекой удобнее пользоваться тем же новичкам. А по размеру кода как дела обстоят? Проверить не могу, не дома.
Скорее всего вы заблуждаетесь. Этот класс создан для того что бы не парить мозг при переделке, когда уровень нажатой кнопки 0 , а когда единица. Можно было назвать переменную ON или оn, но для меня это слово зарезевировано для функции "включить". Так что пришлось назвать ее high. То есть если high = 1, то уровень нажатой клопки 1. Но операция "Исключающая ИЛИ" [^] немного неудобно устроена Уровень тогда был бы digitalRead(pin)^(!high) . Но что бы не напрягать себе голову я применил digitalRead(pin)^low. Просто . Тем более класс я рисовал для себя.
Разумеется можно даже написать и в коде любителям. Я вообще-то борюсь с программами - простынями в 100-200-1000 строк. Так что там функция, там функция и привет простыня. А там где простыня, может быть глюки, как минимум с совпадением названий переменных. Если вам интересно , то я подкину еще один код. Пакет здесь.https://yadi.sk/d/ZYZuO8v93HiDs4 Спойлер: головной файл Код (C++): /* Plug_btm.ino подключить кнопку->2 // при нажатии сделать фукнцию 1 подключить кнопку->3 // при нажатии сделать фукнцию 2 */ #include "Cl_do_btn.h" void f1() { Serial.println("knok1-knok1"); } void f2() { Serial.println("knok2-knok2"); } void setup() { Serial.begin(9600); Plug_btm(2, 0, f1); //пин 2, 0 уров наж.кнопки , выполнить функцию f1() Plug_btm(3, 0, f2); //пин 3, 0 уров наж.кнопки , выполнить функцию f2() } void loop() { Btns_loop(); }
А можно пример кода, на словах не понятно( Я находил пример кода, там почти то, что мне надо, но работает этот код криваовато... Спойлер: Код Код (C++): #define buttonPin 19 // analog input pin to use as a digital input #define ledPin1 9 // digital output pin for LED 1 indicator #define ledPin2 8 // digital output pin for LED 2 indicator #define debounce 20 // ms debounce period to prevent flickering when pressing or releasing the button #define holdTime 2000 // ms hold period: how long to wait for press+hold event // Button variables int buttonVal = 0; // value read from button int buttonLast = 0; // buffered value of the button's previous state long btnDnTime; // time the button was pressed down long btnUpTime; // time the button was released boolean ignoreUp = false; // whether to ignore the button release because the click+hold was triggered // LED variables boolean ledVal1 = false; // state of LED 1 boolean ledVal2 = false; // state of LED 2 //================================================= void setup() { // Set button input pin pinMode(buttonPin, INPUT); digitalWrite(buttonPin, HIGH ); // Set LED output pins pinMode(ledPin1, OUTPUT); digitalWrite(ledPin1, ledVal1); pinMode(ledPin2, OUTPUT); digitalWrite(ledPin2, ledVal2); } //================================================= void loop() { // Read the state of the button buttonVal = digitalRead(buttonPin); // Test for button pressed and store the down time if (buttonVal == LOW && buttonLast == HIGH && (millis() - btnUpTime) > long(debounce)) { btnDnTime = millis(); } // Test for button release and store the up time if (buttonVal == HIGH && buttonLast == LOW && (millis() - btnDnTime) > long(debounce)) { if (ignoreUp == false) event1(); else ignoreUp = false; btnUpTime = millis(); } // Test for button held down for longer than the hold time if (buttonVal == LOW && (millis() - btnDnTime) > long(holdTime)) { event2(); ignoreUp = true; btnDnTime = millis(); } buttonLast = buttonVal; } //================================================= // Events to trigger by click and press+hold void event1() { ledVal1 = !ledVal1; digitalWrite(ledPin1, ledVal1); } void event2() { ledVal2 = !ledVal2; digitalWrite(ledPin2, ledVal2); }
Если вам надо отличать короткое и длинное нажатие (0,5 сек) то Пакет здесь https://yadi.sk/d/CB38v5-13F3VQM И да он написан в более давнишнем стиле. Спойлер: головной файл Код (C++): /*Class_do_btn_long.ino кнопка 1 ->2 (btn1_pin) кнопка */ #include "Cl_do_btn_long.h" const byte btn1_pin = 2; Cl_do_btn_long Btn1(btn1_pin);// подключить кнопку на выв 2 void Do_Btn1() { Serial.println("Do_Btn1"); }; void DoLong_Btn1() { Serial.println("DoLong_Btn1"); }; void setup() { Serial.begin(9600); Btn1.setup(); } void loop() { Btn1.loop(& Do_Btn1, &DoLong_Btn1); }
Да . Код (C++): /*Cl_do_btn_long.h */ #ifndef Cl_do_btn_long_h #define Cl_do_btn_long_h #include "Arduino.h" class Cl_do_btn_long { public: Cl_do_btn_long(byte _pin); void setup(); void loop(void (* Do_1)(), void (* Do_3)()); private: byte pin ; bool btn, btn_old; bool bounce_btn = 0; // антидребезговый флаг uint32_t past = 0 ; const uint32_t time = 500 ;//<--------- здесь и выставляй время bool flag = 0; uint32_t past_flag = 0 ; };
Я не про вашу переменную high, а про библиотечные константы HIGH и LOW, которые возвращает digitalRead. С чего вы взяли что HIGH^true = HIGH^1 это 0 = false?
Ну не знаю. Может у вас digitalRead возвращает библиотечные константы HIGH и LOW. У меня возвращает булевые 1 и 0. Да true , false я предпочитаю не использовать. Так мне легче отлаживать и плотнее запись кода.
Вот пример как отличать долгое от недолгого в трех градациях. Но здесь будет срабатывать только после того как кнопка будет отжата в зависимости от того сколько была нажата. Если нужно чтоб срабатывало само после удержания кнопки более какого то времени, потребуется доработать. Код (C++): #define BUT_1 8 // пин кнопки void setup() { pinMode(BUT_1, INPUT_PULLUP); pinMode(13, OUTPUT); } void loop() { keyPress_1(); // keyPress_2(); // keyPress_3(); // делаем что то еще } void keyPress_1() { static unsigned long timerInc = 0; static unsigned long timerPress; static unsigned long tPress; static byte butStat[2]; if (timerInc > millis()) return; butStat[0] = butStat[1]; butStat[1] = digitalRead(BUT_1); if (!butStat[1] && butStat[0]) timerPress = millis(); // нажали if (butStat[1] && !butStat[0]) { // отжали tPress = millis() - timerPress; if (tPress > 5000) { digitalWrite(13, HIGH); // более 5 сек } else if (tPress > 2000) { digitalWrite(13, LOW); // более 2 сек, но менее 5 сек } else { // менее 2 сек } } timerInc = millis() + 100; // пауза опроса }