Effect of switch bounce on external interrupt ?

I'm going to use an external interrupt for the first time.

The source of the pin input is a relay contact so there will be bounce.

I'm wondering how the ATMEGA328P reacts when it is in the middle of an interrupt service routine which has been called by the external interrupt, then the very same pin "calls" for the interrupt again (i.e. contact bounce) before the interrupt service routine is finished.

Does the interrupt service routine finish before it acknowledges further interrupt requests on the same pin, OR does the interrupt service routine "get interrupted" and start from the beginning again.

Keith.

The processor always finishes an ISR before responding to other interrupts (unless
you explicitly re-enable interrupts before the end).

If the interrupt comes in again the bit gets set again so the ISR will run again.
If it comes in while the bit is set its ignored.

I'm assuming you have RISING or FALLING as the mode.

The datasheet is there for everyone to read, section 12...

Normally, the AVR hardware clears the global interrupt flag (in SREG) before entering an interrupt. This means other interrupts are disabled inside the running handler until the handler finishes and exits.

The RETI instruction is the normal function epilogue for an interrupt handler, and thus re-enables interrupts (just like executing an SEI instruction).

For this reason, normally, interrupt handlers can not be nested.

Search ISR(XXX_vect, ISR_NOBLOCK) for a way around this.

or

Is an interrupt essential?

...R

Thanks very much lads.

That's good then, at least the ISR code does not get interrupted. All my ISR routine will do is change a pin output state from 1 to 0, then reset some registers back to zero. If switch bounce makes that happen several times it won't hurt anything. My main concern was that the ISR code could not get interrupted.

It will be a rising signal on the interrupt pin.

Is an interrupt essential ?? I'm pretty much a beginner at this relatively speaking, so I really don't know, but I will give a brief explanation of what the circuit does. A relay is energised, then the circuit starts a counting / timing function, maybe about 3 seconds long. Under normal circumstances this counting / timing function should never complete, it's just a timeout feature to put things back to the beginning if the interrupt signal does not arrive. The interrupt signal should arrive a short time after the relay is energised. I don't want to poll for the rising signal while running the counting / timer function at the same time because I want the fastest response possible when that rising signal comes, hence my decision to use an interrupt. Hope I explained that well enough.

MarkT,
I know the datasheet is there for everyone to read (I have it, all 700+ pages) but this question popped into my head when I awoke this morning and I only had time to pop the question on the forum before going to work. My head is spinning with all the things I'm trying to learn at once (pcb design, Arduino, machine shop related stuff, and lots lots more LOL), while running a machinery based business with all the maintenance headaches outside of work hours. Time is something I can't get enough of. Thanks to helpful guys like yourself I come home from work and now I know the answer. And forum members often make things a lot easier to understand than reading the info on a datasheet.

Keith.

The interrupt signal should arrive a short time after the relay is energised. I don’t want to poll for the rising signal while running the counting / timer function at the same time because I want the fastest response possible when that rising signal comes, hence my decision to use an interrupt.

Can you quantify any of these timings, for instance, how fast is fast, how short is a short time in your application ?

UKHeliBob:

The interrupt signal should arrive a short time after the relay is energised. I don't want to poll for the rising signal while running the counting / timer function at the same time because I want the fastest response possible when that rising signal comes, hence my decision to use an interrupt.

Can you quantify any of these timings, for instance, how fast is fast, how short is a short time in your application ?

"Fast" is simply as fast as I can get it using the Arduino, no need to quantify how fast that will be. If an interrupt switches off the output quicker than polling for the signal while doing other things then switching the output, isn't that reason enough to use an interrupt.

Sorry I was not more clear on the "short time" bit. Depending on the specific machine I would estimate that time could be anywhere from 0.1 to 1 second. So if my timeout period is about 3 seconds and I have not received the interrupt then something is wrong (machine is not functioning or operator forgot to turn it on).

Keith.

0.1 seconds is a very long time for an Arduino. I doubt very much if there is any need for the complexity of interrupts.

The real value of an interrupt is not speed, it is being able to catch a very short lived and unpredictable event which you might miss using polling. The downside of interrupts is that they can be a nightmare to debug if they go wrong.

...R

If an interrupt switches off the output quicker than polling for the signal while doing other things then switching the output, isn't that reason enough to use an interrupt.

No. Your program needs to be fast enough, it does not have to be as fast as possible.

