0

My current setup has the arduino in 'stand-by' power saving mode, therefore i am unable to use any means of a traditional soft debouncer, such as Bounce2, as far as I know.

I went ahead and attached the buttons to pin change interrupts, since I have one button on each bank, i.e. pin 7 and pin 11.

The technique I'm using doesn't seem to be behaving since the routines are being fired too regularly (inconsistently), and at the rising edge too.

I have the pins set to use their internal pull-ups.

Using the PCI library:

void pciSetup(byte pin)
{
  *digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin));  // enable pin
  PCIFR  |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
  PCICR  |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the 

pciSetup(POWER_SWITCH);
pciSetup(SELECTOR_BTN);

// check if IR IN or Power switch
ISR (PCINT0_vect) // handle pin change interrupt for D8 to D13 here
{

  if (digitalRead(POWER_SWITCH) == LOW)
  {
    noInterrupts();
    unsigned long last_millis = millis();
    while (millis() - last_millis >= 500);
    ir_power_pressed = true;
  }
  interrupts();
}

ISR (PCINT2_vect) // handle pin change interrupt for D0 to D7 
  noInterrupts();
  unsigned long last_millis = millis();
  while (millis() - last_millis >= 500);
  ir_selector_pressed = true;
  interrupts();
}

Am I doing something silly?

Update 1

As suggested in the comments, i've adjusted the code, but it still triggers on the rising edge, and a few times rapidly at the falling edge.

ISR (PCINT2_vect) // handle pin change interrupt for D0 to D7 here
{
  if (digitalRead(SELECTOR_BTN) == LOW)
  {
    noInterrupts();
    static unsigned long last_millis = millis();
    if (millis() - last_millis >= 500)
    {
      ir_selector_pressed = true;
      interrupts();
    }
  }
}
4
  • Hardware debounce with capacitor and resistor?
    – Mike
    Commented Sep 25, 2017 at 1:59
  • Make last_millis static, and replace the while loop with an if statement.
    – tttapa
    Commented Sep 25, 2017 at 7:55
  • @Mike I would do that, but i've put a new MCU in a pre-existing PCB so there's not much space, it'll be my last resort. Commented Sep 25, 2017 at 11:24
  • @tttapa I did so, but it's still triggering on the rising edge, and firing very fast a few times at the falling edge. Please see the update for the updated code. Commented Sep 25, 2017 at 11:25

1 Answer 1

0

You don't update last_millis.
Also, you don't know whether SELECTOR_BTN went from HIGH to LOW or whether another pin fired the interrupt while SELECTOR_BTN was low. Remember the previous state to solve this.

const unsigned long debounceTime = 50;
volatile bool ir_selector_pressed = false;

ISR (PCINT2_vect) { // handle pin change interrupt for D0 to D7 here
  static unsigned long previousStateChangeMillis = 0;
  static bool previousPinState = HIGH;

  bool pinState = digitalRead(SELECTOR_BTN);
  if (pinState != previousPinState) { // ignore pin changes of pins other than SELECTOR_BTN
    if (pinState == LOW) { // only falling events
      if ((millis() - previousStateChangeMillis) > debounceTime) { // debounce
        ir_selector_pressed = true;
      }
    }
    previousPinState = pinState;
    previousStateChangeMillis = millis();
  }
}
2
  • Thank you, this works very well. Is there a reason why you're not deactivating interrupts during the ISR body? Commented Sep 26, 2017 at 12:31
  • 1
    When an interrupt service routine (ISR) is called, interrupts are automatically disabled. Interrupts are automatically enabled when returning from an ISR. It is not necessary to explicitly enable nor disable interrupts inside of an ISR. The processor does these two things for you. Source
    – tttapa
    Commented Sep 26, 2017 at 13:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.