способ как обработать только одно нажатие кнопки + антидребезг. Способ "OneClick"

drAjbolit
Offline
Зарегистрирован: 23.11.2012

 

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

 

То есть нажал на кнопку - а программа считает это нажатие за один клик - пока не отпустишь - а не стопитсот мильёнов как обычно.

 

Delay меня категорически не устроил - если передержишь, то начинает считать следующий клик - это меня не устраивает -  начинаю нервничать :)

 

В общем выход найден - может конечно и не я первый, но мне пофиг. Нашёл-то я сам :)

Кнопку подключил вот так 

 

 

 

Скетч получился такой


//OneClick primer
  
#define BUTTON 7 
#define BUTTON1 6

int val1 = 1;     
int val2 = 1;
int val3 = 1;
int val11 = 1;     
int val22 = 1;
int val33 = 1;
int count = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("start");
  pinMode(BUTTON, INPUT); 
pinMode(BUTTON1, INPUT); 
}

void loop(){
  val1 = digitalRead(BUTTON);  
  val3 = val1;
if (val1 == LOW&&val1 != val2) {
      count++;
      Serial.println("Button 1 on and count");
      Serial.println(count);
      val2 = val3;
  }
if (val1 == HIGH){
    val2 = 1;
    val3 = 1;
  }
  
  val11 = digitalRead(BUTTON1);  
  val33 = val11;
if (val11 == LOW&&val11 != val22) {
      count--;
      Serial.println("Button 2 on and count");
      Serial.println(count);
      val22 = val33;
  }
if (val11 == HIGH){
    val22 = 1;
    val33 = 1;
  }

}

Кнопки на портах 6 и7

Антидребезг получился стопудовый - как побочный эффект.

Удачи!

 

Изначально лежит тут

 

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

2 ноги на одну кнопку - жалко!

step962
Offline
Зарегистрирован: 23.05.2011

Переменные val3 и val33 не несут никакой смысловой нагрузки, кроме (и то незначительного) пожирания ресурсов микроконтроллера - в топку их.

drAjbolit
Offline
Зарегистрирован: 23.11.2012

 

AlexFisher пишет:

2 ноги на одну кнопку - жалко!

тут 2 кнопки - по одному выводу на кнопку. Одна увеличивает счётчик - вторая уменьшает.

 

 

drAjbolit
Offline
Зарегистрирован: 23.11.2012

 

step962 пишет:

Переменные val3 и val33 не несут никакой смысловой нагрузки, кроме (и то незначительного) пожирания ресурсов микроконтроллера - в топку их.

Уверен? Я не против - пробуйте без них. Хотелось бы посмотреть на рабочий код.

maksim
Offline
Зарегистрирован: 12.02.2012

drAjbolit пишет:

 

step962 пишет:

Переменные val3 и val33 не несут никакой смысловой нагрузки, кроме (и то незначительного) пожирания ресурсов микроконтроллера - в топку их.

Уверен? Я не против - пробуйте без них. Хотелось бы посмотреть на рабочий код.

Конечно уверен.

//OneClick primer

#define BUTTON 7 
#define BUTTON1 6

boolean val = 0;
boolean val1 = 0;
int count = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("start");
  digitalWrite(BUTTON, 1);
  digitalWrite(BUTTON1, 1);
}

void loop(){
  if (!digitalRead(BUTTON) && !val){
    count++;
    Serial.println("Button 1 on and count");
    Serial.println(count);
    val = 1;
  }
  if (digitalRead(BUTTON)){
    val = 0;
  }

  if (!digitalRead(BUTTON1) && !val1) {
    count--;
    Serial.println("Button 2 on and count");
    Serial.println(count);
    val1 = 1;
  }
  if (digitalRead(BUTTON1)){
    val1 = 0;
  }

}

И не получилось у вас никакого "стопудового" антидребезга, он получился из-за задержки при отправке данных в сериал, так что если уберете вывод в сериал, то дребезг будет.

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

Так что ваш велосипед получился с 3 педалями.

drAjbolit
Offline
Зарегистрирован: 23.11.2012

