Debouncing или проблема с моим кодом?

Я использую простой микропереключатель на контакте 2, чтобы активировать внешнее прерывание.

void pause()
{
  Serial.print("\n\nPause\n\n");
  delay(1000);
}

void setup()
{
  pinMode(2, INPUT_PULLUP);
  attachInterrupt(0, pause, RISING);
  Serial.begin(9600);
  delay(1000);
}

void loop()
{
  Serial.print("\nGoing");
  delay(100);
}

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

 введите описание изображения здесь>> </a> </p>

<p> Чтобы уточнить, между любыми из </p>

<p> Это просто какое-то серьезное разделение, заставившее моего Arduino найти множество растущих экземпляров? или есть какая-то проблема в моем коде? </p></body></html>

2 голоса | спросил patrick jackson 19 AM00000010000002531 2017, 01:55:25

4 ответа


1

У меня страница об использовании переключателей , но поскольку я не хочу давать link-only answer. Я опишу здесь.


Обнаружение изменений переключателя

Необходимо определить переход . То есть:

  • Он был закрыт и теперь открыт.

Или:

  • Он был открыт и теперь закрыт.

Для этого вам нужно «запомнить» предыдущее состояние коммутатора и обнаружить изменения, например:

 const byte switchPin = 8;
byte oldSwitchState = HIGH;  // assume switch open because of pull-up resistor

void setup ()
  {
  Serial.begin (115200);
  pinMode (switchPin, INPUT_PULLUP);
  }  // end of setup

void loop ()
  {
  // see if switch is open or closed
  byte switchState = digitalRead (switchPin);

  // has it changed since last time?
  if (switchState != oldSwitchState)
    {
    oldSwitchState =  switchState;  // remember for next time 
    if (switchState == LOW)
       {
       Serial.println ("Switch closed.");
       }  // end if switchState is LOW
    else
       {
       Serial.println ("Switch opened.");
       }  // end if switchState is HIGH
    }  // end of state change

  // other code here ...

  }  // end of loop

Этот код ищет изменения и только отображает что-то, когда переключатель изменяется.


Кстати, вы не должны делать ни delay, ни Serial.print внутри прерывания, так как оба полагаются на прерывания, являющиеся активными, а прерывания не активны внутри ISR.


дребезг

Простая методика заключается в том, чтобы построить небольшую задержку, например 10 миллисекунд (мс). Например:

 const byte switchPin = 8;
byte oldSwitchState = HIGH;  // assume switch open because of pull-up resistor
const unsigned long debounceTime = 10;  // milliseconds

void setup ()
  {
  Serial.begin (115200);
  pinMode (switchPin, INPUT_PULLUP);
  }  // end of setup

void loop ()
  {
  // see if switch is open or closed
  byte switchState = digitalRead (switchPin);

  // has it changed since last time?
  if (switchState != oldSwitchState)
    {
    oldSwitchState =  switchState;  // remember for next time 
    delay (debounceTime);   // debounce
    if (switchState == LOW)
       {
       Serial.println ("Switch closed.");
       }  // end if switchState is LOW
    else
       {
       Serial.println ("Switch opened.");
       }  // end if switchState is HIGH
    }  // end of state change

  // other code here ...

  }  // end of loop

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


Отладка без задержки

Вышеприведенный код хорош в простых приложениях, и если вы его протестируете, вы должны обнаружить, что сообщение «Switch closed». и «Переключатель открыт». должен происходить только один раз при нажатии выключателя. Но есть проблема. Если вы немного повеситесь на форумах Arduino, вы, вероятно, увидите, что люди говорят вам: «Не используйте delay". Для этого есть разные причины, и не в последнюю очередь это то, что использование задержки заставляет ваш код делать что-либо еще полезное (например, тестирование датчиков, управление моторами, мигание светодиодов и т. Д.).

В приведенном ниже коде не используется delay, а скорее проверяется на время, прошедшее после нажатия на переключатель, и видит, «debounceTime» (в данном случае 10 мс) истек. Если нет, он игнорирует переход.

 const byte switchPin = 8;
byte oldSwitchState = HIGH;  // assume switch open because of pull-up resistor
const unsigned long debounceTime = 10;  // milliseconds
unsigned long switchPressTime;  // when the switch last changed state

void setup ()
  {
  Serial.begin (115200);
  pinMode (switchPin, INPUT_PULLUP);
  }  // end of setup

void loop ()
  {
  // see if switch is open or closed
  byte switchState = digitalRead (switchPin);

  // has it changed since last time?
  if (switchState != oldSwitchState)
    {
    // debounce
    if (millis () - switchPressTime >= debounceTime)
       {
       switchPressTime = millis ();  // when we closed the switch 
       oldSwitchState =  switchState;  // remember for next time 
       if (switchState == LOW)
          {
          Serial.println ("Switch closed.");
          }  // end if switchState is LOW
       else
          {
          Serial.println ("Switch opened.");
          }  // end if switchState is HIGH

       }  // end if debounce time up

    }  // end of state change

  // other code here ...

  }  // end of loop

Дополнительная информация о сайте Arduino: http://arduino.cc/en/Tutorial/Debounce


  

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

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

Я предлагаю редизайн. Например, в вашем основном цикле вы можете обнаружить нажатие переключателя, а затем ничего не делать до тех пор, пока оно не будет нажато снова. Например, где у меня был «другой код здесь» в моем примере:

 static bool switchWasPressed;

if (switchWasPressed)
  {
  // do nothing
  }
else
  {
  // do what you want to do continuously
  }

Теперь в коде, который обнаруживает нажатие переключателя, вы переключаете switchWasPressed. Поэтому вместо:

 Serial.println ("Switch closed.");

Вы помещаете:

 switchWasPressed = !switchWasPressed;  // toggle switch press state
ответил Nick Gammon 19 AM00000030000001131 2017, 03:28:11
1

Вам действительно нужно использовать прерывание для отладки коммутатора? Если нет, эта библиотека может работать для вас: https://playground.arduino.cc/добавления /код /​​Debounce.zip . Он прост в использовании и предполагает, что вы используете нормально разомкнутый переключатель с одним соединением с землей, а другой - с контактом 4 на Arduino.

    #include <Debounce.h>
    const byte SWITCH = 4;

    Debounce debouncer = Debounce(50, SWITCH);

    void setup(){
      Serial.begin(9600);
      pinMode(SWITCH, INPUT_PULLUP);
    }

    void loop(){
      if(debouncer.update()){
        if(debouncer.read() == 0){
          Serial.println("Button Pressed");
        }
        else if(debouncer.read() == 1){
          Serial.println("Button Released");
        }
      }
    }
ответил VE7JRO 21 AM00000040000004831 2017, 04:34:48
0

Да, это отскакивает от вашей кнопки.

Вы видите это, потому что delay() не работает и не может использоваться в прерывании.

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

ответил Majenko 19 AM00000020000001731 2017, 02:00:17
0

ваш код работает как закодированный - работает ли он так, как ожидалось, неизвестно.

в основном, isr запускается на первом фронте, а выполнение выполняется в isr, а выполнение возвращается через секунду.

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

не является эффективной стратегией debouncing.

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

ответил dannyf 19 AM00000020000005331 2017, 02:35:53

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132