Еще один вопрос новичка :) (кнопки и дребезг)

Тема в разделе "Arduino & Shields", создана пользователем Iulia, 18 апр 2018.

  1. Iulia

    Iulia Нерд

    Добрый день! Добралась до эксперимента 10 (http://wiki.amperka.ru/конспект-arduino:кнопочный-переключатель).

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

    Свой скетч прилагаю. Работает. Но у меня, кажется, отсутствует защита от дребезга второй кнопки.

    1. Нужно ли это делать, если все равно 10 миллисекунд контроллер выжидает после нажатия первой?

    И собственно, если нужно, то
    2. как сделать правильно? :)) Не могу сообразить.
     

    Вложения:

  2. Iulia

    Iulia Нерд

    Вообще получается, что у меня просто срабатывает первая кнопка при нажатой второй... Кривовато как-то... :(
     
  3. mcureenab

    mcureenab Гуру

    Кому надо загружать твой ino файл? Выкладывай исходник с разметкой в сообщение.
     
  4. Iulia

    Iulia Нерд

    Это как? Вот так?

    #define BUTTON_PIN1 3
    #define BUTTON_PIN2 5
    #define LED_PIN 13

    boolean button1WasUp = true; // кнопка 1 отпущена
    boolean button2WasUp = true; // кнопка 2 отпущена
    boolean ledEnabled = false; // не горит

    void setup()
    {
    pinMode(LED_PIN, OUTPUT);
    pinMode(BUTTON_PIN1, INPUT_PULLUP);
    pinMode(BUTTON_PIN2, INPUT_PULLUP);
    }

    void loop()
    {
    // определить момент «клика» несколько сложнее, чем факт того,
    // что кнопка сейчас просто нажата. Для определения клика мы
    // сначала понимаем, отпущена ли кнопка прямо сейчас...
    boolean button1IsUp = digitalRead(BUTTON_PIN1);
    boolean button2IsUp = digitalRead(BUTTON_PIN2);

    // ...если «кнопка была отпущена и (&&) не отпущена сейчас»...
    if (button1WasUp && !button1IsUp ) {
    // ...может это «клик», а может и ложный сигнал (дребезг),
    // возникающий в момент замыкания/размыкания пластин кнопки,
    // поэтому даём кнопке полностью «успокоиться»...
    delay(10);
    // ...и считываем сигнал снова
    button1IsUp = digitalRead(BUTTON_PIN1);
    button2IsUp = digitalRead(BUTTON_PIN2);
    if (!button1IsUp && !button2IsUp) { // если она всё ещё нажата...
    // ...это клик! Переворачиваем сигнал светодиода
    ledEnabled = !ledEnabled;
    digitalWrite(LED_PIN, ledEnabled);
    }
    }
    // запоминаем последнее состояние кнопки для новой итерации
    button1WasUp = button1IsUp;
    button2WasUp = button2IsUp;
    }
     
  5. mcureenab

    mcureenab Гуру

    И кнопочкой Код [<>] воспользоваться для разметки. А то бывает пунктуация из кода теряется.
     
  6. Iulia

    Iulia Нерд

    Код (C++):
    #define BUTTON_PIN1  3
    #define BUTTON_PIN2  5
    #define LED_PIN     13
    boolean button1WasUp = true;  // кнопка 1 отпущена
    boolean button2WasUp = true;  // кнопка 2 отпущена
    boolean ledEnabled = false;  // не горит
    void setup()
    {
      pinMode(LED_PIN, OUTPUT);
      pinMode(BUTTON_PIN1, INPUT_PULLUP);
      pinMode(BUTTON_PIN2, INPUT_PULLUP);
    }
    void loop()
    {
      // определить момент «клика» несколько сложнее, чем факт того,
      // что кнопка сейчас просто нажата. Для определения клика мы
      // сначала понимаем, отпущена ли кнопка прямо сейчас...
      boolean button1IsUp = digitalRead(BUTTON_PIN1);
      boolean button2IsUp = digitalRead(BUTTON_PIN2);
      // ...если «кнопка была отпущена и (&&) не отпущена сейчас»...
      if (button1WasUp && !button1IsUp ) {
        // ...может это «клик», а может и ложный сигнал (дребезг),
        // возникающий в момент замыкания/размыкания пластин кнопки,
        // поэтому даём кнопке полностью «успокоиться»...
        delay(10);
        // ...и считываем сигнал снова
        button1IsUp = digitalRead(BUTTON_PIN1);
        button2IsUp = digitalRead(BUTTON_PIN2);
       if (!button1IsUp && !button2IsUp) {  // если она всё ещё нажата...
          // ...это клик! Переворачиваем сигнал светодиода
          ledEnabled = !ledEnabled;
          digitalWrite(LED_PIN, ledEnabled);
       }
      }
      // запоминаем последнее состояние кнопки для новой итерации
      button1WasUp = button1IsUp;
      button2WasUp = button2IsUp;
    }
     
  7. mcureenab

    mcureenab Гуру

    А тебе как надо?
     
  8. parovoZZ

    parovoZZ Гуру

    Решено же?
     
  9. fogary

    fogary Гик

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

    parovoZZ Гуру

    Зачем по отдельности? Считать целиком регистр порта и по маске проверить биты пинов. Делов на пар-тройку строчек кода.
     
  11. mcureenab

    mcureenab Гуру

    Переключение диода происходит при нажимании кнопок. Чтобы фиксировать переход нужно или программу загонять в состояние нажаты/не нажаты. Или хранить предыдущее состояние самих кнопок.
     
  12. mcureenab

    mcureenab Гуру

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

    boolean twin_btn2 = (digitalRead(BUTTON_PIN1)==LOW?1:0) + (digitalRead(BUTTON_PIN2)==LOW?1:0) == 2;
    if( twin_btn2 && !twin_btn1 ) -- Две кнопки были нажаты вместе.
     
  13. Iulia

    Iulia Нерд

    Симметрично:) Просто если кнопка 2 нажата, тогда кнопкой 1 я могу включать и выключать светодиод. А если кнопка 1 нажата, то кнопкой 2 я не могу этого делать. Вот мне и кажется, что получилось криво и мой код не является верным решением задачи:))
     
  14. Iulia

    Iulia Нерд

    Ну если не нужно отлавливать, то да. Я бы вообще тогда код никакой не вводила а тупо соединила кнопки последовательно :)
     
  15. Iulia

    Iulia Нерд

    Это для меня пока слишком умно...

    А если вот так сделать?

    Код (C++):
    #define BUTTON_PIN1  3
    #define BUTTON_PIN2  5
    #define LED_PIN     13
    boolean button1WasUp = true;  // кнопка 1 отпущена
    boolean button2WasUp = true;  // кнопка 2 отпущена
    boolean ledEnabled = false;  // не горит


    void setup()
    {
      pinMode(LED_PIN, OUTPUT);
      pinMode(BUTTON_PIN1, INPUT_PULLUP);
      pinMode(BUTTON_PIN2, INPUT_PULLUP);
    }
    void loop()
    {
      boolean button1IsUp = digitalRead(BUTTON_PIN1);
      boolean button2IsUp = digitalRead(BUTTON_PIN2);
      // ...если «кнопки были отпущены и (&&) не отпущены сейчас»...
      if (button1WasUp && !button1IsUp && button1WasUp && !button1IsUp ) {
        delay(10);
      button1IsUp = digitalRead(BUTTON_PIN1);
      button2IsUp = digitalRead(BUTTON_PIN2);

          boolean twin_btn = (button1IsUp == LOW) &&  (button2IsUp == LOW);
          if ( twin_btn )
          { ledEnabled = !ledEnabled;
            digitalWrite(LED_PIN, ledEnabled);
          }
        }
        button1WasUp = button1IsUp;
        button2WasUp = button2IsUp;
      }
    Так-то вроде бы работает. И проблема дребезга решена, кажется.
     
  16. mcureenab

    mcureenab Гуру

    Вроде нормально, только зачем анализ нажатия кнопок делать раздельно?

    Мониторь сразу изменение

    Код (C++):
          boolean twin_btn = (button1IsUp == LOW) &&  (button2IsUp == LOW);
     
  17. Iulia

    Iulia Нерд

    Вот так?
    Код (C++):
    #define BUTTON_PIN1  3
    #define BUTTON_PIN2  5
    #define LED_PIN     13
    boolean twin_btn_last = false;  //  кнопки отпущены
    boolean ledEnabled = false;  //  не горит
    void setup()
    {
      pinMode(LED_PIN, OUTPUT);
      pinMode(BUTTON_PIN1, INPUT_PULLUP);
      pinMode(BUTTON_PIN2, INPUT_PULLUP);
    }
    void loop()
    {
      boolean button1IsUp = digitalRead(BUTTON_PIN1);
      boolean button2IsUp = digitalRead(BUTTON_PIN2);
      boolean twin_btn = (button1IsUp == LOW) &&  (button2IsUp == LOW);
       if (twin_btn_last && !twin_btn) {
            delay(10);
      button1IsUp = digitalRead(BUTTON_PIN1);
      button2IsUp = digitalRead(BUTTON_PIN2);
       if (twin_btn); { ledEnabled = !ledEnabled;
            digitalWrite(LED_PIN, ledEnabled);
     
      }
               
      }
       
        twin_btn_last = twin_btn;
      }  
    Тут все в порядке с логикой? Получается twin_btn работает как И-НЕ? Поэтому я использую в качестве условия 0(штрих Шеффера)0=1, так?

    Работает вроде стабильно!
     
  18. Iulia

    Iulia Нерд

    Правда, срабатывает в момент отпускания кнопки, а не нажатия :) Ну я поиграюсь ещё, может смогу сделать так, чтобы при нажатии срабатывало:)
     
  19. mcureenab

    mcureenab Гуру

    LOW на HIGH поменять
     
  20. mcureenab

    mcureenab Гуру

    Тут надо повторно вычислить twin_btn

    Код (C++):
      button2IsUp= digitalRead(BUTTON_PIN2);
       twin_btn = ....
       if (twin_btn); { ledEnabled = !ledEnabled;