Антидребезг для шилда LCD+ кнопки.
- Войдите на сайт для отправки комментариев
Добрый день.
Реализовал антидребезг для шилда (LCD+ кнопки) так. Постоянно происходит опрос аналогового входа кнопок в теле программы и происходит сравнение между двумя замерами (интервал между замерами можно выставить от 5 до 30 мс это оптимальное время для антидребезга) уровня напряжения (от 0 до 1024 ед.) на аналоговом входе кнопок. Если уровни совпадают, то интерпретируется нажатие определенной кнопки, если нет, то происходит повторный замер и сравнение уровней (разницу между замеренными уровнями можно установить от 0 до 10 ед.). Если разницу установить в ноль, то ложных срабатываний не бывает. Реализовал 3 режима нажатия кнопки;
1. Однократное нажатие (длительностью менее 750 мс)
2. Удержание кнопки (более 750 мс.)
3. Длительное нажатие (более 5 с.), можно реализовать и другие режимы.
Готовый скетч с перебором цифр от кнопок на экране LCD.
#include <LiquidCrystal.h> //lcd lib LiquidCrystal lcd(8, 9, 4, 5, 6, 7); #define bs_none 0 //статус нет нажатие #define bs_push 1 //статус нажатие #define bs_hold_1 2 //статус удержание (1-2 секунды)и более, через(5-30 секунд)переход в статус 3 #define bs_hold_2 3 //статус удержание (5-30 секунд)и более #define bf_none 0 //значение флага нет нажатие #define bf_push 1 //значение флага нажатие #define bf_hold_1 2 //значение флага удержание (0,5-2 секунды) #define bf_hold_2 3 //значение флага удержание (5-30 секунд)и более #define long_1_Time 750 //удержание (0,5-2 секунды) - статус 2, через(5-30 секунд)переход в статус 3 #define long_2_Time 5000 //удержание (5-30 секунд)и более - статус 3 #define long_3_Time 250 //время авто нажатий long timerButton_2=0; //время задержка кнопки для антидребезга #define bs_read_1 0 //статус первое чтение с АЦП #define bs_lag 1 //статус задержка и второе чтение с АЦП #define bs_score 2 //статус вычисление разници между 2 чтениями #define bs_change 3 //статус присвоения кнопки #define bf_read_1 0 //значение флага первое чтение с АЦП #define bf_lag 1 //значение флага задержка и второе чтение с АЦП #define bf_score 2 //значение флага вычисление разници между 2 чтениями byte deBounce=0; // переменная СТАТУС антидребезга #define deBounceTime 20 //задержка (мс от 5 до 30 мс)для антидребезга #define p_p 0 //устанавливаем разницу (в единицах от 0 до 10) между двумя считываниями значений с АЦП входа А0 int temp_read=1023; int temp_read_1; int temp_read_2; int temp; int clik_1; int clik_10 = 0; int clik_s = 0; byte buttonPin=A0; // пин подключения кнопки (на АЦП получаем: кнопка не нажата кнопка 0>850, кнопка 1<90,кнопка 2<250, кнопка3<430,кнопка 4<650,кнопка 5<850) byte buttonState=0; // переменная СТАТУС КНОПКИ byte curButton=0; // ТЕКУЩАЯ КНОПКА long timerButton=0; // Время нажатия кнопки long timerButton_1=0; // Время задержка кнопки для антидребезга byte pressBut=0; byte buttonFlag=0; //--------------------- start ReadKey --------------------------- // Функция АНТИДРЕБЕЗГ с присвоением номера нажатой кнопки //--------------------------------------------------------------- byte ReadKey() //функция устраняет дребезг контактов, считывает значение с АЦП и преобразует в номер нажатой кнопки { switch (deBounce) // СТАТУС антидребезга { case bs_read_1: temp_read_1=analogRead(buttonPin); //первое считывание с АЦП входа А0 timerButton_1 = millis(); //запоминаем время deBounce=bs_lag; break; case bs_lag: //задержка if(millis() - timerButton_1 > deBounceTime) //задержка между считываниями { temp_read_2=analogRead(buttonPin); //второе считывание с АЦП входа А0 deBounce=bs_score; break; } deBounce=bs_lag; break; case bs_score: //вычисление разници между 2 чтениями temp=temp_read_1-temp_read_2; //определение разницы значений считаных с АЦП if (temp < 0)temp=(int)(temp*-1); //делаем положительный знак if (temp>p_p) { deBounce=bs_read_1; break; } deBounce=bs_change; break; default: temp_read=((temp_read_2+temp_read_1)/2); //усредняем значение deBounce=bs_read_1; } if (temp_read < 80) return 1; //RIGHT в право if (temp_read < 237) return 2; //UP в верх if (temp_read < 412) return 3; //DOWN в низ if (temp_read < 626) return 4; //LEFT в лево if (temp_read < 866) return 5; //SELECT выбрать return 0; } //end ReadKey //---------------- start checkButton ---------------- // Присвоение статуса кнопки //--------------------------------------------------- void checkButton() { switch (buttonState) { //проверяем СТАТУС КНОПКИ //------------------------------------------ case (bs_none): //если ни чего не нажато(=0) curButton=ReadKey(); //считываем номер нажатой кнопки if (curButton!=0) //Если кнопка нажата (т.е., значение >0) { buttonState=bs_push; //следующий статус нажатия (=1) buttonFlag=bs_push; //флаг сработки = нажата кнопка timerButton=millis(); //запоминаем время } else { buttonState=bs_none; //флаг сработки = статуса нет нажатия кнопки buttonFlag=bf_none; //флаг сработки = нет нажатия кнопки } break; //------------------------------------------ case (bs_push): //если нажата кнопка (=1) if ((ReadKey()==curButton)) //если кнопка все еще нажата { if (millis()-timerButton>long_1_Time) //если кнопка удерживается(1-2 секунды)и более { buttonState=bs_hold_1; //статус удержание (1-2 секунды)и более(=2) buttonFlag=bs_hold_1; //флаг сработки = нажатие кнопки } } else { buttonState=bs_none; //флаг сработки = статуса нет нажатия кнопки buttonFlag=bf_none; //флаг сработки = нет нажатия кнопки } break; //------------------------------------------ case (bs_hold_1): //удержание (1-2 секунды)и более (=2) if ((ReadKey()==curButton)) //если кнопка все еще нажата { if (millis()-timerButton>long_2_Time) //если кнопка удерживается(5-30 секунд))и более { buttonState=bs_hold_2; //меняем на статус удержание (5-30 секунд)и более buttonFlag=bf_hold_2; //флаг сработки = 1-2 секунды и более } } else { buttonState=bs_none; //флаг сработки = статуса нет нажатия кнопки buttonFlag=bf_none; //флаг сработки = нет нажатия кнопки } break; //------------------------------------------ case (bs_hold_2): //удержание (5-30 секунд)и более (=3) if ((ReadKey()==curButton)) //если кнопка все еще нажата { if (millis()-timerButton>long_1_Time) //если кнопка удерживается более времени для автоповтора { timerButton=millis(); //запоминаем время buttonFlag=bf_hold_2; //флаг сработки = 5-30 секунд и более } } else { buttonState=bs_none; //флаг сработки = нет нажатия кнопки buttonFlag=bf_none; //флаг сработки = нет нажатия кнопки } break; //------------------------------------------ } //end switch } //end checkButton //------------------------ int lik = 0; int clik = 0; int s = 0; void setup() { lcd.begin(16, 2); lcd.setCursor(3,1); lcd.print("0"); lcd.setCursor(9,1); lcd.print("0"); lcd.setCursor(5,0); lcd.print(" 0 "); } void loop() { checkButton(); if (buttonFlag!=bf_none) //Если кнопка нажата и статус кнопки не равен нулю { if (curButton==2&&buttonFlag==1){ //Однократное нажатие кнопки UP "в верх" buttonFlag=bf_none; clik_1 ++; if(clik_1 > 4){ clik_1 = 0; } lcd.setCursor(3,1); lcd.print(" "); lcd.setCursor(3,1); lcd.print(clik_1); } if (curButton==2&&buttonFlag==2){ //Удержание кнопки UP "в верх" if (millis()-timerButton_2>long_3_Time){ clik_1 ++; if(clik_1 > 4){ clik_1 = 0; } lcd.setCursor(3,1); lcd.print(" "); lcd.setCursor(3,1); lcd.print(clik_1); timerButton_2=millis(); } } if (curButton==3&&buttonFlag==1){ //Однократное нажатие кнопки DOWN "в низ" buttonFlag=bf_none; clik_1 --; if(clik_1 < 0){ clik_1 = 4; } lcd.setCursor(3,1); lcd.print(" "); lcd.setCursor(3,1); lcd.print(clik_1); } if (curButton==3&&buttonFlag==2){ //Удержание кнопки DOWN "в низ" if (millis()-timerButton_2>long_3_Time){ clik_1 --; if(clik_1 < 0){ clik_1 = 4; } lcd.setCursor(3,1); lcd.print(" "); lcd.setCursor(3,1); lcd.print(clik_1); timerButton_2=millis(); } } if (curButton==1&&buttonFlag==1){ //Однократное нажатие кнопки RIGHT "в право" buttonFlag=bf_none; lik ++; if(lik > 4){ lik = 0; } lcd.setCursor(9,1); lcd.print(" "); lcd.setCursor(9,1); lcd.print(lik); } if (curButton==4&&buttonFlag==1){ //Однократное нажатие кнопки LEFT "в лево" buttonFlag=bf_none; lik --; if(lik < 0){ lik = 4; } lcd.setCursor(9,1); lcd.print(" "); lcd.setCursor(9,1); lcd.print(lik); } if (curButton==5&&buttonFlag==1){ //Однократное нажатие кнопки SELECT "выбрать" buttonFlag=bf_none; lcd.setCursor(5,0); lcd.print(" 0 "); } if (curButton==5&&buttonFlag==2){ //Удержание кнопки SELECT "выбрать" if (millis()-timerButton_2>long_3_Time){ lcd.setCursor(5,0); lcd.print("111"); timerButton_2=millis(); } } if (curButton==5&&buttonFlag==3){ //Длительное нажатие кнопки SELECT "выбрать" (нажатие более 5 секунд) if (millis()-timerButton_2>long_3_Time){ lcd.setCursor(5,0); lcd.print("PPP"); timerButton_2=millis(); } } } //end if } //end loop
Схема в Proteus, термометры + гигрометр для сауны с возможностью регулировать газовой горелкой каменки и парогенератором. Кнопки нужны для выбора окон отображения на LCD и семисегментном индикаторе, настройки порогов управления и калибровки датчиков.