When to use interrupt?

Hi gang,

Many, many questions about interrupts and the programming thereof, result in the answer as a question "but why are you using interrupts in the first place?".

I get that the processor is so fast, that loop() is almost certain to service your sensor in good time without using an interrupt and that in some large proportion of cases where interrupts are mooted, they're in fact unnecessary. They add complexity and probably don't buy anything in terms of efficiency or effect.

But where's the dividing line? What sort of circumstances typically warrant the use of an interrupt?

Jim

What sort of circumstances typically warrant the use of an interrupt?

When the action to be reacted to could happen at any time and needs to be noticed without delay or could itself be so transient as to possibly be missed otherwise.

An example in my case is reading the input from encoders on robot wheels to count the number of turns of the wheel. These inputs are used to ensure that each wheel is running at the same speed by adjusting one or both if a mismatch is detected. Meanwhile the robot is scanning for obstructions by rotating a servo, flashing LEDs to indicate its current state etc.

The encoder signal could arrive at any time and is by its nature is transient so could be missed. Instead the ISR flags receipt of the input, increases a counter and exits. The value of the counters is compared next time through loop(), during which time it is possible that they have been incremented several times, and the wheel speed(s) are adjusted.

If the encoders were polled in loop() then they could be in one of 2 states but the ISR ensures that the number of state transitions are counted correctly.

Gotcha, thanks.

I personally use them with the alarm function of an RTC.

The processor can completely ignore the clock until such time as it receives an interrupt. Then it can divert and go and do whatever it needs to do at that time. Useful if you have the processor in sleep mode. Mr Gammon has an excellent piece on this subject on his site, under power saving.

JimboZA: Gotcha, thanks.

Bear in mind that is only my take on it.

There is no reason, for instance, why an interrupt should not be used to respond to a button press even if it can be done by simply polling the input. In fact, turning Devil's advocate, I could make a case to encourage people to use interrupts more often as long as they understand what they are doing. It's just a shame that there are not more interrupts available (pin change interrupts excepted) on most Arduinos.

Stands back, puts on flack jacket and awaits comments.

Think about the latency - the time from when the input happens to the latest time it must be responded to. If that's 1ms or less consider seriously interrupts, 10ms or more and interrupts shouldn't be needed. Depends a bit on the slowest blocking operation called from loop().

Responding to a HMI event like a button press it up in the 100ms region, never requires interrupt's speed of response.

Generating or reading a complex signal with microsecond-timing - interrupt driven (or hardware if it exists). See SoftwareSerial and Servo libraries for examples.

Reading a mechanical rotary encoder switch - no interrupt needed as a few 100 Hz max

Reading an optical shaft encoder at 3000rpm - interrupts needed, upto 100kHz or so.

Stands back, puts on flack jacket and awaits comments.

You know the reason not to very well.

I’m sitting reading the paper.
The doorbell rings.
I go to answer the door.
I go back to making my cup of tea.

OR

I’ve got the fryer on, making chips
The doorbell rings.
I go to answer the door.
I have a twenty minute conversation with the postman.
(My house burns down.)

These are the common misconceptions (and their consequences) of using interrupts.

Stands back, puts on flack jacket and awaits comments.

I’ll add to AWOL’s excellent list.

as long as they understand what they are doing.

That, of course, is the rub. Most people do NOT understand how interrupts work, how they should be handled, how they should be kept as short as possible, etc.

The doorbell example is classic. All the the interrupt handler should do is answer the door, see that someone is there, and notify, by some means, the responsible party to deal with the person at the door.

Of course, sometimes, in the case of serial data arriving, the postman rang the bell and held out a package. The postman, in this case, knows enough to not hang around having a 20 minute conversation. So, the interrupt handler simply needs to accept the package and put it in the proper place.

But, far too often, we see people that want to do just what AWOL describes in his first example, and don’t understand that the process automatically returns them to reading the paper. They think that after processing the interrupt that they should be able to go have a beer.

Interrupts have their place. When you need to use an interrupt, generally I think that you know that you have that need. If you don’t KNOW that you have that need, you probably don’t have it.

Wow. Less reaction than I expected so far. Of course the correct use of interrupts is predicated on the user understanding them as is the use of polling an input pin.

I've got the fryer on, making chips The doorbell rings. I go to answer the door. I have a twenty minute conversation with the postman. (My house burns down.)

That could happen just as easily if you listened for the doorbell using polling as it could using interrupts.

It is quite fun being on the Dark side sometimes (I must have been reading too much Harry Potter recently) even if you are only pretending :)

That could happen just as easily if you listened for the doorbell using polling as it could using interrupts.

But then your action is down to simple stupidity, not unreasonable expectations of a magic spell you don't understand correctly or at all.

Scott Adams

You can never underestimate the general public

There are two separate but somewhat related questions

Do you know how to use interrupts?

Do you need to use interrupts?

