pulseIn и двойное нажатие клавиши

so_nooby
so_nooby аватар
Offline
Зарегистрирован: 24.09.2013

смысл такой

по зажатию кнопки больше чем на 0,5 секунды активировать void lob();  и держать пока не отпустишь кнопку.

по двойному клику на туже кнопку активировать void fara();.

Давлю на кнопку как могу, нихрена. Схему привел, скетч скинул.

Часть с двойным кликом в моем исполнении - бред сивой кобылы. Приму в дар исправления.

в конце все будет на Аттине13

 

int Fara = 7;
int Lob  = 6;
int nasos = 3;
int clapan = 2;
int lepestok = 5;
int davil = 0;

 
void setup()
{
  pinMode(Fara, OUTPUT);
  pinMode(Lob, OUTPUT);
  pinMode(nasos, OUTPUT);
  pinMode(clapan, OUTPUT);
  pinMode(lepestok, INPUT);
  pinMode(12,OUTPUT);
}
 
void loop()
{
  int time1 = millis();
  davil = pulseIn(lepestok, HIGH);
   if (davil > 500000)
     { 
    lob();
     }
   else if (davil<500000&&davil>200000)
     {    
      if (((time1-millis())>220)&&(time1-millis())>2000)
        { 
       fara();
        }
     }

}
 
void lob()
{

digitalWrite(Lob,HIGH);
digitalWrite(nasos,HIGH);
delay(5000);
digitalWrite(Lob,LOW);
digitalWrite(nasos,LOW);
}
void fara()
{
    int lep=digitalRead(lepestok);
    while( lep = 1)
  {
digitalWrite(Fara,HIGH);
digitalWrite(clapan,HIGH);
digitalWrite(nasos,HIGH);
delay(5000);
digitalWrite(Fara,LOW);
digitalWrite(clapan,LOW);
digitalWrite(nasos,LOW);
  }
}

 

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

pulseIn ждет изменение уровня секунду, и если ничего нет, то возвращает 0, ЕМНИП.

Т.е. проверяешь перед замером, что кнопка не нажат и начинаешь ловить. Если после замера 0, то прогон оказался пустым и ничего делать не надо.

Еще я не понял сакральный смысл 29-й строки.

Maverik
Offline
Зарегистрирован: 12.09.2012

чтобы эту мысль реализовать по человечески, нужно бы пользоваться прерываниями функция (attachInterrupt() ), и еще - кроме LOW и HIGH есть еще другие значения- в данном случае может быть актуально.

так что тут до фары, насоса и клапана еще очень далеко :-)

so_nooby
so_nooby аватар
Offline
Зарегистрирован: 24.09.2013

Radjah пишет:

pulseIn ждет изменение уровня секунду, и если ничего нет, то возвращает 0, ЕМНИП.

Т.е. проверяешь перед замером, что кнопка не нажат и начинаешь ловить. Если после замера 0, то прогон оказался пустым и ничего делать не надо.

Еще я не понял сакральный смысл 29-й строки.

 

Секунду? Я вроде понял что таймаут ожидания можно выставлять, приписывая 3 параметр как время в МИКРОсекундах.

29 строкой пытался поймать быстрый клик, т.е. Зажатие больше чем на 0,2 секунды но меньше чем на 0,5

so_nooby
so_nooby аватар
Offline
Зарегистрирован: 24.09.2013

Maverik пишет:

чтобы эту мысль реализовать по человечески, нужно бы пользоваться прерываниями функция (attachInterrupt() ), и еще - кроме LOW и HIGH есть еще другие значения- в данном случае может быть актуально.

так что тут до фары, насоса и клапана еще очень далеко :-)

я более менее умею обращаться с прерыванием. 

У меня цель освоить пульсИн.

пусть фара, насос и клапан вас не смущают, допустим там 4 светодиода как на схеме.

А где могут быть интересующие меня значения кроме 1 и 0, я не понял

Maverik
Offline
Зарегистрирован: 12.09.2012

> А где могут быть интересующие меня значения кроме 1 и 0, я не понял

в digitalRead(), которым Вы не пользуетесь.  

а 29я строка не причем, там просто в первой части знак перепутан (должно быть "<"). Ваша проблема, естественно, в том, что Вы храните сравниваете значения, которые имеют тип unsigned long (функции времени вроде millis() ) со своими переменными типа int.  Если Вы посмотрите, какая максимальная величина может храниться в int, всё встанет на свои места.

 

 

 

 

 

 

