Антидребезг для шилда 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 и семисегментном индикаторе, настройки порогов управления и калибровки датчиков.