Ищу библиотеку для работы с кнопками

faraddin
Offline
Зарегистрирован: 11.08.2013

Может кто сталкивался, или знает где найти толковую библиотеку для работы с кнопками, такую с помощью которой можно было бы легко отслеживать одинарные, двойные, тройные и т.д. с удержанием или без него. Чтоб на каждую комбинацию можно было повесить свою функцию и т.д.

Ну или подскажите мне идею, как организовать лучше историю нажатий кнопки (клик, двойно клик, двойной клик с удержанием)

ourlive
Offline
Зарегистрирован: 26.05.2012

Напишите сами, это интереснее. 

Нагляднее всего хранить историю нажатий в текстовой строке, приплюсовывая для каждого нового нажатия в зависимсти от его длительности определённый символ (в принципе так даже коротки и длинный клик можно различать). Соотетственно сбрасить строку если состояние "кнопка отпущена" превысил некий разумный интервал времени, предварительно проанализировав. И при привышении длительности нажатия аналогично сбросить строку после анализа на совпадение с заданным жестом оканчивающимся на "удержание".

Для понимания идеи такой алгоритм нагляднее всего и его даже можно иногда реально использовать в устройствах. Если при этом опрашивать состояние клавишь не чаще раза в 10мс, то и дополнительных антидребезговых алгоритмов не нужно.

EvgenJekson
Offline
Зарегистрирован: 15.12.2015

Вот мое решение:

 

// Объявляем переменные и константы
const int buttonPin = 2;                  // Пин с кнопкой


int currentButtonStatus = 0;              // 0 - Кнопка не нажата
                                          // 1 - Кнопка нажата первый раз
                                          // 2 - Кнопка отжата после нажатия
                                          // 3 - Кнопка нажата во второй раз

unsigned long currentButtonStatusStart1;  // Кол-во милисекунд от начала работы программы, когда начался статус 1
unsigned long currentButtonStatusStart2;  // Кол-во милисекунд от начала работы программы, когда начался статус 2    
unsigned long currentButtonStatusStart3;  // Кол-во милисекунд от начала работы программы, когда начался статус 3
    


const int delayFalse = 10;                // Длительность, меньше которой не регистрируется единоразовый клик
const int delayLongSingleClick = 1000;    // Длительность зажатия кнопки для выхода в режим увеличения громкости
const int delayDeltaDoubleClick = 800;    // Длительность между кликами, когда будет зафиксирован двойной клик


void setup() {
  
  // Прописываем пины
  pinMode(buttonPin, INPUT);
  
  // Вывод
  Serial.begin(9600);

}

void loop() {

  // Определяем текущий статус кнопки
  int event = changeButtonStatus();
  if(event > 0) {
    // Если поменялся статус
    Serial.print("status change: ");
    Serial.println(event);
  } 
  
  
  
  

}

/**
 * Смена текущего статуса 
 * @return = 0 - ничего не произошло
 *           1 - простой клик
 *           2 - двойнок клик
 *           3 - зажата кнопка
 *           4 - отжата кнопка после долгого зажатия
 */
