rising interrupt runs on both push and release

Hi,
I've used interrupts before for incoming clock signals and had no problem. This time I am trying to use buttons.
I cannot understand why even though I have defined the ISR to run on rising signal I see that the ISRs run both when pushing the button and when releasing it.
Is this possibly because of the signal bouncing from the button? If yes is there a way around it with code without having to use hardware debounce?

const int Button1 = 2;
const int Button2 = 3;

bool wasButton1 = false;
bool wasButton2 = false;

#define debounceTime 200
int prevMilis = 0;

static unsigned long button1_last_interrupt_time = 0;
static unsigned long button2_last_interrupt_time = 0;

void wakeupButton1() // used when waking up by belly button
{
  unsigned long button1_interrupt_time = millis();
  if (button1_interrupt_time - button1_last_interrupt_time > debounceTime)
  {
  wasButton1 = true;
  }
  button1_last_interrupt_time = button1_interrupt_time;
}

void wakeupButton2() // used when waking up by belly button
{
  unsigned long button2_interrupt_time = millis();
  if (button2_interrupt_time - button2_last_interrupt_time > debounceTime)
  {
  wasButton2 = true;
  }
  button2_last_interrupt_time = button2_interrupt_time;
}



void setup() {
  Serial.begin(9600);

  pinMode(Button2, INPUT_PULLUP);
  pinMode(Button1, INPUT_PULLUP);

  attachInterrupt(0, wakeupButton1, RISING);  // interrupt for belly button
  attachInterrupt(1, wakeupButton2, RISING);  // interrrupt for hand button

  Serial.println("Setup ended");
  delay(1000);
}

void loop()
{
  if (wasButton1)
  {
    wasButton1 = false ;
    Serial.println("button1 pressed");
  }


  if (wasButton2)
  {
    wasButton2 = false ;
    Serial.println("button2 pressed");

  }
}

Any help would be appreciated.
Thanks,

Elan

variables used in ISR and main body should be declared volatile
millis() won't get updated in your ISR
Yes you will experience bouncing, thus multiple triggering of your ISR

capturing buttons press by human is a slow process, there is no need for ISR for this... handle that directly in the loop() and deal with debounce there.

This is the ISR based debounce I use all the time.

volatile bool wasButton1 = false;  // <<<<<<<<<<<<<<<<<<<<<<<<<< note the volatile before the declaration
                                   // this forces the microprocessor to reload this variable each time it is used to make sure it is up to date
void wakeupButton1() // used when waking up by belly button
{
  unsigned long cTime;
  static unsigned long EdgeTime;
  unsigned long debounceTime = 10000; // adjust to meet your needs this is a guess
  cTime = micros();
  if ((cTime - EdgeTime) >= debounceTime ) {
    EdgeTime = cTime;
    wasButton1 = true;
  }
}

Try this out and let us know what you think :slight_smile:
Z

a small doubt on this :slight_smile:

  unsigned long debounceTime 10000; // adjust to meet your needs this is a guess

J-M-L:
a small doubt on this :slight_smile:

  unsigned long debounceTime 10000; // adjust to meet your needs this is a guess

10 milliseconds? should it be longer like 100 milliseconds = 100000 in microseconds

well my point was the missing = sign :slight_smile:

indeed need to think in terms of micro-seconds and 10 to 15ms usually good enough

J-M-L:
well my point was the missing = sign :slight_smile:

indeed need to think in terms of micro-seconds and 10 to 15ms usually good enough

thanks fixed for the future readers below in my post

There is a problem with these lockout type debounce routines which accept the initial response and then lock out any additional interrupts for a subsequent period.

The interrupt pin is configured for INPUT_PULLUP.

The interrupt is set for RISING. On the button press which gives a lead falling edge, any bounce high on that edge will be accepted as a valid interrupt.

Then if the release of the button is after the lock out time, you will see another interrupt. Your code had a 200ms lock out, so you need a very quick finger to get the release within the timeout window.

If you set the interrupt for FALLING you will see an interrupt on the lead edge, and again if the button release is longer than the lock out time, you can see the bounce on the rising edge as the button is released.

If you make the lock out time long, then the button becomes unresponsive. Deciding between RISING and FALLING and selecting a lock out time takes some experimentation.

As J-M-L has suggested you do not need interrupts to read buttons. If you put the button read in loop() you can use debounce routines which rely on the persistance of readings, not lock out.

It's not a problem, it's an operational decision. Do you want the thing to respond immediately as soon as it sees the slightest glitch of a button press or do you want it to wait until you really mean it, like the button was held down for 200ms?

Either option is appropriate in different circumstances. The fast-response option is the one usually chosen but it doesn't have to be that way.

The reason I'm using interrupts for this is because ultimately I want my arduino to be put to sleep in the beginning of my loop and wake up once one of the buttons are pressed and after going throught "ifs" go back to sleep until the next button is pressed.
I noticed myself the mistake with the rising and falling options and changed that.

Would detaching the interrupts in my ISRs essentially do the job of quasi debouncing for me? If I detach the interrupts then there will be no reason for the ISR to be called again until I active them right before setting the arduino to sleep.
Does this logic sound correct?

Would detaching the interrupts in my ISRs essentially do the job of quasi debouncing for me? If I detach the interrupts then there will be no reason for the ISR to be called again until I active them right before setting the arduino to sleep.
Does this logic sound correct?

Sounds like a good approach to me, but if there is a queued interrupt from the bounce, you should clear any interrupt flags set.

See Nick Gammon’s tutorial on using of interrupts for waking from sleep.
http://gammon.com.au/interrupts