Очень интересная логическая задача, на опрос состояния кнопок (help)

Тема в разделе "Arduino & Shields", создана пользователем yozhikov.d, 17 окт 2018.

  1. yozhikov.d

    yozhikov.d Нерд

    Друзья, добрый день!) История такая: пишу цикл проверки состояния кнопок. Условие: есть 2 тактовые кнопки, которые должны работать по ИДЕЕ в взаимоисключающем состоянии, другими словами если на кнопке 1 - HIGH, то на кнопке 2 обязательно - LOW, и если HIGH у кнопки, то должно выводиться в сериал определенное сообщение. Так вот, возможна такая ситуация (не спрашивайте, как, почему, зачем, откуда корни), что эти кнопки, будут не в взаимоисключающем состоянии, обе либо в HIGH либо в LOW, что является состоянием ошибки, и на это событие (когда обе в одинаковом состоянии), тоже нужно реагировать определенным сообщением. Я написал определенный код, который делает прерывание событий + обработка дребезга, сравнивает состояние друг с другом и все хорошо, если нажимаешь кнопки по очереди, но есть одно маленькое НО: в моем проекте состоянием ошибки, является ТО состояние, когда кнопки находятся в одинаковом состоянии некоторое время (скажем 1 секунду), а рабочий режим кнопок их поочередное нажатие, другими словами, когда я нажал кнопку 1 и РЕЗКО ее отпускаю и нажимаю кнопку 2, в момент переключения, когда я отпустил кнопку 1, программа сравнивает свое состояние со 2 кнопкой на, которой LOW, и думает, что это состояние ошибки (мой кривокод), вот, а это не состояние ошибки, а рабочий момет переключения, как мне это пофиксить, надеюсь у меня получилось объяснить, код прикладываю)
    Код (C++):

    //1
    const int switchPin1 = 2;
    boolean switchPin1_memory = 0;
    boolean switchPin1_now_memory = 0;
    unsigned long switchPin1_lastPress;
    boolean error1 = true;
      //2
    const int switchPin2 = 3;
    boolean switchPin2_memory = 0;
    boolean switchPin2_now_memory = 0;
    unsigned long switchPin2_lastPress;
    boolean error2 = false;

    void setup() {
    pinMode (switchPin1, INPUT);
    pinMode (switchPin2, INPUT);
    Serial.begin(9600);
    while(!Serial);
    }

    void loop() {

      //порт 1
     
    switchPin1_now_memory = digitalRead(switchPin1);
      if (switchPin1_now_memory == 1 && switchPin1_memory == 0 && millis() - switchPin1_lastPress > 100)
      {
          switchPin1_memory = true;
          switchPin1_lastPress = millis();
           if (switchPin2_memory == switchPin1_memory)
               {
                error1 = !error1;
                Serial.println("Ошибка1");
                error1 = !error1;
               }
                   if (error1 != error2)
                   {
                     error1 = !error1;
                     Serial.println("Кнопка 1 нажата");
                   }
     
      }
     
      if (switchPin1_now_memory == 0 && switchPin1_memory == 1)
      {
          switchPin1_memory = false;
          if (switchPin2_memory == switchPin1_memory)
          {
          error1 = !error1;
          }
          if (error1 != error2)
          {
          Serial.println("Ошибка11");
          }
         
       
      }

    // Второй порт
     
      switchPin2_now_memory = digitalRead(switchPin2);
     
      if (switchPin2_now_memory == 1 && switchPin2_memory == 0 && millis() - switchPin2_lastPress > 100){
          switchPin2_memory = true;
          switchPin2_lastPress = millis();
          if (switchPin2_memory == switchPin1_memory)
            {
              error2 = !error2;
              Serial.println("Ошибка2");
              error2 = !error2;
             }
                  if (error1 != error2)
                         {
                          error2 = !error2;
                          Serial.println("кнопка 2 нажата");
                         
                         }
       
      }
     
      if (switchPin2_now_memory == 0 && switchPin2_memory == 1){
         switchPin2_memory = false;
          if (switchPin2_memory == switchPin1_memory)
         {
         error2 = !error2;
         }
         if (error1 != error2)
         {
          Serial.println("Ошибка2");
         }
       
      }
      }
     
     
  2. DIYMan

    DIYMan Guest

    Для того, чтобы научиться правильно писать код - существует один из приёмов: вы в комментариях, строка за строкой - описываете то, как должен работать код. Потом - наполняете файл кодом, вставляя его между комментариями.

    В вашем случае, с алгоритмической точки зрения, должен быть флаг "состояние кнопок одинаковое и не менялось N времени". Скажем, это может быть переменная типа unsigned long, куда записывается время, получаемое с millis().

    Далее, для каждой кнопки - у вас есть такое понятие, как событие: т.е. соответствие каким-то условиям, по наступлению которых можно понять - кликнута ли кнопка, нажата ли кнопка, нажата и удерживается - это всё как пример.

    По итогу получаем что: у вас всё равно есть регулярный опрос состояния пинов кнопок. В этом опросе вы делаете следующее: если состояние кнопок РАЗНОЕ - то сбрасываете флаг одинаковости состояния кнопок в millis(). Если оно одинаковое, то проверяете - как давно был сброс флага одинаковости состояния кнопок. Если дольше, чем N времени - это ошибка, о которой надо сигнализировать.

    Таким образом, мы алгоритмически разделили несколько частей кода, сделав их отдельными единицами, оперировать которыми в коде - гораздо легче, чем мешать весь код в большую простыню ;)

    Надеюсь, помог.
     
    yozhikov.d нравится это.
  3. parovoZZ

    parovoZZ Гуру

    необходимо научиться правильно составлять алгоритм. Код это уже десятое дело.
     
  4. DIYMan

    DIYMan Guest

    Ну так я об этом и писал, собственно. Пока в комментариях расписываешь - по сути, составляешь алгоритм, пусть даже в первом грубом приближении.
     
  5. parovoZZ

    parovoZZ Гуру

  6. yozhikov.d

    yozhikov.d Нерд

    Да, спасибо) Я думал в эту сторону, просто не знаю, как грамотней завернуть мб в строчку
    Код (C++):
    switchPin2_memory == switchPin1_memory
    где я проверяю на "одинаковость" состояния, вставить еще одно временное условие? Вы имели это ввиду?
     
  7. DIYMan

    DIYMan Guest

    Смотрите, как это может примерно выглядеть в псевдокоде:
    Код (C++):
    state buttonState1 = button1.getState();
    state buttonState2 = button2.getState();

    if(buttonState1 != buttonState2)
    {
        // состояние кнопок - разное, нормальный режим работы
        stateCheckTimer = millis(); // сбросили таймер
        stateTimerOn = false;
     
    }
    else
    {
        // состояние кнопок - одинаковое, надо проверить, какое время оно удерживается
        if(!stateTimerOn)
        {
            stateTimerOn = true;
            stateCheckTimer = millis();
        }
        else
        {
            if(millis() - stateCheckTimer > INTERVAL)
            {
                alert("АВАРИЯ!");
            }
        }
    }
     
     
    yozhikov.d нравится это.
  8. yozhikov.d

    yozhikov.d Нерд

    Да да да, все дошло) Спасибо большое)