Interrupt question – RISING interrupt triggered during FALLING state… HELP!

Hello all,

I know similar questions have been asked on this forum but I couldn’t find a clear solution to this particular issue. Basically I have a circuit with a button on an (interrupt) input pin, that when pressed, turns on pin13’s LED for 500ms. Very simple.

More specifically, the software must control for these factors:

1) The interrupt is triggered ONLY when the button is pushed (RISING). The LED should turn on for 500ms then turn off ONCE, regardless of whether or not the user continues to keep the button pressed by holding it down, or simply taps it for a split-second.

2) Once the button has been pushed the LED stays on for exactly 500ms even if the user decides to frantically mash the button.

3) The LED can only be triggered to light up again once it has turned off after a successful 500ms cycle, and after the button has been released (back to a LOW) state.

It seems that my code is working just fine except for one major problem… The interrupt is being triggered both when the button is being pressed AND intermittently when it is being released. For example, if I press the button, hold it down for say 3 seconds, then release it, the interrupt is triggered again upon release. This shouldn’t happen if I have the interrupt set to RISING. I tried changing the interrupt type to HIGH but the same thing happens.

Below is my code. Just to clarify I have a 1k-Ohm resistor connecting the input pin to GND and the button shorts the +5V to the input pin.

Any thoughts?


int pin = 13; volatile int changedx = 0;

void setup() { pinMode(pin, OUTPUT); attachInterrupt(1, blink, RISING); }

void loop() { if (changedx == 1) { digitalWrite(pin, HIGH); delay(500); digitalWrite(pin, LOW); changedx = 0; } }

void blink() { if (changedx == 0) //This makes sure the contents of the loop() function //can't be re-triggered thru the interrupt if user mashes the button. { changedx = 1; } }


Contact bounce, debounce the button.

You need a de-bounce routine to mask the voltage spikes from the switch.

The debounce routines I see seem to all be coded for canceling out multiple voltage spikes/bounces that are milliseconds apart. In my situation if the button-release triggers only one, single spike before falling, how will the code adjust for this? How will the code know to ignore the initial spike and 'see' only the falling state (even though falling does nothing in my program)?

This sounds like a good example of an interrupt being unnecessary and just causing trouble.

One solution would be to have the interrupt routine immediately detach the interrupt. Then when the 500ms has elapsed the code could turn attach it again. This would simultaneously debounce the switch and facilitate the waiting period.

But I suspect that using loop() to poll the status of the switch would be perfectly adequate, and much easier to implement and debug.

And use the Blink Without Delay technique to manage the timing in either case.

...R

Robin2: This sounds like a good example of an interrupt being unnecessary and just causing trouble.

I agree.

Bouncing can be on key release also. Interrupts routines are fast, and will see the bounces.

I will try the detach idea and see if it works. I simplified the scenario just to describe the issue. This will end up being a more complex project in the end, as this will control four solenoids via four switches in a 3/4 scale pinball machine. Two of the switches need to fire their respective solenoids (for slingshots and pop bumpers) momentarily to avoid a coil from accidentally getting stuck on and burning out. What’s more, is the other two ’ flipper’ solenoids need to be fired at full voltage for roughly 100ms, then using PWM voltage dropped by 50% so the coils don’t burn up if the player holds the flipper button down for an extended amount of time. This happens quite frequently when a player catches the ball with the flipper and holds it to aim for a playfield target. I figure in the end interrupts would make coding this much easier since up to three of the switches could theoretically be triggered at nearly the same time, and polling for all of this without delays in loop () seems like it’d be a nightmare to code.

I think I figured it out... For anyone interested this code seems to work flawlessly and the interrupt does not trigger at all when the button is de-pressed. I'm sure I'll be posting more newbie questions as I get deeper into this project. Thank you for your replies!

-Brian

Here is the working code:

int pin = 13; volatile int changedx = 0;

void setup() { pinMode(pin, OUTPUT); attachInterrupt(1, blink, RISING); }

void loop() { if (changedx == 1) { delay(5); //waits 5ms to avoid potential voltage spike on button depress. if (digitalRead(3) == HIGH) { digitalWrite(pin, HIGH); delay(500); digitalWrite(pin, LOW); changedx = 0; } } }

void blink() { if (changedx == 0) //This makes sure the contents of the loop() function //can't be re-triggered thru the interrupt if user mashes the button. { changedx = 1; } }

moses1592: I figure in the end interrupts would make coding this much easier since up to three of the switches could theoretically be triggered at nearly the same time, and polling for all of this without delays in loop () seems like it'd be a nightmare to code.

I figure exactly the opposite. The interrupt-based approach is going to be relatively complex and error prone. A non-blocking state machine to handle switch inputs and timed actions would be far simpler and cleaner, using a separate small state machine to handle each independent thing you need to manage.

PeterH: [ using a separate small state machine to handle each independent thing you need to manage.

I wrote a very simple example in the first post of this Thread.

...R

Very ingesting.

Dumb question,

Out of curiosity, after an interrupt request is completed does the program continue right where it left off, say, in the middle of a miscellaneous function it was previously executing, or does it begin at the start of loop () again?

moses1592: Out of curiosity, after an interrupt request is completed does the program continue right where it left off, say, in the middle of a miscellaneous function it was previously executing, or does it begin at the start of loop () again?

right where it left off

...R

A good question, but the fact that you needed to ask it suggests that you should NOT be using interrupts just yet. Find another way, such as those suggested!

Good Luck!