FALLING interrupts works same as CHANGE

So, i have a Arduino pro mini and a scatch from interrupt examples:

const byte ledPin = 13;
const byte interruptPin = 2;
volatile byte state = LOW;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), blink, FALLING);

void loop() {
  digitalWrite(ledPin, state);

void blink() {
  state = !state;

and a normally-on button connected in this way

So, when I press button signal on D2 is LOW. When i release it, signal goes to HIGH. I checked with oscilloscope.
What do i need: call FALLING interrupt on D2 pin (int0) when i presss button.
What i actually have: interrupt is calling twice: when i push button and when i release it. (working same as CHANGE interrupt).
But! RISING interrupt works as it should, so button connection is right.
What is wrong with my button?

It sounds as if your button is bouncing - which is very common. I can’t think why the bounce might be different for a RISING interrupt.

The usual way to deal with bouncing is to leave a short interval between reads of the switch pin. That can be done using interrupts but it is a bit more complex.

if this is for a project in which a human is pressing a button there should be no need to use an interrupt to detect the switch press because humans are VERRRY SLOOOWWW.


You have switch bounce creating a second falling interrupt when you release the button. Google the term switch bounce or contact bounce. Here's a link to one of the best articles on switch bounce

Thank you for answers. I also tried making so

void blink()//my interrupt function
  static unsigned long millis_prev = 0;
  if(millis()-100 > millis_prev)
      led = !led;
      millis_prev = millis();

and had the same problems.

Using a lock out debounce can be problematic depending on how fast the button is released. If your button is held pressed for more than 100 ms which is pretty short for a human, you can still see an interrupt on the release. I agree with Robin2 that there is no need for interrupts with buttons.

if(millis()-100 > millis_prev)

Tor prevent any issues with millis() rollover, this is best constructed as

if(millis()- millis_prev >100)

Ok, i will consider other ways to check button state.
But still, what is wrong with interrupt? Im curious about it

But still, what is wrong with interrupt? Im curious about it

Interrupts are harder to debounce with software, and its impossible I think, if you are trying to test for a stable state which persists for a period of time, rather than just lock out any subsequent changes during a time period after the first change.

The experience on this forum is that it is very easy for beginners to use interrupts improperly, and they run into subsequent problems.

A great tutorial on interrupts is here

I tried these (3 left schemes), they didnt help. Im 99% shure that its controller's fault

On your original code you use input_pullup but you also have a pull-down resistor? Why?

That is bad copy/paste
pinMode(interruptPin, INPUT_PULLUP);
is unwanted

Contact bounce can happen anything from zero to hundreds of times, which is why its a poor idea to
sense a raw switch input with an ISR - the bounces can cause the ISR to run dozens/hundreds of times in
succession, locking out other interrupts or progress.

A good exception to this rule is for an emergency stop switch where all that matters is the switch
gets noticed and things shutdown immediately - shutting down 5 times is a row is still shutting down.

Ok, i will consider other ways to check button state.
But still, what is wrong with interrupt? Im curious about it

Because they are unnecessary and overcomplicated.

Switches are made out of metal, which is springy and elastic. When a switch is closed, the metal pieces are slammed together and sproing apart multiple times before eventually settling down in steady contact, just like dropping a rubber ball onto the floor. Filtering out the bounces (called debouncing) is an important part of making an interface function properly. This is just as easy to do in normal code as it is in an interrupt, which is to say that they are equally hard.

And if you can’t read your switch properly because you’re using delay(), STOP USING IT. It is a terrible, over-abused function that’s holding you back.

ok, guys.
thank you all.

Try the code in Several Things at a Time and see if that gives button bounce - it shouldn't.