класс титановый велосипед для тактовой кнопки.
- Войдите на сайт для отправки комментариев
Чт, 06/08/2015 - 20:46
класс титановый велосипед для тактовой кнопки.
фильтр дребезга, отслеживание событий: нажатие, отпускание, двойное нажатие(doubleclick), нажато и удерживается в течении определённого времени, отпущено и неактивно в течении определённого времени.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // класс титановый велосипед для тактовой кнопки. // фильтр дребезга, отслеживание событий: нажатие, отпускание, двойное нажатие(doubleclick), нажато и удерживается в течении определённого времени, отпущено и неактивно в течении определённого времени. class BUTTON { public: //================================================================ static const byte bounce_ = 50; // длительность отслеживания дребезга. static const byte doubleclick_ = 200; // длительность отслеживания двойного клика. static const unsigned long timer_ = 5000; // длительность отслеживания неактивности. static const unsigned int retention_ = 2000; // длительность отслеживания нажатия и удержания. //================================================================ boolean click_down; boolean click_up; boolean doubleclick; boolean timer; boolean retention; //================================= unsigned long m; boolean p; boolean b; boolean dc; byte c; boolean t; boolean r; //================================= byte _pb; //================================= BUTTON(byte pb) { _pb = pb; pinMode(_pb, INPUT); digitalWrite(_pb, 1); //==== click_down = 0; click_up = 0; doubleclick = 0; timer = 0; retention = 0; //==== m = millis(); p = digitalRead(_pb); b = 0; dc = 0; c = 0; t = 0; r = 0; //==== } void read() { //======================================================= unsigned long nm = millis(); boolean np = digitalRead(_pb); //================= boolean nb = 0; boolean ndc = 0; boolean nt = 0; boolean nr = 0; //================ click_down = 0; click_up = 0; doubleclick = 0; timer = 0; retention = 0; //================= if (np != p) {p = np; m = nm; } //======================================================= if (nm - m > bounce_) {nb = 1;} if (nm - m > doubleclick_) {ndc = 1;} if (ndc != dc) {dc = ndc; if (dc == 1) {c = 0;}} if (nb != b) {b = nb; if (p == 0 && b == 0) {click_down = 1; ++c; if (c == 2) {c = 0; doubleclick = 1;} } if (p == 1 && b == 1) {click_up = 1;} } //======================================================= if (nm - m > timer_) {nt = 1;} if (nt != t) {t = nt; if (p == 1 && t == 1) {timer = 1;} } //======================================================= if (nm - m > retention_) {nr = 1;} if (nr != r) {r = nr; if (p == 0 && r == 1) {retention = 1;} } //======================================================= } }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~пример, объясняющий отличия работы с кнопкой классическим способом и с использованием предложенного класса:
void loop() { // классический способ использования кнопки. if (считываем логическое состояние пина кнопки == LOW) {что-то делаем при нажатой кнопке} // стоп! а, зачем что-то делается во время каждого цикла loop многократно, если мы нажали на кнопку только один раз? if (считываем логическое состояние пина кнопки == HIGH) {что-то делаем при отпущенной кнопке} // так же непорядок - что-то делается многократно, не смотря на то, что событие отпускания кнопки произошло ровно один раз. // использование кнопки с классом - всё корректно: одно физическое событие генерит одно программное событие. if (нажатие == TRUE) {что-то делаем при нажатой кнопке} if (отпускание == TRUE) {что-то делаем при отпущенной кнопке} if (двойное нажатие == TRUE) {что-то делаем при двойном нажатии} if (удержание == TRUE) {что-то делаем, если нажато и удерживается в течении определённого времени} if (неактивность == TRUE) {что-то делаем, если отпущено и неактивно в течении определённого времени} }пример скетча с использованием класса:
//~~~~~~~~~~~~~~~~~~~~ // здесь код приведённого выше класса class BUTTON {}; //~~~~~~~~~~~~~~~~~~~~ BUTTON BUTTON_01(3); // объявляем объект класса BUTTON кнопку с именем BUTTON_01, подключенную к пину 3. BUTTON BUTTON_02(4); // объявляем объект класса BUTTON кнопку с именем BUTTON_02, подключенную к пину 4. void setup () {} void loop() { BUTTON_01.read(); // обновляем состояние переменных кнопки BUTTON_01. BUTTON_02.read(); // обновляем состояние переменных кнопки BUTTON_02. // работаем с переменными кнопки BUTTON_01. if (BUTTON_01.click_down) {что-то делаем при нажатии} if (BUTTON_01.click_up) {что-то делаем при отпускании} if (BUTTON_01.doubleclick) {что-то делаем при двойном нажатии(doubleclick)} if (BUTTON_01.timer) {что-то делаем, если кнопка отпущена и неактивна в течении определённого времени} if (BUTTON_01.retention) {что-то делаем при нажатии и удержании в течении определённого времени} // работаем с переменными кнопки BUTTON_02. if (BUTTON_02.click_down) {} if (BUTTON_02.click_up) {} if (BUTTON_02.doubleclick) {} if (BUTTON_02.timer) {} if (BUTTON_02.retention) {} }UPD: упустил из вида очевидное - надеюсь, ползателям ясно, что эти переменные можно настраивать по своему хотению:
07//================================================================08staticconstbytebounce_ = 50;// длительность отслеживания дребезга.09staticconstbytedoubleclick_ = 200;// длительность отслеживания двойного клика.10staticconstunsignedlongtimer_ = 5000;// длительность отслеживания неактивности.11staticconstunsignedintretention_ = 2000;// длительность отслеживания нажатия и удержания.12//================================================================Щас 10-ка ставится, потому много не напишу с телефона, но
Имена локальных переменных - мама роди меня обратно. Автор через неделю забудет что это и для чего. Для либы - это смерть. Утрирую, но так и есть, имена переменных должны пониматься без переводчика. Далее, все, что есть в классе имеет доступ public. Блджад, так нельзя. Нужно исходить из мысли, что члены класса не должны меняться снаружи никогда, только методами set и т.п. А щас, что хочу, то и ворочу. Это неправильно.
private - все, что никто не увидит. protected - это увидят только здесь и в порождённое классе. public - увидят все. Типа так
Огромное человеческое спасибо за данный класс. В своем новом проекте(новый контроллер для пивоварни) я полностью использую события данного класса.
Проект на стадии 50% готовности, кому интересно код прилагаю.
Проект разбит на 6 файлов.
// Last Relise - 05/08/2015 Alpha // // Last Relise - 19/08/2015 Betha // // Last Relise - 00/00/0000 Relise // ///////////////////////////////////// // #define ENCODER_DO_NOT_USE_INTERRUPTS #include <SD.h> #include <SPI.h> #include <Wire.h> #include <EEPROM.h> #include <Encoder.h> #include <OneWire.h> #include <LiquidCrystal_I2C.h> #include <DS1307.h> #include <RTClib.h> #include <PID_v1.h> #include <IniFile.h> #include <TimeHelpers.h> #define ONE_WIRE_BUS 7 // Шина датчика температуры #define SD_SELECT 4 // Шина CS SD карты #define ButtonEnc 8 // Кнопка энкодора #define TEN1 13 // Порт шины нагревательного элемента 1 #define UPGRADE 1000 // Частота обновления главного экрана в милисикундах //`````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` byte type_s; // Создание переменной типа датчика измерения температуры byte data[12]; // Создание переменной данных датчика температуры byte addr[8]; // Создание переменной адреса датчика температуры // long Pos; // Создание переменной нового положения энкодера long position; // Создание переменной текущего положения энкодера long NeoTime = 0; // Создание переменной хранения значения unix времени конца выполнения программы // const size_t bufferLen = 30; // Создания константы размера буфера строк читаемых из ini файла // char buffer[bufferLen]; // Создания буфера строк читаемых из ini файла // double Setpoint; // Создание переменной устанавливаемой температуры (и передача данных из памяти) double Input; // Создание переменной входящих данных в ПИД регулятор double Output; // Создание переменной исходящих данных из ПИД регулятора double consKp = 5; // Создание переменных констант ПИД регулятора double consKi = 75; // Создание переменных констант ПИД регулятора double consKd = 1; // Создание переменных констант ПИД регулятора // String FileiniNAMEAn; String FileiniNAME; // 0 1 2 3 4 5 6 7 8 9 const String Prog[10] = {"PROG_1", "PROG_2", "PROG_3", "PROG_4", "PROG_5", "PROG_6", "PROG_7", "PROG_8", "PROG_9", "PROG_10"}; int Pat[10][3] = {{20,0,0}, {20,0,0}, {20,0,0}, {20,0,0}, {20,0,0}, {20,0,0}, {20,0,0}, {20,0,0}, {20,0,0}, {20,0,0} }; int prog = 0; int mem1 = 0; int mem2 = 0; int mem3 = 0; int Nasos_Start = 30; int Nasos_Stop = 80; int PID_SPEED = 3; int _HR = 0; // Создание переменной хранения значения часов int _MI = 0; // Создание переменной хранения значения минут int _SE = 0; // Создание переменной хранения значения секунд int A_H = 0; // Создание переменной хранения значения часов при изменении времени int A_M = 0; // Создание переменной хранения значения минут при изменении времени int maxMenu = 40; // Отсчет от 0 (количество пунктов -1). int curMenu = 0; // Значение текущего пункта меню. int Moschnost; // Создание переменной мощности нагревательного элемента int T_Upr = 0; // Режим работы. int P_Numb = 0; // Создание переменной определения пункта масива програмируемых периодов (общего назначения) int R_Numb = 0; // Создание переменной определения пункта масива програмируемых периодов (отрисовка меню) long unixt; // Создание переменной хранения текущего unix времени long Sec; // Создание переменной временивыполнения программы // float Mic1 = 0; // Переменные измерения производительности float Mic2 = 0; // Переменные измерения производительности float celsius; // Создание переменной значения измерений датчика температуры // boolean StartTime = 0; // Создание переменной начала работы по заданному переоду (Р1 - Р9) boolean Rabota = 1; // Создание переменной дополнительная переменная управления переключением периодов (Р1 - Р9) boolean Alarm = 0; // Создание переменной значения сигнализации boolean chgTemp = 0; // Создание переменной флага изменения значения температуры boolean flag = 0; // Создание переменной флага управления пьезо излучателем boolean rasTempBol = 0; // Создание переменной флага необходимости расчета времени boolean tr_menu = false; // Признак входа в меню настройки. boolean dir = false; // Признак переключения между вводом данных и листанием меню. boolean keyPres = false; // Признак исплнния клика по кнопке. boolean STATUS = false; // Состояние предохранителя (программа включена/выключенна) boolean Udate = true; // Обновление основного экрана boolean SD_stat = false; // Определяет наличие или отсутствие SD карты. //`````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` RTC_DS1307 rtc; // Инициализация Часов точного времени OneWire ds(ONE_WIRE_BUS); // Инициализация шины датчика измерения температуры LiquidCrystal_I2C lcd(0x27, 20, 4); // Инициализация дисплея DateTime now; // Создания объекта Часов точного времени PID myPID(&Input, &Output, &Setpoint, consKp, consKi, consKd, DIRECT); // Инициализация ПИД регулятора Encoder myEnc(2, 3); File root; File entry; class BUTTON { public: //================================================================ static const byte bounce_ = 50; // длительность отслеживания дребезга. static const byte doubleclick_ = 200; // длительность отслеживания двойного клика. static const unsigned int retention_ = 2000; // длительность отслеживания нажатия и удержания. static const unsigned long timer_ = 60000; // длительность отслеживания неактивности. //================================================================ boolean click_down; boolean click_up; boolean doubleclick; boolean timer; boolean retention; //================================= unsigned long m; boolean p; boolean b; boolean dc; byte c; boolean t; boolean r; //================================= byte _pb; //================================= BUTTON(byte pb) { _pb = pb; pinMode(_pb, INPUT); digitalWrite(_pb, 1); //==== click_down = 0; click_up = 0; doubleclick = 0; timer = 0; retention = 0; //==== m = millis(); p = digitalRead(_pb); b = 0; dc = 0; c = 0; t = 0; r = 0; //==== } void read() { //======================================================= unsigned long nm = millis(); boolean np = digitalRead(_pb); //================= boolean nb = 0; boolean ndc = 0; boolean nt = 0; boolean nr = 0; //================ click_down = 0; click_up = 0; doubleclick = 0; timer = 0; retention = 0; //================= if (np != p) {p = np; m = nm; } //======================================================= if (nm - m > bounce_) {nb = 1;} if (nm - m > doubleclick_) {ndc = 1;} if (ndc != dc) {dc = ndc; if (dc == 1) {c = 0;}} if (nb != b) {b = nb; if (p == 0 && b == 0) {click_down = 1; ++c; if (c == 2) {c = 0; doubleclick = 1;} } if (p == 1 && b == 1) {click_up = 1;} } //======================================================= if (nm - m > timer_) {nt = 1;} if (nt != t) {t = nt; if (p == 1 && t == 1) {timer = 1;}} //======================================================= if (nm - m > retention_) {nr = 1;} if (nr != r) {r = nr; if (p == 0 && r == 1) {retention = 1;}} //======================================================= }}; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ BUTTON BUTTON_01(ButtonEnc); /////////////////////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ void clearLine(int line){if (line <= 3 && line >= 0){lcd.setCursor(0, line); lcd.print(" "); lcd.setCursor(0, line);} else {lcd.clear();}} void Enc_Zero(int ps = 0){ if (ps == 0) {myEnc.write(0);} else {ps = ps*4; myEnc.write(ps);} position = Pos;} void EnterCHG(){if (tr_menu == true) {if (dir == true) {Enc_Zero(curMenu); menu(curMenu);} else {lcd.setCursor(13, 0); lcd.print("Chenge"); Enc_Zero(0); ChgData();} dir = !dir;}} /////////////////////////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ int s; // удалить временная парковочная переменная void setup() { Serial.begin(115200); // SavePAT(); LoadPAT(); rtc.begin(); lcd.init(); lcd.backlight(); pinMode(TEN1, OUTPUT); pinMode(ButtonEnc, INPUT); digitalWrite(ButtonEnc, HIGH); myPID.SetMode(AUTOMATIC); delay(500); if (!SD.begin(SD_SELECT)) {lcd.setCursor(0, 0); lcd.print("SD init - failed!");} // Тестирование SD карты (карта отсутствует) else {lcd.setCursor(0, 0); lcd.print("SD init - ok"); root = SD.open("/"); root.rewindDirectory(); SD_stat = true;} // Тестирование SD карты (карта на месте, исправна) delay(1000); lcd.setCursor(0, 1); lcd.print("CPU init - ok"); // Приятный красивый мультик (несёт только эстетический хорактер) delay(1000); lcd.setCursor(0, 2); lcd.print("SYS init - ok"); // Приятный красивый мультик (несёт только эстетический хорактер) delay(1000); lcd.setCursor(0, 3); lcd.print("PID init - ok"); // Приятный красивый мультик (несёт только эстетический хорактер) delay(2000); lcd.clear(); } void loop(){ Mic1 = millis(); now = rtc.now(); _HR = now.hour(); _MI = now.minute(); _SE = now.second(); getTemp(); Input = celsius; // Конвертация типов переменных на вход ПИД регулятора. DO_EVERY(PID_SPEED,{ myPID.Compute(); }); Pos = myEnc.read() / 4; Moschnost = map(Output, 0, 255, 0, 100); if (STATUS) {analogWrite(TEN1, Output);} else {analogWrite(TEN1, 0); Moschnost = 0;} //-------------------------------------------------------- BUTTON_01.read(); if (BUTTON_01.timer) {lcd.noBacklight(); tr_menu = false; lcd.noBlink(); lcd.clear(); Enc_Zero(0); keyPres = false;} if (BUTTON_01.click_down) {keyPres = true; lcd.backlight();} if (BUTTON_01.retention) {lcd.backlight(); tr_menu = !tr_menu; if (tr_menu == true) {Enc_Zero(0); menu(0); lcd.blink();} else {lcd.noBlink(); lcd.clear(); Enc_Zero(0); SavePAT();} keyPres = false;} if (BUTTON_01.doubleclick) {if (tr_menu == false && position == 1){STATUS = true; Enc_Zero(0);} else {STATUS = false;} Udate = true;} if (BUTTON_01.click_up) {if (keyPres == true) {EnterCHG();} keyPres = false;} //-------------------------------------------------------- if (tr_menu == false){ DO_EVERY(UPGRADE,{Udate = true;}); menu(99); } if (Pos != position) {position = Pos; lcd.backlight(); if (tr_menu == false) {if (position > 1) {Enc_Zero(0);} else if (position < 0) {Enc_Zero(1);} Print_ctrl_main();} if (tr_menu == true && dir == false) {if (position > maxMenu) {Enc_Zero(0);} else if (position < 0) {Enc_Zero(maxMenu);} menu(position);} if (tr_menu == true && dir == true) {ChgData();} } //`````````````````````````````````````````` Mic2 = 1000 / (millis() - Mic1); // Вычисление количества операций(циклов) в секунду Serial.print(" CPU-"); Serial.print(Mic2); Serial.print("Lps"); Serial.print(" Status-"); Serial.print(STATUS); Serial.print(" Output-"); Serial.println(Output); //`````````````````````````````````````````` } // end Loopvoid ChgData(){ if (curMenu == 0) {if (position >= 0 && position <= 3) {s = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();} if (curMenu == 1) {if (position >= 0 && position <= 100) {s = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();} if (curMenu == 2) {if (position >= 0 && position <= 100) {s = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} s = position; lcd.setCursor(0, 3); lcd.blink();} if (curMenu == 3) {lcd.setCursor(6, 1); lcd.print(" "); CHGFile(); lcd.setCursor(6, 1); lcd.print(FileiniNAME); lcd.setCursor(0, 1); lcd.blink();} if (curMenu == 4) {ReadINI(); lcd.setCursor(8, 3); lcd.print("ok"); lcd.setCursor(0, 3); lcd.blink();} if (curMenu == 5) {if (position >= 1 && position <= 100) {PID_SPEED = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();} if (curMenu == 6) {if (position >= 0 && position <= 100) {consKi = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();} if (curMenu == 7) {if (position >= 0 && position <= 100) {Setpoint = position; lcd.setCursor(12, 3); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 3); lcd.blink();} if (curMenu == 8) {if (position >= 0 && position <= 24) {A_H = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();} if (curMenu == 9) {if (position >= 0 && position <= 59) {A_M = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();} if (curMenu == 10){rtc.adjust(DateTime(2015, 8, 19, A_H, A_M, 0)); lcd.setCursor(12, 3); lcd.print("ok"); lcd.setCursor(0, 3); lcd.blink();} if (curMenu == 11) {if (position >= 0 && position <= 100) {Pat[0][0] = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();} if (curMenu == 12) {if (position >= 0 && position <= 32000) {Pat[0][1] = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();} if (curMenu == 13) {if (position >= 0 && position <= 1) {Pat[0][2] = position; lcd.setCursor(12, 3); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 3); lcd.blink();} if (curMenu == 14) {if (position >= 0 && position <= 100) {Pat[1][0] = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();} if (curMenu == 15) {if (position >= 0 && position <= 32000) {Pat[1][1] = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();} if (curMenu == 16) {if (position >= 0 && position <= 1) {Pat[1][2] = position; lcd.setCursor(12, 3); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 3); lcd.blink();} if (curMenu == 17) {if (position >= 0 && position <= 100) {Pat[2][0] = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();} if (curMenu == 18) {if (position >= 0 && position <= 32000) {Pat[2][1] = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();} if (curMenu == 19) {if (position >= 0 && position <= 1) {Pat[2][2] = position; lcd.setCursor(12, 3); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 3); lcd.blink();} if (curMenu == 20) {if (position >= 0 && position <= 100) {Pat[3][0] = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();} if (curMenu == 21) {if (position >= 0 && position <= 32000) {Pat[3][1] = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();} if (curMenu == 22) {if (position >= 0 && position <= 1) {Pat[3][2] = position; lcd.setCursor(12, 3); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 3); lcd.blink();} if (curMenu == 23) {if (position >= 0 && position <= 100) {Pat[4][0] = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();} if (curMenu == 24) {if (position >= 0 && position <= 32000) {Pat[4][1] = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();} if (curMenu == 25) {if (position >= 0 && position <= 1) {Pat[4][2] = position; lcd.setCursor(12, 3); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 3); lcd.blink();} if (curMenu == 26) {if (position >= 0 && position <= 100) {Pat[5][0] = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();} if (curMenu == 27) {if (position >= 0 && position <= 32000) {Pat[5][1] = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();} if (curMenu == 28) {if (position >= 0 && position <= 1) {Pat[5][2] = position; lcd.setCursor(12, 3); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 3); lcd.blink();} if (curMenu == 29) {if (position >= 0 && position <= 100) {Pat[6][0] = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();} if (curMenu == 30) {if (position >= 0 && position <= 32000) {Pat[6][1] = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();} if (curMenu == 31) {if (position >= 0 && position <= 1) {Pat[6][2] = position; lcd.setCursor(12, 3); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 3); lcd.blink();} if (curMenu == 32) {if (position >= 0 && position <= 100) {Pat[7][0] = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();} if (curMenu == 33) {if (position >= 0 && position <= 32000) {Pat[7][1] = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();} if (curMenu == 34) {if (position >= 0 && position <= 1) {Pat[7][2] = position; lcd.setCursor(12, 3); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 3); lcd.blink();} if (curMenu == 35) {if (position >= 0 && position <= 100) {Pat[8][0] = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();} if (curMenu == 36) {if (position >= 0 && position <= 32000) {Pat[8][1] = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();} if (curMenu == 37) {if (position >= 0 && position <= 1) {Pat[8][2] = position; lcd.setCursor(12, 3); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 3); lcd.blink();} if (curMenu == 38) {if (position >= 0 && position <= 100) {Pat[9][0] = position; lcd.setCursor(12, 1); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 1); lcd.blink();} if (curMenu == 39) {if (position >= 0 && position <= 32000) {Pat[9][1] = position; lcd.setCursor(12, 2); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 2); lcd.blink();} if (curMenu == 40) {if (position >= 0 && position <= 1) {Pat[9][2] = position; lcd.setCursor(12, 3); lcd.print(position); lcd.print(" ");} else {Enc_Zero(0);} lcd.setCursor(0, 3); lcd.blink();} }void CHGFile(){ entry = root.openNextFile(); if (!entry) { root.rewindDirectory(); } FileiniNAMEAn = entry.name(); if (FileiniNAMEAn == "" or FileiniNAMEAn == "SYSTEM~1") {entry = root.openNextFile();} else {FileiniNAME = entry.name();}} void ReadINI(){ if (SD_stat){ char Str2[FileiniNAME.length()+1]; FileiniNAME.toCharArray(Str2, FileiniNAME.length()+1); IniFile ini(Str2); if (!ini.open()) {clearLine(0); lcd.print("Ini file does not exist"); while (1);} if (!ini.validate(buffer, bufferLen)) {clearLine(0); lcd.print("ini file "); lcd.print(ini.getFilename()); lcd.print(" not valid"); while (1);} //-------------------------------------------------------------------- if (ini.open()) { /* clearLine(0); lcd.print("Load: "); lcd.print(ini.getFilename()); */ } if (ini.getValue("NAME", "NAME", buffer, bufferLen)) {if (curMenu == 4) {clearLine(2); lcd.setCursor(1, 2); lcd.print(buffer);}} //else {clearLine(0); lcd.print("Default Error file");} if (ini.getValue("PID", "consKp", buffer, bufferLen)) {consKp = String(buffer).toInt();} if (ini.getValue("PID", "consKi", buffer, bufferLen)) {consKi = String(buffer).toInt();} if (ini.getValue("PID", "consKd", buffer, bufferLen)) {consKd = String(buffer).toInt();} if (ini.getValue("PID", "PID_SPEED", buffer, bufferLen)) {PID_SPEED = String(buffer).toInt();} if (ini.getValue("NASOS", "start", buffer, bufferLen)) {Nasos_Start = String(buffer).toInt();} if (ini.getValue("NASOS", "stop", buffer, bufferLen)) {Nasos_Stop = String(buffer).toInt();} for (int mesMas=0; mesMas <= 9; mesMas++){ char Str1[Prog[mesMas].length()+1]; Prog[mesMas].toCharArray(Str1, Prog[mesMas].length()+1); if (ini.getValue(Str1, "P_Temp", buffer, bufferLen)) {Pat[mesMas][0] = String(buffer).toInt();} if (ini.getValue(Str1, "P_Time", buffer, bufferLen)) {Pat[mesMas][1] = String(buffer).toInt();} if (ini.getValue(Str1, "P_Alar", buffer, bufferLen)) {Pat[mesMas][2] = String(buffer).toInt();} } ini.close(); entry.close(); //-------------------------------------------------------------------- }}void LoadPAT(){ INI_pat_mem(); for (int pr=50; pr <= 59; pr++){ prog = pr - 50; mem1 = pr; mem2 = pr + 10; mem3 = pr + 20; Pat[prog][0] = EEPROM.read(mem1); Pat[prog][1] = EEPROM.read(mem2); Pat[prog][2] = EEPROM.read(mem3); } T_Upr = EEPROM.read(111); consKi = EEPROM.read(112); PID_SPEED = EEPROM.read(113); myPID.SetTunings(consKp, consKi, consKd); } void SavePAT(){ INI_pat_mem(); for (int pr=50; pr <= 59; pr++){ prog = pr - 50; mem1 = pr; mem2 = pr + 10; mem3 = pr + 20; EEPROM.write(mem1, Pat[prog][0]); EEPROM.write(mem2, Pat[prog][1]); EEPROM.write(mem3, Pat[prog][2]); } if (EEPROM.read(111) != T_Upr) { if (T_Upr != 3){ EEPROM.write(111, T_Upr); } } // Сохранение значения режима работы if (EEPROM.read(112) != consKi) { EEPROM.write(112, consKi); myPID.SetTunings(consKp, consKi, consKd); } // Сохранение значения режима consKi PID регулятора if (EEPROM.read(113) != PID_SPEED) { EEPROM.write(113, PID_SPEED); myPID.SetTunings(consKp, consKi, consKd); } // Сохранение значения режима SPEED PID регулятора } void INI_pat_mem(){ prog = 0; mem1 = 0; mem2 = 0; mem3 = 0; }void getTemp() { ds.reset(); ds.select(addr); ds.write(0x44, 1); ds.reset(); ds.select(addr); ds.write(0xBE); for ( int i = 0; i < 9; i++) {data[i] = ds.read();} int16_t raw = (data[1] << 8) | data[0]; if (type_s) { raw = raw << 3; if (data[7] == 0x10) {raw = (raw & 0xFFF0) + 12 - data[6];} } else { byte cfg = (data[4] & 0x60); if (cfg == 0x00) raw = raw & ~7; else if (cfg == 0x20) raw = raw & ~3; else if (cfg == 0x40) raw = raw & ~1; } celsius = (float)raw / 16.0; return; }void menu(int lvl){ if (lvl == 0 || lvl == 1 || lvl == 2){ lcd.clear(); curMenu = lvl; lcd.setCursor(0, 0); lcd.print(" MENU - 0 "); lcd.setCursor(0, 1); lcd.print(" -"); lcd.setCursor(12, 1); lcd.print(""); lcd.setCursor(0, 2); lcd.print(" -"); lcd.setCursor(12, 2); lcd.print(""); lcd.setCursor(0, 3); lcd.print(" -"); lcd.setCursor(12, 3); lcd.print(""); switch (lvl){case 0:lcd.setCursor(0, 1); lcd.blink(); break; case 1:lcd.setCursor(0, 2); lcd.blink(); break; case 2:lcd.setCursor(0, 3); lcd.blink(); break;} } if (lvl == 3 || lvl == 4){ lcd.clear(); curMenu = lvl; lcd.setCursor(0, 0); lcd.print(" MENU - 1 "); lcd.setCursor(0, 1); lcd.print(" File:"); lcd.print(FileiniNAME); if (!SD_stat) {lcd.setCursor(0, 2); lcd.print(" SD init - failed!");} lcd.setCursor(0, 3); lcd.print(" Load"); switch (lvl){case 3:lcd.setCursor(0, 1); lcd.blink(); break; case 4:lcd.setCursor(0, 3); lcd.blink(); break;} } if (lvl == 5 || lvl == 6 || lvl == 7 ){ lcd.clear(); curMenu = lvl; lcd.setCursor(0, 0); lcd.print(" MENU - 2 "); lcd.setCursor(0, 1); lcd.print(" PID_SPEED "); lcd.setCursor(12, 1); lcd.print(PID_SPEED); lcd.setCursor(0, 2); lcd.print(" consKi "); lcd.setCursor(12, 2); lcd.print(consKi); lcd.setCursor(0, 3); lcd.print(" Setpoint "); lcd.setCursor(12, 3); lcd.print(Setpoint); switch (lvl){case 5:lcd.setCursor(0, 1); lcd.blink(); break; case 6:lcd.setCursor(0, 2); lcd.blink(); break; case 7:lcd.setCursor(0, 3); lcd.blink(); break;} } if (lvl == 8 || lvl == 9 || lvl == 10 ){ lcd.clear(); curMenu = lvl; lcd.setCursor(0, 0); lcd.print(" MENU - 3 "); lcd.setCursor(0, 1); lcd.print(" hour"); lcd.setCursor(12, 1); lcd.print(A_H); lcd.setCursor(0, 2); lcd.print(" minute"); lcd.setCursor(12, 2); lcd.print(A_M); lcd.setCursor(0, 3); lcd.print(" set clock"); switch (lvl){case 8: lcd.setCursor(0, 1); lcd.blink(); break; case 9: lcd.setCursor(0, 2); lcd.blink(); break; case 10:lcd.setCursor(0, 3); lcd.blink(); break;} } //``````````````````````````````````````````````````````````````````````````````````````````` if (lvl == 11 || lvl == 12 || lvl == 13){ lcd.clear(); curMenu = lvl; lcd.setCursor(0, 0); lcd.print(" MENU - 4.0 "); lcd.setCursor(0, 1); lcd.print(" P_Temp "); lcd.setCursor(12, 1); lcd.print(Pat[0][0]); lcd.setCursor(0, 2); lcd.print(" P_Time "); lcd.setCursor(12, 2); lcd.print(Pat[0][1]); lcd.setCursor(0, 3); lcd.print(" P_Alar "); lcd.setCursor(12, 3); lcd.print(Pat[0][2]); switch (lvl){case 11:lcd.setCursor(0, 1); lcd.blink(); break; case 12:lcd.setCursor(0, 2); lcd.blink(); break; case 13:lcd.setCursor(0, 3); lcd.blink(); break;} } if (lvl == 14 || lvl == 15 || lvl == 16){ lcd.clear(); curMenu = lvl; lcd.setCursor(0, 0); lcd.print(" MENU - 4.1 "); lcd.setCursor(0, 1); lcd.print(" P_Temp "); lcd.setCursor(12, 1); lcd.print(Pat[1][0]); lcd.setCursor(0, 2); lcd.print(" P_Time "); lcd.setCursor(12, 2); lcd.print(Pat[1][1]); lcd.setCursor(0, 3); lcd.print(" P_Alar "); lcd.setCursor(12, 3); lcd.print(Pat[1][2]); switch (lvl){case 14:lcd.setCursor(0, 1); lcd.blink(); break; case 15:lcd.setCursor(0, 2); lcd.blink(); break; case 16:lcd.setCursor(0, 3); lcd.blink(); break;} } if (lvl == 17 || lvl == 18 || lvl == 19){ lcd.clear(); curMenu = lvl; lcd.setCursor(0, 0); lcd.print(" MENU - 4.2 "); lcd.setCursor(0, 1); lcd.print(" P_Temp "); lcd.setCursor(12, 1); lcd.print(Pat[2][0]); lcd.setCursor(0, 2); lcd.print(" P_Time "); lcd.setCursor(12, 2); lcd.print(Pat[2][1]); lcd.setCursor(0, 3); lcd.print(" P_Alar "); lcd.setCursor(12, 3); lcd.print(Pat[2][2]); switch (lvl){case 17:lcd.setCursor(0, 1); lcd.blink(); break; case 18:lcd.setCursor(0, 2); lcd.blink(); break; case 19:lcd.setCursor(0, 3); lcd.blink(); break;} } if (lvl == 20 || lvl == 21 || lvl == 22){ lcd.clear(); curMenu = lvl; lcd.setCursor(0, 0); lcd.print(" MENU - 4.3 "); lcd.setCursor(0, 1); lcd.print(" P_Temp "); lcd.setCursor(12, 1); lcd.print(Pat[3][0]); lcd.setCursor(0, 2); lcd.print(" P_Time "); lcd.setCursor(12, 2); lcd.print(Pat[3][1]); lcd.setCursor(0, 3); lcd.print(" P_Alar "); lcd.setCursor(12, 3); lcd.print(Pat[3][2]); switch (lvl){case 20:lcd.setCursor(0, 1); lcd.blink(); break; case 21:lcd.setCursor(0, 2); lcd.blink(); break; case 22:lcd.setCursor(0, 3); lcd.blink(); break;} } if (lvl == 23 || lvl == 24 || lvl == 25){ lcd.clear(); curMenu = lvl; lcd.setCursor(0, 0); lcd.print(" MENU - 4.4 "); lcd.setCursor(0, 1); lcd.print(" P_Temp "); lcd.setCursor(12, 1); lcd.print(Pat[4][0]); lcd.setCursor(0, 2); lcd.print(" P_Time "); lcd.setCursor(12, 2); lcd.print(Pat[4][1]); lcd.setCursor(0, 3); lcd.print(" P_Alar "); lcd.setCursor(12, 3); lcd.print(Pat[4][2]); switch (lvl){case 23:lcd.setCursor(0, 1); lcd.blink(); break; case 24:lcd.setCursor(0, 2); lcd.blink(); break; case 25:lcd.setCursor(0, 3); lcd.blink(); break;} } if (lvl == 26 || lvl == 27 || lvl == 28){ lcd.clear(); curMenu = lvl; lcd.setCursor(0, 0); lcd.print(" MENU - 4.5 "); lcd.setCursor(0, 1); lcd.print(" P_Temp "); lcd.setCursor(12, 1); lcd.print(Pat[5][0]); lcd.setCursor(0, 2); lcd.print(" P_Time "); lcd.setCursor(12, 2); lcd.print(Pat[5][1]); lcd.setCursor(0, 3); lcd.print(" P_Alar "); lcd.setCursor(12, 3); lcd.print(Pat[5][2]); switch (lvl){case 26:lcd.setCursor(0, 1); lcd.blink(); break; case 27:lcd.setCursor(0, 2); lcd.blink(); break; case 28:lcd.setCursor(0, 3); lcd.blink(); break;} } if (lvl == 29 || lvl == 30 || lvl == 31){ lcd.clear(); curMenu = lvl; lcd.setCursor(0, 0); lcd.print(" MENU - 4.6 "); lcd.setCursor(0, 1); lcd.print(" P_Temp "); lcd.setCursor(12, 1); lcd.print(Pat[6][0]); lcd.setCursor(0, 2); lcd.print(" P_Time "); lcd.setCursor(12, 2); lcd.print(Pat[6][1]); lcd.setCursor(0, 3); lcd.print(" P_Alar "); lcd.setCursor(12, 3); lcd.print(Pat[6][2]); switch (lvl){case 29:lcd.setCursor(0, 1); lcd.blink(); break; case 30:lcd.setCursor(0, 2); lcd.blink(); break; case 31:lcd.setCursor(0, 3); lcd.blink(); break;} } if (lvl == 32 || lvl == 33 || lvl == 34){ lcd.clear(); curMenu = lvl; lcd.setCursor(0, 0); lcd.print(" MENU - 4.7 "); lcd.setCursor(0, 1); lcd.print(" P_Temp "); lcd.setCursor(12, 1); lcd.print(Pat[7][0]); lcd.setCursor(0, 2); lcd.print(" P_Time "); lcd.setCursor(12, 2); lcd.print(Pat[7][1]); lcd.setCursor(0, 3); lcd.print(" P_Alar "); lcd.setCursor(12, 3); lcd.print(Pat[7][2]); switch (lvl){case 32:lcd.setCursor(0, 1); lcd.blink(); break; case 33:lcd.setCursor(0, 2); lcd.blink(); break; case 34:lcd.setCursor(0, 3); lcd.blink(); break;} } if (lvl == 35 || lvl == 36 || lvl == 37){ lcd.clear(); curMenu = lvl; lcd.setCursor(0, 0); lcd.print(" MENU - 4.8 "); lcd.setCursor(0, 1); lcd.print(" P_Temp "); lcd.setCursor(12, 1); lcd.print(Pat[8][0]); lcd.setCursor(0, 2); lcd.print(" P_Time "); lcd.setCursor(12, 2); lcd.print(Pat[8][1]); lcd.setCursor(0, 3); lcd.print(" P_Alar "); lcd.setCursor(12, 3); lcd.print(Pat[8][2]); switch (lvl){case 35:lcd.setCursor(0, 1); lcd.blink(); break; case 36:lcd.setCursor(0, 2); lcd.blink(); break; case 37:lcd.setCursor(0, 3); lcd.blink(); break;} } if (lvl == 38 || lvl == 39 || lvl == 40){ lcd.clear(); curMenu = lvl; lcd.setCursor(0, 0); lcd.print(" MENU - 4.9 "); lcd.setCursor(0, 1); lcd.print(" P_Temp "); lcd.setCursor(12, 1); lcd.print(Pat[9][0]); lcd.setCursor(0, 2); lcd.print(" P_Time "); lcd.setCursor(12, 2); lcd.print(Pat[9][1]); lcd.setCursor(0, 3); lcd.print(" P_Alar "); lcd.setCursor(12, 3); lcd.print(Pat[9][2]); switch (lvl){case 38:lcd.setCursor(0, 1); lcd.blink(); break; case 39:lcd.setCursor(0, 2); lcd.blink(); break; case 40:lcd.setCursor(0, 3); lcd.blink(); break;} } //``````````````````````````````````````````````````````````````````````````````````````````` if (lvl == 99){ if (Udate){ Udate = false; lcd.setCursor(0, 0); lcd.print("T.ust "); lcd.print(Setpoint); if (STATUS) {lcd.setCursor(17, 0); lcd.print("RUN");} else {lcd.setCursor(17, 0); lcd.print("OFF");} lcd.setCursor(0, 1); lcd.print("T.zid "); lcd.print(Input); lcd.setCursor(0, 2); lcd.print("P.ten "); if (Moschnost <= 100) {lcd.setCursor(6, 2);lcd.print(Moschnost); lcd.print("% ");} if (Moschnost < 10) {lcd.setCursor(6, 2);lcd.print(Moschnost); lcd.print("% ");} Print_ctrl_main(); lcd.setCursor(0, 3); if (_HR < 10) {lcd.print("0"); lcd.print(_HR);} else {lcd.print(_HR);} lcd.print(":"); if (_MI < 10) {lcd.print("0"); lcd.print(_MI);} else {lcd.print(_MI);} lcd.print(":"); if (_SE < 10) {lcd.print("0"); lcd.print(_SE);} else {lcd.print(_SE);} } } } void Print_ctrl_main(){ if (tr_menu == false && position == 0) {lcd.setCursor(14, 1); lcd.print(">>STOP"); lcd.setCursor(14, 2); lcd.print(" WORK");} if (tr_menu == false && position == 1) {lcd.setCursor(14, 1); lcd.print(" STOP"); lcd.setCursor(14, 2); lcd.print(">>WORK");} }попробовал и я велосипед
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // класс титановый велосипед для тактовой кнопки. // фильтр дребезга, отслеживание событий: нажатие, отпускание, двойное нажатие(doubleclick), нажато и удерживается в течении определённого времени, отпущено и неактивно в течении определённого времени. class BUTTON { public: //=================================================================================================== static const byte bounce_ = 50; // длительность отслеживания дребезга. static const byte doubleclick_ = 200; // длительность отслеживания двойного клика. static const unsigned long timer_ = 10000; // длительность отслеживания неактивности. static const unsigned int retention_ = 1000; // длительность отслеживания нажатия и удержания. //=================================================================================================== boolean click_down; boolean click_up; boolean doubleclick; boolean timer; boolean retention; //================================= unsigned long m; boolean p; boolean b; boolean dc; byte c; boolean t; boolean r; //================================= byte _pb; //================================= BUTTON(byte pb) { _pb = pb; pinMode(_pb, INPUT); digitalWrite(_pb, 1); //==== click_down = 0; click_up = 0; doubleclick = 0; timer = 0; retention = 0; //==== m = millis(); p = digitalRead(_pb); b = 0; dc = 0; c = 0; t = 0; r = 0; //==== } void read() { //======================================================= unsigned long nm = millis(); boolean np = digitalRead(_pb); //================= boolean nb = 0; boolean ndc = 0; boolean nt = 0; boolean nr = 0; //================ click_down = 0; click_up = 0; doubleclick = 0; timer = 0; retention = 0; //================= if (np != p) {p = np; m = nm; } //======================================================= if (nm - m > bounce_) {nb = 1;} if (nm - m > doubleclick_) {ndc = 1;} if (ndc != dc) {dc = ndc; if (dc == 1) {c = 0;}} if (nb != b) {b = nb; if (p == 0 && b == 0) {click_down = 1; ++c; if (c == 2) {c = 0; doubleclick = 1;} } if (p == 1 && b == 1) {click_up = 1;} } //======================================================= if (nm - m > timer_) {nt = 1;} if (nt != t) {t = nt; if (p == 1 && t == 1) {timer = 1;} } //======================================================= if (nm - m > retention_) {nr = 1;} if (nr != r) {r = nr; if (p == 0 && r == 1) {retention = 1;} } //======================================================= } }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //////////////////////// BUTTON BUTTON_01(3); //////////////////////// void setup() { ///// pinMode(16, OUTPUT); digitalWrite(16, 1); pinMode(14, OUTPUT); digitalWrite(14, 1); pinMode(15, OUTPUT); digitalWrite(15, 1); pinMode(13, OUTPUT); } void loop() { if (BUTTON_01.click_down) {digitalWrite(16, !digitalRead(16));} if (BUTTON_01.click_up) {} if (BUTTON_01.doubleclick) {digitalWrite(14, !digitalRead(14));} if (BUTTON_01.timer) {} if (BUTTON_01.retention) {digitalWrite(15, !digitalRead(15));} BUTTON_01.read(); }при двойном клике или удержании кнопки одиночное нажатие всё равно срабатывает, что иногда не приемлемо
при двойном клике или удержании кнопки одиночное нажатие всё равно срабатывает, что иногда не приемлемо
в версии Дуино ИДЕ arduino-1.6.6 класс можно подключить как библиотеку:
схема подключения кнопки некоторым ползателям класса оказалась неочевидной - прилагаю расово правильную схему
если эта схема расово правильная, то почему большинство схем в гугле не имеют сопротивления R1? На что оно влияет?
Резистор ограничивает ток через контакты кнопки при её нажимании.
Смотреть про второй закон коммутации:
https://ru.wikipedia.org/wiki/%D0%9F%D0%B5%D1%80%D0%B5%D1%85%D0%BE%D0%B4%D0%BD%D1%8B%D0%B5_%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81%D1%8B_%D0%B2_%D1%8D%D0%BB%D0%B5%D0%BA%D1%82%D1%80%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D1%85_%D1%86%D0%B5%D0%BF%D1%8F%D1%85
Хотя при 0.1 без резистора будет и не смертельно для кнопки...... какое-то время......
Поставьте для "пробы" 2200.0 - могут и контакты "свариться"
если эта схема расово правильная, то почему большинство схем в гугле не имеют сопротивления R1? На что оно влияет?
*большинство схем в гугле имеют сиськи.
R1 , если:
1. если ты по запарке что-то не то зальёшь в дуино и пин у тебя окажется оутпут.
2. см. #128
отлично. Беру на вооружение.
и еще один дурацкий вопрос - а конденсатор зачем? от скачков напряжения?
он забирает на себя дребезг контактов. Кое-что, конечно, прорывается, но для МК все же легче.
алгоритм борьбы с дребезгом, используемый в класс титановый велосипед для тактовой кнопки.
в версии Дуино ИДЕ arduino-1.6.6 класс можно подключить как библиотеку:
*работает только в версии arduino-1.6.7
что бы работало в версиях младше вплоть до Arduino 1.0, нужно в код #1 добавить первой строкой
**проверяем.
Попробовал класс, понравилось. Но я так и не догнал как сделать повторяющиеся нажатия?
Но я так и не догнал как сделать повторяющиеся нажатия?
после нажатия кнопки, повторяешь действие.
а можно сделать, чтобы при даблклике не выполнялось действие одного клика (т.е. поставить небольшую задержку одиночного нажатия, и если обнаружено двойное нажатие, то не выполнять действие по одиночному нажатию)?
а можно сделать, чтобы при даблклике не выполнялось действие одного клика (т.е. поставить небольшую задержку одиночного нажатия, и если обнаружено двойное нажатие, то не выполнять действие по одиночному нажатию)?
а, можно у тебя узнать алгоритм предсказания действий пользователя кнопки и попросить тебя прочитать топик полностью или начиная отсюда #100 ?
Только вот одно не понятно, почему на хорошую вещь сначала пытаются нагадить.
жёстким БДСМпричинно-следственными связями.3. всё оказалось совсем не так, как на самом деле.
желающим познать дзен - странный диалог Клапауций&Logik начало отсюда #62
*подписчикам, срочно отписаться - титановый велосипед подготавливается к переплавке в титановый костыль на три кнопки. :D
делаю зарядное для LI-Io и Ni-Mh ...
в контексте обсуждения класс титановый велосипед для тактовой кнопки. - эта информация не имеет значения и впредь прошу не засорять тему схемами и другими фактами автобиографии, не относящимися в обсуждению работы и практическому применению класс титановый велосипед для тактовой кнопки.
1. Подскажите, плз, где глянуть примеры с разными действиями на разное количество нажатий кнопки?
заведи переменную, считающую количество нажатий кнопки - будешь что-то делать не просто по условию нажатия, а по условию нажатия и значения этой переменной.
т.е.:
#include <class_BUTTON.h> BUTTON BUTTON_01(3); // объявляем объект класса BUTTON кнопку с именем BUTTON_01, подключенную к пину 3. byte tick_click_down_01 = 0; // счётчик нажатий кнопки BUTTON_01 void setup () {} void loop() { BUTTON_01.read(); // обновляем состояние переменных кнопки BUTTON_01. // работаем с переменными кнопки BUTTON_01. if (BUTTON_01.click_down) {++tick_click_down_01; if (tick_click_down_01 == 5) {tick_click_down_01 = 4;}} // подсчёт нажатий кнопки до 4. if (BUTTON_01.timer) {tick_click_down_01 = 0;} // сброс счётчика нажатий в 0 после 5 секунд неактивности кнопки. if (BUTTON_01.click_down && tick_click_down_01 == 1) {} // что-то делаем по событию первого нажатия. if (BUTTON_01.click_down && tick_click_down_01 == 2) {} // что-то делаем по событию второго нажатия. if (BUTTON_01.click_down && tick_click_down_01 == 3) {} // что-то делаем по событию третьго нажатия. if (BUTTON_01.click_down && tick_click_down_01 == 4) {} // что-то делаем по событию червёртого нажатия. }2. Как организовать запрет опроса кнопки после того, как процесс будет запущен, т.е. на РВ3( Ардуино 2) будет лог 1 и Тини 13 не должна реагировать на нажатие кнопки.
#4
if (!условие) {BUTTON_01.read();}// обновляем состояние переменных кнопки BUTTON_01.При паузе между нажатиями более 5 сек, фиксируется последнее состояние портов, которое можно изменить следующим нажатием кнопки (если на порту РВ3 лог 0).
здесь не понятно - последнее состояние фиксируется в момент изменения состояния и сохраняется навсегда до следующего события изменения состояния и никак не зависит от времени.
если ты желаешь сбросить счётчик нажатий, то выше в примере реализовано. и настраивается
ооооо! Клапауций 232, гораздо понятнее стало.
спасибо!
а про тему я понял что ошибся, да уже ничё не исправить.
Клапацуй 232, попробовал Ваш класс (после того как в своём обнаружил баг (при создании более одного экземпляра класса защита от дребезга не производится, в данный момент ищу причину).
Использовал для проверки следующий код
#include <BUTTON.h> BUTTON BUTTON_01(2); void setup () { pinMode(13,OUTPUT); } void loop() { BUTTON_01.read(); // обновляем состояние if (BUTTON_01.click_down) { digitalWrite(13,!digitalRead(13)); } }К удевлению задержку между нажатием кнопки и реакцией на неё в течении длительности отслеживания дребезга я не обнаружил. В чем может быть проблемма? Код класса взят из поста #1.
К удевлению задержку между нажатием кнопки и реакцией на неё в течении длительности отслеживания дребезга я не обнаружил. В чем может быть проблемма? Код класса взят из поста #1
для обнаружения реакции на дребезг нужно симулировать ситуацию дребезга - нажатия кнопки чаще, чем
staticconstbytebounce_:для проверки вручную и визуально установи
staticconstbytebounce_ = 1000;// длительность отслеживания дребезга.нажатия реже, чем один раз в секунду у тебя будут отрабатываться - чаще, чем один раз в секунду будут игнорироваться.
или сгенери аппаратным образом нажатие кнопки чаще, чем
staticconstbytebounce_ = 50при дефолтных настройках класса, если владеешь осциллографом.*код класса работает по следующему алгоритму - если время между нажатиями кнопки меньше
staticconstbytebounce_, то событие считается дребезгом и игнорируются, если больше, то нажатием и отрабатывается немедленно.** начиная отсюда #173 пытаюсь объяснить, почему так, а не иначе.
Провел эксперимент. Если на вход пина кнопки подавать прямоугольные импульсы (имитация дребезга) на выходе класса должны видеть 0.
Начал с 50Гц и снижал частоту до 10Гц, и Ваш и мой класс отработали одинаково, вплоть до 11Гц на выходе у них ничего небыло, а вот на 10Гц и Ваш и мой начал переодически устанавливать выход т.к. длина импульса при частоте 10Гц около 50мс.
Так что оба решения состоятельны.
Так что оба решения состоятельны.
как же состоятельны, если
далее, я тебе объяснил, что бабушку хоронят потому, что она умерла, а не потому, что выкопана могила.
Тогда лично я не очень понял, зачем Вы текст тут разместили, если юзать будете сами? Чтобы не забыть? Или все таки для того, чтобы им могли пользоваться другие? Если второй вариант, то тогда надо позаботится об удобстве будущих пользователей и добавить в описание класа одну строчку private: в нужном месте, а не становится в позицию оскорбленного справедливой критикой.
Тогда лично я не очень понял, зачем Вы текст тут разместили, если юзать будете сами? Чтобы не забыть? Или все таки для того, чтобы им могли пользоваться другие? Если второй вариант, то тогда надо позаботится об удобстве будущих пользователей и добавить в описание класа одну строчку private: в нужном месте, а не становится в позицию оскорбленного справедливой критикой.
и, кто мне это переведёт на русский язык?
кому я снова недодал личного внимания или недостаточно убедительно послал в пень?
Боюсь Вас огорчить, но послать меня достаточно убедительно в пень Вам удасться лет через 15-20 занятий встроенным программированием.
Есть такая очаровательная фраза "В Уставе караульной службы каждая строчка написана кровью людей, которые пытались делать по своему". Вы, похоже, решили пройти путь по хорошо освещенным граблям самостоятельно, в добрый путь.
Мое же мнение состоит в том, что программировать можно или хорошо, или никак. Поскольку Ваша программа до уровня хорошо не дотягиваем явно, и советы по ее улучшению Вы категорически отвергаете, то готов оставить Вас с программой уровня никак.
Если Вы действительно считаете, что потрясающие в своей эффективности алгоритмы и необычные, не приходящие до сего момента никому в голову решения, примененные в Вашем чудесном коде, вызывают злопыхания завистников, который в бессильной злобе пытаются своими грязными лапами обеспечить Ваше прекрасное детище, то боюсь, Вы живете в вымышленном мире.
Ни в коей мере не претендуя на личное внимание столь продвинутого программиста, тем не менее мог бы порекомендовать посмотреть исходные коды обработки событий мыши в древней системе Turbo Pascal, где то, что Вы считаете невозможным без заглядывания в будущее, реализуется вполне понятными и довольно таки тривиальными конструкциями.
Боюсь Вас огорчить...
я тебя огорчать не боюсь - т.к. у тебя несколько вариантов поведения:
- ты пишешь хороший код для работы с кнопкой и публикуешь его на этом форуме.
- ты исправляешь ошибки в код класс титановый велосипед для тактовой кнопки.
- ты идёшь в пень, как программист-пустомеля.
*кретинам, обзывающим меня программистом, повторяю: я - радиомонтажник.
Уважаемый GarryC, не сочтите за труд прочитать.
Тогда лично я не очень понял, зачем Вы текст тут разместили, если юзать будете сами? ...то тогда надо позаботится об удобстве будущих пользователей и добавить в описание класа одну строчку private: в нужном месте.
Если Вы пришли к нам в "песочницу" из "конструкторского бюро", так помогите, если не затруднит. Если обратите внимание на попытки написать альтернативу этому коду, то увидите, что никто не довел дела до конца и/или его теория оказалась не состоятельной.
Боюсь Вас огорчить, но послать меня достаточно убедительно в пень Вам удасться лет через 15-20 занятий встроенным программированием.
Мда, сколько таких тут мимо проходило, ни один не доказал своей состоятельности ДЕЛОМ.
..., и советы по ее улучшению Вы категорически отвергаете, ..
Достаточно часто проглядываю топики, чего-то не увидел дельных советов.
... Если Вы действительно считаете, что потрясающие в своей эффективности алгоритмы и необычные, не приходящие до сего момента никому в голову решения, примененные в Вашем чудесном коде, вызывают злопыхания завистников, который в бессильной злобе пытаются своими грязными лапами обеспечить Ваше прекрасное детище...
Ежу понятно, что нет предела совершенству. Вот только где эти "супер коды-алгоритмы" в законченном виде? Где-то выше, только один человек написал "я использую вот такой код" но он мне не подходит, а кде все остальные???
...тем не менее мог бы порекомендовать посмотреть исходные коды обработки событий мыши в древней системе Turbo Pascal, где то, что Вы считаете невозможным без заглядывания в будущее, реализуется вполне понятными и довольно таки тривиальными конструкциями.
Мог (я) бы сказать СПАСИБО, ЕСЛИ БЫ такой продвинутый человек за "спасибо" (как это сделал Клапауций 232) подарил БЫ сообществу сие чудо.
Ну и, чтоб не из пустоты писать. Вот мой четвертый или пятый код в жизни (вполне рабочий говнокод), чтоб Вы понимали уровень многих участников, для которых код написан.
/* этот код я написал для замка в деревне, чтоб за ключем не бегать. Если работаешь не далеко и кто-то пришел, он должен знать код. Устройсто втягивает защелку на замке. КОД необходимо набирать последовательно, дождавшись когда КРАСНЫЙ светик потухнет, иначе нажитие другой кнопки будет включено в КОД (комбинацию кнопок). Каждая кнопка имеет "вес" 1, 2, 4 и 8 соответственно, пока горит КРАСНЫЙ светодиод вводится КОД соответствующий зашитому в программе и установленному джамперами. Невозможно понять, ошибся ты или нет, пока не набраны 4 комбинации. Для повторного нажатия неоходимо дождаться пока потухнет подсветка... Ну не хватило у меня кнопок на полную клавиатуру :))))))))))))))) Если на А3 (тумблер в доме) лог 0 (тумблер включен) при любой комбинации А0, А1 и А2 (выбор кода) работает "простой код" силовой "полевик" выдран с компьютерной матери 18N06L (что было, то и ставим) */ #include <class_noDELAY.h> #include <class_BUTTON.h> // коды доступа :)))------------ byte COD_A[8][5] = { // [строка] [значение] {0, 0, 0, 0, 0}, // нули. чтоб код не править по инициализации {0, 1, 8, 2, 4}, // код при нажатом тумблере (простой код) {0, 2, 2, 5, 5}, // первый код (по перемычкам кода) {0, 2, 6, 8, 10}, // второй код и т.д. {0, 10, 2, 8, 2}, {0, 1, 6, 8, 8}, }; //---------------------------- noDELAY nD_01; // таймер 1 noDELAY nD_02; // таймер 2 noDELAY nD_011; // таймер 11 noDELAY nD_022; // таймер 22 noDELAY nD_03; // таймер 3 - сброс незавершенного кода BUTTON BT_01(2); // кнопок 1 разряда BUTTON BT_02(3); // кнопок 2 разряда BUTTON BT_03(4); // кнопок 4 разряда BUTTON BT_04(5); // кнопок 8 разряда BUTTON BT_05(8); // кнопка в доме // A0, A1, A2 - джамперы выбора предустановленного кода // A3 - упрощенный код доступа // an array of pin numbers to which BUTTON or jumper are attached int BUTTON_Pins[] = { 2, 3, 4, 5, 8, A0, A1, A2, A3 }; int i=0, j=0; byte q1=0, q2=0;; // перебор кода, очередь нажатия byte Bt = 0; // код кнопок byte Bt1=0, Bt2=0, Bt3=0, Bt4=0, Bt5=0; // результат (факт) нажатия кнопок по весу byte AC0=0, AC1=0, AC2=0, AC3=0, AC4=0, AC5=0, AC6=0; // выбор кода boolean Btc = 0; // признак обработки кода кнопок, 1 если еще не обработан boolean OL=0; // открыть замок //---------------------------------------------------- void setup () { for (int k = 0; k < 9; k++) { pinMode(BUTTON_Pins[i], INPUT); } pinMode(6,OUTPUT); // белый светик на подсветку pinMode(7,OUTPUT); // красный светик на индикацию pinMode(9,OUTPUT); // ШИМ на мотор замка Serial.begin(9600); // for deBug } //------------------------------------------------------ //---------------------------------------------------------- // процедура открытия замка void OPE_LOCK () { if (OL == 1) { nD_011.start(); nD_011.read(1000); nD_022.start(); // мигалка красным светиком пока открываем nD_022.read(100); //мигает красный светик открытого замка if (nD_011.tick) {j++;} if (j==1) { digitalWrite(9, 1); // рывок на открытие, время nD_011.read(1000); } if (j>=2) {analogWrite(9, 30);} // удержание задвижки замка ШИМом if (nD_022.tick) {digitalWrite(7, !digitalRead(7));} //мигает красный светик открытого замка if (j>=5) // открыли, обнуляем все переменные { digitalWrite(9, 0); digitalWrite(7, 0); q1=0; q2=0; j=0; Bt = 0; Btc = 0; nD_011.stop(); nD_022.stop(); OL=0; } } } //------------------------------------------------------ void loop() { //--------------------------------- получаем код нажатия кнопок BT_01.read(); // обновляем состояние BT_02.read(); // обновляем состояние BT_03.read(); // обновляем состояние BT_04.read(); // обновляем состояние BT_05.read(); // обновляем состояние кнопка в доме if (BT_01.click_down) { Bt1=1;} if (BT_02.click_down) { Bt2=2;} if (BT_03.click_down) { Bt3=4;} if (BT_04.click_down) { Bt4=8;} if (BT_05.click_down) { Bt5=16;} //------------------- если нажата кнопка - подсветка и отсчет на сброс переменных кода if (Bt1==1 || Bt2==2 || Bt3==4 || Bt4==8 || Bt5==16) { // Serial.println ("nD_03.start() "); nD_03.start(); digitalWrite(6, 1); } nD_03.read(10000); // время до сброса или нажатия if (nD_03.tick) { digitalWrite(6, 0); nD_03.stop(); Bt=0; Btc=0; q1=0; q2=0; } // конец подсветки и ограничения времени // начало проверки набранной комбинации кнопок if (Btc == 0) // если предыдущий код обработан, а новый еще нет { if (Bt1==1 || Bt2==2 || Bt3==4 || Bt4==8 || Bt5==16) //если кнопка нажата { digitalWrite(7, 1); nD_01.start(); nD_01.read(200); if (nD_01.tick) {i++;} if (i>=3) // интервал определения одновременного нажатия кнопок { Bt=Bt1 + Bt2 + Bt3 + Bt4 + Bt5 ; // получен код набора кнопок Bt1=0, Bt2=0, Bt3=0, Bt4=0, Bt5=0; // получен код набора кнопок Btc = 1; // признак, код еще не обработан // Serial.println (Bt); i=0; nD_01.stop(); digitalWrite(7, 0); // Serial.println ("Bt1=0, Bt2=0, Bt3=0, Bt4=0, Bt5=0; "); }}} //======== подучен код кнопок и признак обработки //---------------------------------------- // обработчик кода нажатия кнопок if (Btc == 1) { q1++; // перебор очереди нажатия // Serial.print ("q1= "); // Serial.println (q1); if (Bt >= 16) // если нажата кнопка в доме (независимо от набора на улице) { // Serial.println ("if (Bt>=16) !!!!!! "); OL=1; // OPEN_LOCK (1); // в конце лупа Btc=0; q1=0; q2=0; } if (Bt<=15) //набираем кнопки на улице { // Serial.println ("[AC4] = "); // Serial.println (AC4); // Serial.println ("[q1] = "); // Serial.println (q1 ); // Serial.println ("COD_A[AC4][q1] "); // Serial.println (COD_A[AC4][q1]); ACCESS_CODE (); // какой код выбран т.е. где стоят джамперы (работа с массивом) if (Bt == COD_A[AC4][q1]) // если код совпал { q2++; // Serial.print ("q2= "); // Serial.println (q2); } else {q2=0;} if ( q2 >= 4) //если все 4 цифры верно набрали { OL=1; // открыть и обнулить Btc=0; q1=0; q2=0; } if ( q1 >= 12) // если кто-то брутит, можно еще больше сделать { // OL=1; Btc=0; q1=0; q2=0; } Btc=0; // ХБЗ зачем оно тут :) } } // конец обработчика кода нажатия кнопок //--------------------------------------- // Serial.print ("OL "); // Serial.println (OL); OPE_LOCK (); // открыть замок, если OL = 1 } // loop //-------------------------------------------------------------- void ACCESS_CODE () // работа с кодом доступа { // Serial.println ("void ACCESS_CODE () "); AC0 = !digitalRead(A0); AC1 = !digitalRead(A1); AC2 = !digitalRead(A2); AC3 = !digitalRead(A3); // Serial.print ("AC0... AC2= "); // Serial.print (AC0); // Serial.print (AC1); // Serial.println (AC2); if (AC3 == 1) // если код "простой" т.е. вкл. тумблер в доме { // byte COD_A[8][4] = // [строка] [значение] AC4 = 1; } if (AC3 == 0) // собираем код из джамперов и спускаем ниже кода тумблера (+1) { AC4 = 1 + AC0 + AC1 + AC1 + AC2 + AC2 + AC2 + AC2; } // Serial.print ("AC3= "); // Serial.println (AC3); // Serial.print ("AC4= "); // Serial.println (AC4); }UPD
так я и не понял этой фразы....
...мог бы порекомендовать посмотреть исходные коды обработки событий мыши в древней системе Turbo Pascal, где то, что Вы считаете невозможным без заглядывания в будущее, реализуется вполне понятными и довольно таки тривиальными конструкциями.
объяснитесь, пожалуйста, так я собираюсь нажать, кликнуть 2 раза или подержать (ну скажем 5 секунд). И как там это реализовано?
пост 100
при двойном клике или удержании кнопки одиночное нажатие всё равно срабатывает, что иногда не приемлемо
опиши мне словами алгоритм, который будет предсказывать будущее, например:
я нажал кнопку и... [здесь девайс смотрит в будущее и он точно знает, что]....
так я и не понял этой фразы....
Гриша, если бы хоть у одного, пострадавшего от класс титановый велосипед для тактовой кнопки., было желание вести конструктивный диалог с целью улучшения, исправления, приведения к некоему стардарту кода класса, то это звучало бы следующим образом - в языке Z++ кнопки обрабатываются таким кодом по такому алгоритму.
т.е. забей на этот серый шум профессиональных безработных программистов - времени у них дофига, а код бесплатно написать им профессиональность не позволяет.
анонс.
на днях выложу переписанную заново версию кода класса - через более чем год многие вещи вижу иначе.
анонс.
на днях выложу переписанную заново версию кода класса - через более чем год многие вещи вижу иначе.
Ждем. Юзаю более или менее данный класс. Немного переписал под себя, убрал лишние примочки.
Ждем. Юзаю более или менее данный класс. Немного переписал под себя, убрал лишние примочки.
и чего мешает поделиться результатом (ну соответственно, с описание переделок.)? Я пример использования кинул в посте 243 (тока там без переделок, я их не делал)
Прежде всего, хотелось бы подчеркнуть, что воспитанный человек не может обращаться на ты к незнакомому человеку в русском языке, поскольку это невежливо. В других языках, где понятия ты И Вы сливаются, это вполне допустимо, но даже в них при общении с малознакомыми людьми принято применять безличные Mrs и Ms вместо You. Но это так заметка по поводу, конечно, можно быть хорошим разработчикам и при этом пренебрегать правилами поведения в обществе, но мне подобное сочетания представляется маловероятным в силу ряда причин, излагать которые в данном комменте считаю излишним.
Насчет первого варианта поведение - предложение интересное, своего рода вызов, конечно, не моего уровня, но вполне себе вызов. У меня такой код есть, написан он лет 15 назад на ассемблере для I8051, в ближайшие выходные постараюсь первратить его в программу для среды Ардуино и выложить.
Второй вариант, простите, не рассматриваю - здесь как раз тот случай, когда проше выкинуть, чем переделать, постараюсь свой интерфейс сделать максимально близким к Вашему.
Третий вариант, с Вашего позволения, пока не рассматриваем до ближайших выходных.
Ну и последнее, по моему мнению, назвать человека программистом - это не обозвать его, поскольку программирование, как профессия, требует весьма высокого уровня интеллектуального развития и не может быть оскорбительныи. А что касается того, чем Вы зарабатываете в реальной жизни - по Вашему, это существенно? Я должен сделать скидку и относится к Вашей программе, исходя из иных критериев, нежели к своей или к программе коллеги? Это почему, собственно?
Если я Вам принесу криво собранную плату со "слепыми " пайками и в ответ на Ваши замечания гордо заявлю, что я программист, это как-то улучшит качество этой платы?
Сразу отвечу на вопрос из следующего Вашего комментария о заглядывании в будущее - Вы увидите это в коле, который я обещал написать за выходные, но сразу изложу основную идею - событие нажатия задерживается до того момента, когда достоверно станет известно, что это не двойной клик и не длительное нажатие - довольно таки несложно. Постараюсь обратить внимание на данный момент в комментариях.
1. В том то и дело, что я прочитал комменты в начале и там уважаемому автору предлагалось другими участниками ввести некоторые элементарные исправления в код, чтобы соблюсти общепринятые соглашения о написании классов. Но, вместо того, чтобы последовать этим несомненно разумным советам, автор начинает вопрошать, зачем это делать (я не буду цитировать содержимое любой книги по ООП, там все наглядно показано с примерами), заявлять, что он и так прекрасно использует свой класс, что и вызвало к жизни мой комментарий относительно намерений, сподвигнувших его на выставление своего кода на всеобщее обозрение. Да, Вы правы, никто из критикующих код не предложил внятной альтернативы; как я и обещал, постараюсь исправить данное упущение.
2. Отосительно проходящих мимо, ничего не могу сказать, надеюсь, что после выходных буду зачислен в другую категорию, пока могу порекомендовать посмотреть мои посты на Хабре, я там пишу исключительно о встроенном программировании и разработке, возможно, они позволят Вам создать первое впечатление о моем уровне.
3. По поводу советов именно они и были в комментах к этому посту - посмотрите внимательнее.
4. Да, это был сарказм, возможно, излишний, наверное, погорячился.
5. Если я выполню свое обещание за эти выходные, то вполне приму Вашу благодарность, ни на что другое я не рассчитываю, мои посты удовлетворяют не нижние уровни пирамиды потребностей.
6. Ваш код (я никогда в своей жизни в письменном виде слово, которым Вы его охаректеризовали, не использовал и использовать не собираюсь), несомненно, тоже посмотрю и постараюсь дать к нему комментарий (по первому впечатлению, там есть, что комментировать в плане улучшения), но сразу хочу заявить, что ..
7. Если Вы занялись программированием, то Вы должны ответственно относиться к данному процессу и постоянно повышать свой уровень, какой бы он в данный момент не был.
Прежде всего, хотелось бы подчеркнуть, что воспитанный человек не может обращаться на ты к незнакомому человеку в русском языке, поскольку это невежливо.
почему ты решил, что ты мне не знаком?
IMHO (лирика) {
Уважаемый GarryC, что касается:
Прежде всего, хотелось бы подчеркнуть, что воспитанный человек не может обращаться на ты к незнакомому человеку в русском языке, поскольку это невежливо.
Давно заметил, что чем дальше на восток, тем больше люди говорят друг - другу Вы. На западе (России) подавляющее большинство ТЫчет :) такая вот диалектика. Это становится для меня вопросом восприятия и, Я лично, отношусь к этому так:
И посылал в иные земли [посланников, как правило, перед объявлением войны] со словами: „Иду на Вы!“
Если копнуть историю, несложно нарыть вагон информации, где среди прочего "Как называть родителей на «ты» или на «вы» ".
Что же касается грубости "Клапауций ХХХ (и его ипостаси)" комментировать не буду, тем более воспитывать, он не один на форуме.
} IMHO (лирика)
Сразу отвечу на вопрос из следующего Вашего комментария о заглядывании в будущее ... событие нажатия задерживается до того момента, когда достоверно станет известно, что это не двойной клик и не длительное нажатие - довольно таки несложно.
пост 110
* возможно!, этот алгоритм поможет следующим пользователям... :
в программе определяется "что" использовать (нажатие, двойное нажатие, удержание) и устанавливается интервал (время) определения - до его окончания никаких действий. Соответственно если использовать только простое нажатие - мгновенное исполнение, во всех других комбинациях - действие исполняется по истечении времени интервала определения - да хоть тройное нажатие!
ты не оригинален в желании программно затупить работу кнопки на время, превышающее bounce_ - длительность отслеживания дребезга.
пост113
UPD пост 109. "залипание кнопки" - если перекрыть все моменты, то необходимо позаботиться в алгоритме о том, что есть "залипание кнопки" и как этот момент обрабатывать!!!
никак не обрабатывать, т.к. при залипании кнопки(постоянном нажатии) обработается один раз событие удержание кнопки и в дальнейшем кнопка перестанет работать совсем от слова СОВСЕМ.
исходя из условий поставленной задачи, можно вообще не обрабатывать "удержание" если кнопку не отпустили!!! НО, это все должен определить РАЗРАБОТЧИК (програмист) согласно алгоритму по ТЗ.
ИМХО. Написать код достаточно просто, правильно составить алгоритм почти - искусство. Это как в школе – правильно составленное условие задачи больше половины решения. А в данном случае, разработчик должен описать все возможные события именно так, как ему это нужно.
Темка понравилась именно тем, что есть код (доступный), который можно допилить под свои нужды – все универсальное слишком громоздко.
PS. тем не менее ждем Вашего расширенного варианта кода
Давно заметил, что чем дальше на восток, тем...
...толще партизаны.(с)
Гриша, неужели моё обращение к GarryC на "ты", является главным из перечисленных им, моих преступлений против человечности в общем и ползателями форума в частности, что бы акцентировать внимание именно на этом, вместо того, что бы осудить меня по совокупности моих ужасных деяний?
весь в сомнениях - ведь, весь этот флуд просто обязан как-то коррелировать к кодом для обработки работы тактовой кнопки... но, как и каким местом?
что GarryC хотел мне и нам донести, потратив время для написания таких длинных и полезных для меня и всех нас постов?
весь в сомнениях - ведь, весь этот флуд просто обязан как-то коррелировать к кодом для обработки работы тактовой кнопки... но, как и каким местом?
да никакак - это ИМХО
уже раз 5 писал:
пост 15
3) Пожалуйста, дайте право ТС дополнять (возможно, и изменять) первый пост всегда!!!
пост 25
Назрела проблема с офф.топом. Много сообщений убивающих время и не несущих полезной информации....
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // класс титановый велосипед для тактовой кнопки. (версия 1.0) // фильтр дребезга, отслеживание событий: нажатие, отпускание, двойное нажатие(doubleclick), нажато и удерживается в течении определённого времени, отпущено и неактивно в течении определённого времени. #include <Arduino.h> class BUTTON { public: //============================================================================================ // константы настроек класса. static const byte bounce_ = 50; // длительность отслеживания дребезга. static const byte doubleclick_ = 250; // длительность отслеживания двойного нажатия. static const unsigned long timer_ = 5000; // длительность отслеживания неактивности. static const unsigned int retention_ = 2000; // длительность отслеживания нажатия и удержания. //============================================================================================ unsigned long start; // старт отсчёта времени. boolean p; // состояние пина кнопки. boolean s; // программное состояние кнопки. boolean b; // состояние таймера фильтра дребезга. byte c; // переменная счётчика двойного нажатия. boolean t; // состояние таймера неактивности. boolean r; // состояние таймера нажатия и удержания. //============================================================ boolean click_down; // событие нажатия. boolean click_up; // событие отпускания. boolean doubleclick; // событие двойного нажатия. boolean timer; // событие неактивности. boolean retention; // событие нажатия и удержания. //============================================================ byte _pb; //============================================================ BUTTON(byte pb) { _pb = pb; pinMode(_pb, INPUT); digitalWrite(_pb, 1); //=================== start = millis(); p = digitalRead(_pb); // p = !digitalRead(_pb); // отключить тихий старт. s = p; b = 0; c = 0; t = 0; r = 0; //============== click_down = 0; click_up = 0; doubleclick = 0; timer = 0; retention = 0; //============== } void read() { //============================================================================== boolean np = digitalRead(_pb); // текущее состояние пина кнопки. unsigned long stop = millis(); // стоп отсчёта времени. //============================================================================== click_down = 0; click_up = 0; doubleclick = 0; timer = 0; retention = 0; //============================================================================== if (np != p) {p = np; click(); start = stop; b = 1; t = 1; r = 1;} // состояние цифрового пина изменилось. //============================================================================== if (b != 0 ) {if (stop - start > bounce_ ) {b = 0; click(); }} // фильтр дребезга. if (c != 0 ) {if (stop - start > doubleclick_) {c = 0; }} // обнуление счётчика двойного клика. if (t != 0 && s == 1) {if (stop - start > timer_ ) {t = 0; timer = 1;}} // неактивность. if (r != 0 && s == 0) {if (stop - start > retention_ ) {r = 0; retention = 1;}} // нажатие и удержание. //============================================================================== } void click() { // нажатие, отпускание, двойное нажатие. if (b == 0 && s != p) {s = p; if (s == 0) {click_down = 1; ++c; if (c == 2) {c = 0; doubleclick = 1;}} if (s == 1) {click_up = 1; } } } }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Уважаемый, строка 35, случаем не ошибка?????????? или это pullup?
digitalWrite(_pb, 1);