maksim]</p> <p>[quote=drAjbolit]</p> <p> </p> <p>[quote=step962 пишет:

И не получилось у вас никакого "стопудового" антидребезга, он получился из-за задержки при отправке данных в сериал, так что если уберете вывод в сериал, то дребезг будет.

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

Так что ваш велосипед получился с 3 педалями.

 

Нет - ну странный человек!

Если есть что сказать - просьба с фактами в руках.

Всё отлично работает - и с передачей в порт и без него! 

Просьба - если не хотите проверять и использовать или плохо разбираетесь в вопросе - не занимайтесь троллингом, пожалуйста.

maksim
Offline
Зарегистрирован: 12.02.2012

Ну во-первых вы невежда - это факт.
Во вторых, опишите алгоритм антидребезга в вашем коде, если вы его там видите.
И в третих посматрите стандартный пример Debounce.

drAjbolit
Offline
Зарегистрирован: 23.11.2012

maksim пишет:

Ну во-первых вы невежда.
Во вторых, опишите алгоритм антидребезга в вашем коде, если вы его там видите.
И в третих посматрите стандартный пример Debounce.

Вы вообще в курсе о чём тот пост?

Debounce - только антидребезг и отлично воспроизводит множественное нажатие кнопки - если её не отпускать длительное время.

В выше приведённом примере обрабатывается только одно - первое нажатие - пока не отпустишь кнопку. 

Совсем просто - если нажать и держать кнопку при использовании Debounce - можно получить больше одного срабатывания кнопки.

В моём случае - только одно срабатывание - что и требовалось.

 

Код рабочий. Заявленному функционалу соответствует - что ещё нужно?

Кстати да - Ваш пример рабочий - приму к сведению:) Спасибо.

Borland
Offline
Зарегистрирован: 17.05.2012

 Я никогда не обрабатывал кнопок но читал про антидребезг

решил сперва попробовать сам, не применяя библиотек

у меня кнопка с лампочкой подсветки


         if(digitalRead(BUT1+i)) {
           digitalWrite(GREEN1,HIGH);
           delay(100);  
           while(digitalRead(BUT1+i));
           digitalWrite(GREEN1,LOW);  
           ButtonIsPressed=1
        }

Что я делаю не так , что никакого антидребезга не наблюдаю ?

 

step962
Offline
Зарегистрирован: 23.05.2011

Borland пишет:

 Я никогда не обрабатывал кнопок но читал про антидребезг

решил сперва попробовать сам, не применяя библиотек

у меня кнопка с лампочкой подсветки


         if(digitalRead(BUT1+i)) {
           digitalWrite(GREEN1,HIGH);
           delay(100);  
           while(digitalRead(BUT1+i));
           digitalWrite(GREEN1,LOW);  
           ButtonIsPressed=1
        }

Что я делаю не так , что никакого антидребезга не наблюдаю ?

 

У вас, как и у всех людей, с глазами не так. Вы просто не успеваете заметить загорание-гашение светодиода, если оно происходит с частотой больше 25-30 циклов в секунду.

Стало быть, "не так" вы выполняете проверку отсутствия дребезга, используя инструмент (глаз), неспособный уловить быстроизменяющиеся события. Поставьте вместо светодиода счетчмк и вы удивитесь, с какой скоростью будет увеличиваться его значение.

Ну, про осциллограф я не говорю...

step962
Offline
Зарегистрирован: 23.05.2011

drAjbolit пишет:

Нет - ну странный человек!

Если есть что сказать - просьба с фактами в руках.

Всё отлично работает - и с передачей в порт и без него! 

Каким образом вы считываете показания счетчика без передачи его значения в порт?

drAjbolit
Offline
Зарегистрирован: 23.11.2012

step962 пишет:

Каким образом вы считываете показания счетчика без передачи его значения в порт?

Например поставив светодиод, который срабатывает один раз на одно нажатие - например зажигается на 0,2 секунды.

Сколько раз сработало - столько раз моргнул

Ну и кнопку держу подольше - что б удостовериться в отсутствии повторных срабатываний.

step962
Offline
Зарегистрирован: 23.05.2011

drAjbolit пишет:

step962 пишет:

Каким образом вы считываете показания счетчика без передачи его значения в порт?

Например поставив светодиод, который срабатывает один раз на одно нажатие - например зажигается на 0,2 секунды.

Сколько раз сработало - столько раз моргнул