When you know how, you can usefully use them for all sorts of things.

If you don't know how they are very unlikely to be necessary.

In my view the most important part of knowing how to use interrupts is knowing how to debug problems without having to ask questions here. Because interrupt problems can be very obscure it will be hard for someone else to sort out a problem without spending a huge amount of time on it.

...R

Way back in the dim distant past (late 1970s), before "computing" had factionalised into "web", IT", "embedded" and all the other sects , I got a slim volume (there wasn't a lot to write on the subject back then) out of the library on microprocessor system design.

Back then, you could fit both software and hardware aspects in the same book, and each chapter was headed by a quote from some industry luminary, and I vividly remember the quote from the chapter on interrupts.

It said something like "Interrupts are difficult and dangerous; their use is to be avoided at all costs".

Plus ça change. . .

AWOL: It said something like "Interrupts are difficult and dangerous; their use is to be avoided at all costs".

people said the same thing about automobiles in the 1890's.

Plus ça change. . ? non!

plus les gens changent, plus elles restent les mêmes...

rusty right grade french...

Well, they're more efficient than polling usually.

Consider what life would be like if you had to poll the telephone. You're in the kitchen making fries, and every time you pull a batch out of the frier you run over and grab the phone and ask, "Hello, is anybody there?"

But the polling has to take place anyway, sometimes it's just done in a different way. In the Arduino it's usually done in the loop() routine. But if there are other things happening in the loop routine as well, and some of them take a while, you can use interrupts so you don't miss something important just because you're doing something more important at the moment.

I also use interrupts if I have to know what time something happened. The interrupt service routine takes a time stamp and saves it in a variable or a queue so my main program can handle it later when it gets around to it. Then I don't have to worry about missing it because I was doing more important stuff.

It's like when I'm making fries and the doorbell rings, I run to the door and take the package from the postman, but I tell him I can't talk right now because I'm busy making fries. Would he like to come in and sit in the parlor and wait while I finish up this batch? Then I head back into the kitchen and finish the fries, turn off the stove, and I can chat with the postman at my leisure.

VWell, they’re more efficient than polling usually.

I think that depends on your definition of efficient. Interrupts are useful when the interrupt, like serial data arrival needs to be handled NOW. A switch press that is recognized 10 milliseconds late? Not usually a problem.

and every time you pull a batch out of the frier you run over and grab the phone and ask, “Hello, is anybody there?”

I thinks it’s more like looking over and seeing if the “I’m ringing” light is blinking.

and some of them take a while

Well, that;s the gist of the problem in a nutshell. NOTHING in loop() should take long. delay() should be avoided at all costs. In fact, I’d be in favor of removing the “suppress all warnings” option, and adding a warning if you use delay() that says “You are an idiot”.

I also use interrupts if I have to know what time something happened.

Sure. IF the EXACT time is critical.

The interrupt service routine takes a time stamp and saves it in a variable or a queue so my main program can handle it later when it gets around to it.

That’s exactly how interrupts SHOULD be handled. Pity that far too many people think otherwise.

When you use interrupts and update some volatile variable that you also use in other parts of code you can get some nasty, or possibly useful side effects. You just have to understand that the first time you check a variable and the second time you check it might not return the same value.

Sticking to the doorbell example...

I'm arguing with my wife about why we don't got the rent The doorbell rings I answer it and it's the sweepstakes man, we've just won a million dollars When I return to my wife, no matter what the next question is, I'd like to already have that information and not have to continue arguing until I get to the next iteration of loop.

I guess an example would be a bumper on a robot that stops it if it touches a wall before it knocks it over.

...NOTHING in loop() should take long...

That's an interesting concept to me. I understand that tying up the processor for seconds at a time with delay() or other tight loops may not be the best idea, but suppose my program actually has some useful processing to do. Graphics to put out, sound to process, or incoming data to handle. If I can't handle them in the loop() function, exactly where do you propose I handle them? I thought that pretty much everything in the Arduino system was done through the loop(). Is there some other place I don't know about where this can be done?

TanHadron:

...NOTHING in loop() should take long...

but suppose my program actually has some useful processing to do. Graphics to put out, sound to process, or incoming data to handle.

It doesn't matter if the code is in the loop() function or elsewhere (even in an ISR). The issue is how long (rather, how short) does it take to execute all the code called by loop() and get back to the next iteration of loop().

As an example there are regularly problems here where someone wants to move a stepper motor through (say) 1200 steps and finds it difficult to see that can easily be achieved with 1 step in each iteration of loop() rather than tying up the CPU while all 1200 steps happen.

And some of the Libraries seem to be poorly written and use blocking code when it is unnecessary.

Another thing to bear in mind is that an interrupt brings with it a significant amount of baggage as it must save and restore the state of things which polling does not need to do.

...R

I also use an interrupt to wake up the processor when I put it to sleep to save power.