What method do you intend to use to change the output pin from 1 to 0 ?

Robin,

the 0.1 sec is not the needed reaction time of the ISR, it is simply the time from issuing an output to getting an input back from the machine. I need the fast reaction time from when I receive this input.

I'm a relative beginner here but what you say about speed not being the main purpose of an interrupt is completely opposite to many write-ups I've read on why to use an interrupt. If the code cannot be written to poll the pin fast enough, because it has a bunch of other stuff to do, and an external interrupt can do it faster, then (to me at least) that's a very viable reason to use an interrupt, and like I say, from what I have read, one of the main reasons to use an interrupt.

UKHeliBob,

I do want it to be as fast as possible because I don't have the facilities to measure the reaction time of the external machine. Plus researching about how long Arduino instructions take comes up with no real answer, or the answers seems to be that you can only measure the time of assembly code commands, not compiled C. So I'm basing my sketch on "as fast as I can make it". Plus it's good practise for me learning how to do this :slight_smile: I'm sure there will be times in the future where knowing what is the fastest way for the Arduino to react to an event will be useful. My ISR will be pretty basic code so is there a reason not to use an interrupt. Just a few minutes ago while Googling I read that it is possible that the overhead time from when an external interrupt is received, to when the ISR starts (saving registers, etc) could possibly be more than using polling code. Without knowing how long instructions take or how long for an interrupt to save registers, etc, it's difficult for me to know what is the faster method.

For changing the output pin state from 1 - 0 is was just going to use "digitalWrite". I don't really know any other method at this point in time.

Keith.

beefy23:
I do want it to be as fast as possible because ...

That only makes sense if you already know that the maximum speed that can be achieved is less than you want. I think in fact you are assuming here that the Arduino will be too slow if you use a polling approach, but you're given no information to support that assumption. Unless you're trying to achieve sub-microsecond resolution, I doubt that you need interrupts. Put some numbers to it: at what timing resolution would you consider your project a failure?

PeterH:

beefy23:
I do want it to be as fast as possible because ...

That only makes sense if you already know that the maximum speed that can be achieved is less than you want. I think in fact you are assuming here that the Arduino will be too slow if you use a polling approach, but you're given no information to support that assumption. Unless you're trying to achieve sub-microsecond resolution, I doubt that you need interrupts. Put some numbers to it: at what timing resolution would you consider your project a failure?

Read what I said before regarding how I'd like to know how to do it the fastest way possible regardless of whether it's needed or not, and I stated the reason why. Sorry if you don't like me thinking that way, no harm intended.

For changing the output pin state from 1 - 0 is was just going to use "digitalWrite". I don't really know any other method at this point in time.

My question was loaded because I thought that you would say that ! There is a faster way to change a pin from 1 to 0 using direct port manipulation but I am as sure as I can be that you do not need to use it.

Good for you for investigating faster ways to do things as you may need them in the future, but it is probably just as important to make your code easily understood and maintainable as it is to make it go as fast as possible when it is not needed. It would be very instructive for you to write two separate programs, one using polling and one using interrupts, and to compare the results.

Using polling you could also deliberately try slowing down the response to see just how much slack time you have during which time the program could be doing something else.

It seems to me that mostly when people imagine that polling will be slow they are not planning the main body of their code in the correct way to minimize the time for the polling loop. The Arduino is quite capable of managing several things at the same time while repeating loop() very frequently.

The code in my demo sketch in the following thread loops about once every 47 microseconds.

…R

UKHeliBob,

thanks again, I like your recommendations and I might do just what you suggested. I got hold of a good writeup on interrupts and looking at the time to save the registers and put them back after the ISR. After what I read, perhaps polling may be just as fast in this case. For my timeout code I'll stay away from "delay" and use millis instead then after every millis reading I can poll the external input. There's relatively little in my that I need to do together with polling. Good ideas what you said about making two separate sketches for testing then further testing by deliberately adding delay.

I've also got something else to research now (direct bit manipulation). Like you say I probably won't need it but you've stirred my curiosity and I'm a sucker for punishment.

Robin,

thanks for that, I'll check out your sketch and see what learning points I can pick up. Since I last posted I've been doing nothing but Googling for methods on creating a delay without locking up the whole processor (i.e. without using "delay"), so that I can frequently poll the input while measuring elapsed time. Millis seems the best so far (said as a programming beginner LOL).

Keith.