Стало быть, об управлении яркостью свечения светодиода с помощью ШИМ (это когда много-много следующих друг за другом включений-выключений светодиода, а он сцуко (пардон!) постоянно светится) вы пока что ничего не слышали. Что-ж, ждем от вас новых открытий.

drAjbolit
Offline
Зарегистрирован: 23.11.2012

step962 пишет:

Стало быть, об управлении яркостью свечения светодиода с помощью ШИМ (это когда много-много следующих друг за другом включений-выключений светодиода, а он сцуко (пардон!) постоянно светится) вы пока что ничего не слышали. Что-ж, ждем от вас новых открытий.

[/quote]

Не - ну конечно! Куда уж нам про ШИМ знать...

Вы тут чего такие злые сегодня?

Borland
Offline
Зарегистрирован: 17.05.2012

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

вероятно кнопка хорошая, и дребезгов не дает

step962
Offline
Зарегистрирован: 23.05.2011

Borland пишет:

никакого дребезга ни разу не наблюдал

вероятно кнопка хорошая, и дребезгов не дает

"Ты суслика видишь?

Нет.

И я нет. А он есть!"

Когда-нибудь вы углубите свои знания в области микроконтроллеров, перестанете мигать светодиодом и перейдете к чуть более сложным вещам. И сможете наблюдать дребезг. И даже научитесь с ним бороться.

 

step962
Offline
Зарегистрирован: 23.05.2011

drAjbolit пишет:

Не - ну конечно! Куда уж нам про ШИМ знать...

 

А дребезг - тот-же шим, только нерегулярный и кратковременный (сотые/десятые доли секунды)

Цитата:

Вы тут чего такие злые сегодня?

И чего это неофиты-открыватели самых удивительных вещей сегодня косяком пошли?

drAjbolit
Offline
Зарегистрирован: 23.11.2012

А дребезг - тот-же шим, только нерегулярный и кратковременный (сотые/десятые доли секунды)

 

 

Это гениально Ватсон!

 

step962
Offline
Зарегистрирован: 23.05.2011

На экране осциллографа:

Мат. модель:

 

 

Всегда к вашим услугам, Лестрейд!

Borland
Offline
Зарегистрирован: 17.05.2012

Все правильно, дребезг есть, просто временной  интервал 100 мс который я выделяю на отпускание кнопки, накрывает весь происходящий дребезг  , как бык овцу. Собственно библиотека debonce возвращает не просто значение пина, а его стабильное состояние в пределах интервала, обычно 20 мс.

у Tactile Switch вребя дребезга, меньше 10 мс

maksim
Offline
Зарегистрирован: 12.02.2012

Не верите нам, проверьте сами. Вот ваш же код, но вывод в сериал происходит только после 10-ти стопудовых нажатий.

//OneClick primer

#define BUTTON 7 
#define BUTTON1 6

int val1 = 1;     
int val2 = 1;
int val3 = 1;
int val11 = 1;     
int val22 = 1;
int val33 = 1;
int count = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("start");
  pinMode(BUTTON, INPUT); 
  pinMode(BUTTON1, INPUT); 
  digitalWrite(BUTTON, 1);
}

void loop(){
  val1 = digitalRead(BUTTON);  
  val3 = val1;
  if (val1 == LOW && val1 != val2) {
    count++;
   // Serial.println("Button 1 on and count");
   // Serial.println(count);
    val2 = val3;
  }
  if (val1 == HIGH){
    val2 = 1;
    val3 = 1;
  }

 // val11 = digitalRead(BUTTON1);  
  val33 = val11;
  if (val11 == LOW && val11 != val22) {
    count--;
   // Serial.println("Button 2 on and count");
   // Serial.println(count);
    val22 = val33;
  }
  if (val11 == HIGH){
    val22 = 1;
    val33 = 1;
  }
  /////////////////
  if(count == 10) {  
    Serial.println(count);
    count = 0;
  }
  //////////////////
}

Попробуйте отсчитывать 10 нажатий и смотреть когда count выводится в сериал-монитор.
Так вот в 99% случаев число 10 будет появляться в мониторе на 6 - 8 стопудовое нажатие кнопки, что означает...

Но это справедливо для обычной кнопки без кондесатора или тригера.

И не забудьте написать о результатах.

drAjbolit
Offline
Зарегистрирован: 23.11.2012

maksim пишет:

