Антидребезг для шилда LCD+ кнопки.

skalinas
Offline
Зарегистрирован: 13.01.2016

Добрый день.

Реализовал антидребезг  для шилда (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

 

skalinas
Offline
Зарегистрирован: 13.01.2016

Схема в Proteus, термометры + гигрометр для сауны с возможностью регулировать газовой горелкой каменки и парогенератором. Кнопки нужны для выбора окон отображения на LCD и семисегментном индикаторе, настройки порогов управления и калибровки датчиков.