int changeButtonStatus() {
  // Событие
  int event = 0;
  
  // Текущее состояние кнопки
  int currentButtonClick = digitalRead(buttonPin);
  
  // Текущее время 
  unsigned long timeButton = millis();
  
  switch(currentButtonStatus) {
    
    case 0:
      // В настоящий момент кнопка не нажималась
      
      if(currentButtonClick) {
        // Зафиксировали нажатие кнопки
        
        currentButtonStatus = 1;
        currentButtonStatusStart1 = millis();
        
        
      } else {
        // Кнопка не нажата
        // Ничего не происходит
      }
      break;
      
    case 1:
      // В настоящий момент кнопка на этапе первого нажатия
      
      if(currentButtonClick) {
        // Кнопка все еще нажата
        
        if(timeButton - currentButtonStatusStart1 >= delayLongSingleClick) {
          // Кнопка в нажатом состоянии уже дольше времени, после которого фиксируем длительное одинарное нажатие на кнопку
          
          // Событие длительного давления на кнопку - продолжаем давить
          event = 3; 
          
        }
        
      } else {
        // Кнопку отжали обратно
        
        if(timeButton - currentButtonStatusStart1 < delayFalse) {
          // Время, которое была кнопка нажата, меньше минимального времени регистрации клика по кнопке
          // Скорее всего это были какие то флюктуации
          // Отменяем нажатие
          currentButtonStatus = 0;
          event = 0;
          
        } else if(timeButton - currentButtonStatusStart1 < delayLongSingleClick) {
          // Время, которое была кнопка нажата, меньше времени фиксации долгого нажатия на кнопку
          // Значит это первое одноразовое нажатие
          // Дальше будем ожидать второго нажатия
          currentButtonStatus = 2;
          currentButtonStatusStart2 = millis();
        } else {
          // Время, которое была нажата кнопка, больше времени фиксации долгого единоразового нажатия
          // Значит это завершение длительного нажатия
          currentButtonStatus = 0;
          event = 4;
          
        }
        
      }
      
      break;
      
    case 2:
      // Мы находимся в фазе отжатой кнопки в ожидании повторного ее нажатия для фиксации двойного нажатия
      // или, если не дождемся - значит зафиксируем единичное нажатие
      
      
      if(currentButtonClick) {
        // Если кнопку снова нажали
        
        // Проверяем, сколько времени кнопка находилась в отжатом состоянии
        if(timeButton - currentButtonStatusStart2 < delayFalse) {
          // Кнопка была в отжатом состоянии слишком мало времени
          // Скорее всего это была какая то флюктуация дребезга кнопки
          // Возвращаем обратно состояние на первичное нажатие кнопки
          currentButtonStatus = 1;
          
        } else {
          // Кнопка была достаточно долго отжата, чтобы зафиксировать начало второго нажатия
          // Фиксируем
          currentButtonStatus = 3;
          currentButtonStatusStart3 = millis();
        }
        
      } else {
        // Если кнопка все еще отжата
        
        // Проверяем, не достаточно ли она уже отжата, чтобы зафиксировать разовый клик
        if(timeButton - currentButtonStatusStart2 > delayDeltaDoubleClick) {
          // Кнопка в отжатом состоянии слишком долго
          // Фиксируем одинарный клие
          currentButtonStatus = 0;
          event = 1;
        }
        
      }
    
      break;
      
    case 3:
      // Мы на этапе второго нажатия
      // Для подтверждения факта двойного нажатия
      
      if(currentButtonClick) {
        // Кнопка все еще зажата
        // Ничего не происходит, ждем, когда отожмут
        
      } else {
        // Кнопку отжали
        
        // Проверям, действительно ли отжали, или это дребезг кнопки
        if(timeButton - currentButtonStatusStart3 < delayFalse) {
          // Кнопку отжали слишком рано
          // Скорре всего это дребезг
          // Гинорируем его
          
        } else {
          // Кнопка была в нажатом состоянии уже достаточно длительное время
          // Это завершение цикла фиксации двойного нажатия
          // Сообщаем такое событие
          event = 2;
          currentButtonStatus = 0;
        }
      }
      
      break;
    
  }
  
  return event;
}

 

Radjah
Offline
Зарегистрирован: 06.08.2014

Еще один адепт церкви Идеальной Кнопки.

Клапауций 123
Offline
Зарегистрирован: 06.12.2015

Radjah пишет:

Еще один адепт церкви Идеальной Кнопки.

а, чего мне нравится - смешные комменты в коде

102           // Скорее всего это были какие то флюктуации
103           // Отменяем нажатие

 

Radjah
Offline
Зарегистрирован: 06.08.2014

Черт! А я их фильтром отсеивал. :(

Клапауций 321
Offline
Зарегистрирован: 17.12.2015

Radjah пишет:

Черт! А я их фильтром отсеивал. :(

фильтровать - это полдела, а вот отменять нажатие...