Не верите нам, проверьте сами. Вот ваш же код, но вывод в сериал происходит только после 10-ти стопудовых нажатий.

Попробуйте отсчитывать 10 нажатий и смотреть когда count выводится в сериал-монитор.

Так вот в 99% случаев число 10 будет появляться в мониторе на 6 - 8 стопудовое нажатие кнопки, что означает...

Но это справедливо для обычной кнопки без кондесатора или тригера.

И не забудьте написать о результатах.

Что - то я не очень пойму.

У меня была задача - 1 нажатие любой длины - 1 срабатывание. Точка.

Нужный результат я получил. На 10 нажатий получается цифра 10.

Всегда. На обоих кнопках - соответственно в сторону увеличения и уменьшения.

Без ложных срабатываний.

Мне больше ничего не нужно - честно-честно.

Я подумал - что не все такие же продвинутые как мои нынешние оппоненты.

Может кому пригодится - не более того.

maksim
Offline
Зарегистрирован: 12.02.2012

+ антидребезг

drAjbolit пишет:

Всё отлично работает - и с передачей в порт и без него! 

drAjbolit пишет:

Код рабочий. Заявленному функционалу соответствует - что ещё нужно?

В постах выше вам написали, что антидребезга у вас нет, а вы заявляете и спорите что есть.
А то что кому-то пригодится неработающий антидребезг это врядли.
Это называется "медвежья" услуга, потому как взяв ваши "труды" как данное, некий человек мог бы очень долго промучиться, не понимая почему происходят ложные нажатия, если он использует код со "стопудовым" антидребезгом. Зачем вводить людей в заблуждение? 

pyro
Offline
Зарегистрирован: 24.11.2012

 if (!digitalRead(BUTTON1) && !val1)

Товарищи, будьте любезны, объясните в чем заключается условие.

step962
Offline
Зарегистрирован: 23.05.2011

ЕСЛИ на выводе BUTTON1 читается низкий уровень (LOW==false==0) И значение переменной val1 равно нулю ТО ...

а если совсем "дословно" то

ЕСЛИ на выводе BUTTON1 читается НЕ высокий уровень (HIGH~true<>0) И значение переменной val1 НЕ неравно нулю (любое отличное от нуля значение суть true) ТО ...

maksim
Offline
Зарегистрирован: 12.02.2012

drAjbolit пишет:

Нужный результат я получил. На 10 нажатий получается цифра 10.

Всегда. На обоих кнопках - соответственно в сторону увеличения и уменьшения.

Без ложных срабатываний.

Что за кнопки используете?

pyro
Offline
Зарегистрирован: 24.11.2012

Вы, скорее всего, используете кнопки хорошие, с минимальным дребезгом. У меня через раз произошли ложные ссрабатывания.

std
Offline
Зарегистрирован: 05.01.2012

я может быть неправ, но

boolean holdflag[20];
byte i;

void setup(void){
  for(i=0;i<20;i++){
    holdflag[i]=0;
    pinMode(i,INPUT);
  }
}

void loop(void){
  for(i=0;i<20;i++){
    if(!holdflag[i]){            // key weren't pressed, set flag on press
      if(digitalRead(i)==0) holdflag[i]=1;
    }else{                       // key were pressed, clear flag on release
      if(digitalRead(i)==1) holdflag[i]=0;
    }
  }
}

boolean btnstate(byte btnnumber){
  return holdflag[btnnumber];
}
step962
Offline
Зарегистрирован: 23.05.2011

И правы, и неправы...

Антидребезг у вас присутствует - но как результат очень медленного алгоритма - пока вы в своем цикле последовательно опросите 20 выводв, да еще с помощью Arduino-оберток, а не посредством прямого опроса портов, пройдет около 4 мсек - время вполне достаточное для завершения переходных процессов в контактах кнопки.

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

 PS: "очень медленный" - понятие, естественно, о-о-о-очень относительное. Если "слушать" выполняемые человеком нажатия, то 250 опросов каждой кнопки в секунду более, чем достаточно для надежной реакции. Но вот уже выключатель, используемый для подсчета оборотов вала даигателя (пресловутый механический энкодер), может легко создать проблемы с детекцией.

std
Offline
Зарегистрирован: 05.01.2012

не, это в примере, на все 20 входов. реально то меньше надо, надеюсь. и да, этот костыль только для кнопок.