Araris
Offline
Зарегистрирован: 09.11.2012

IMHO, pulseIn() в данной задаче выглядит насильно притянутым за уши с целью изучения, а вот attachInterrupt() - самое то.

so_nooby
so_nooby аватар
Offline
Зарегистрирован: 24.09.2013

Araris пишет:

IMHO, pulseIn() в данной задаче выглядит насильно притянутым за уши с целью изучения, а вот attachInterrupt() - самое то.

согласен полностью. Просто хочу освоить

so_nooby
so_nooby аватар
Offline
Зарегистрирован: 24.09.2013

Maverik пишет:

> А где могут быть интересующие меня значения кроме 1 и 0, я не понял

в digitalRead(), которым Вы не пользуетесь.  

а 29я строка не причем, там просто в первой части знак перепутан (должно быть "<"). Ваша проблема, естественно, в том, что Вы храните сравниваете значения, которые имеют тип unsigned long (функции времени вроде millis() ) со своими переменными типа int.  Если Вы посмотрите, какая максимальная величина может храниться в int, всё встанет на свои места.

 

В digitalRead() на выходе можно получить иное чем 0 или 1????

Да неужели?

 

 

 

 

Maverik
Offline
Зарегистрирован: 12.09.2012

>Да неужели?

Угу. только для этого нужны кой-какие телодвижения, в общем не грузитесь )

И вообще, простого "спасибо" было вполне достаточно ;-)

 

 

so_nooby
so_nooby аватар
Offline
Зарегистрирован: 24.09.2013

Maverik пишет:

>Да неужели?

Угу. только для этого нужны кой-какие телодвижения, в общем не грузитесь )

И вообще, простого "спасибо" было вполне достаточно ;-)

 

 

с телодвижениями все можно.

за тип спасибо

с внимательным чтениям мануалов у меня всегда проблемы были и будут

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
    
                                    
int currentValue = 10;                    // Текущее значение громкости
const int maxValue = 30;                  // Максимальное значение громкости
const int minValue = 5;                   // Минимальное значение громкости

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: ");
    //time = millis();
    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;
}

 

Делаю возможность смены композиций в mp3-плеере работая с одной кнопкой: нажал = включил - еще раз нажал = выключил - два раза нажал = следующая композиция - долго давлю на кнопку = увеличение звука.

в примере нет работы с музыкой. есть только получение действий с кнопкой. а это уже можно куда хотите прикрутить...

ArcadePUB
Offline
Зарегистрирован: 01.04.2020

Добрый день. Наверное, уже не актуально, но добавлю свои 5 копеек. Может кому пригодится по поиску. Скетч для мультиклика. Более подробные комментарии написал на сайте. + возможность удержания кнопки и разные функции от времени удержания. arcadepub.ru/кнопка/

 

#define BUTTON_PIN 2

int bounceTime = 10;          // задержка для подавления дребезга
int doubleTime = 500;         // время, в течение которого нажатия можно считать двойным
int i = 0;

boolean lastReading = false;  // флаг предыдущего состояния кнопки
boolean buttonSingle = false; // флаг состояния "краткое нажатие"
boolean buttonMulti = false; // флаг состояния "двойное нажатие"

long onTime = 0;              // переменная обработки временного интервала
long lastSwitchTime = 0;      // переменная времени предыдущего переключения состояния

void setup(){
  Serial.begin(9600);
}

void loop(){
  boolean reading = digitalRead(BUTTON_PIN);

  // проверка первичного нажатия
  if (reading && !lastReading){
    onTime = millis();
  }
  
  if (!reading && lastReading){
    if (((millis() - onTime) > bounceTime)){
      if ((millis() - lastSwitchTime) >= doubleTime){
        lastSwitchTime = millis();
        buttonSingle = true;
        i=1;
      } else {
        i++;
        lastSwitchTime = millis();
        buttonSingle = false;
        buttonMulti = true;
      }
    }
  }
  
  lastReading = reading;
  
  if (buttonSingle && (millis() - lastSwitchTime) > doubleTime){
    isButtonSingle();
  }
  if (buttonMulti && (millis() - lastSwitchTime) > doubleTime){
    isButtonMulti(i);
  }
}

void isButtonSingle(){
    buttonMulti = false;
    buttonSingle = false;
    Serial.println(1);
}
void isButtonMulti( int count ){
    buttonSingle = false;
    buttonMulti = false;
    Serial.println(count);
}