Which interrupts - Choosing between External and Pin Change Interrupts

Looking for some help on how to distribute my interrupt sources.

I'm making a project that will have a wide variety of inputs for controlling some PWM lights, a timed pulse signal, a relay, and updating a display.

I want to have a proper PCB made up, but am getting into a bit of a time crunch, so I'll need to order the PCBs before I have a chance to do the programming. I am confident the hardware will work as intended. (my background is more hardware than firmware)

My question ISN'T on HOW to write the ISRs, but which physical pins I should attach the various inputs in order to have the least chance of problems

Interrupt needing Inputs: (Though, Some may be able to be polled)

Rotary encoder - EncodeA_wPU

  • This will be primarily used to adjust settings for the various outputs.
  • The associated EncodeB_wPU pin doesn't need an interrupt
  • I don't need super responsiveness for the encoder - Human interface, rotary dial.

Encoder's PB - EnsodeSW_wPU

  • Primarily used to confirm settings made with the encoder dial.
  • Secondary use - to 'wake up' the display from standby mode and enter the settings menu.
    Doesn't need to be super fast - Human Interface, momentary push button

IR Remote Data - IR_Data

zero cross detector - FP_Sense

  • Will receive a pulse everytime an AC signal crosses 0V.
  • Used for triggering a Triac based AC motor (small fan) speed controller.

Mode Switch PB - ModeSW_wPU

  • Manual override for the relay. Human interface, momentary push button
  • Max. actionable frequency is one change every 15 sec. (any bounce will be ignored)

RF Input data - Radio_In

  • Expecting a signal burst every 250mS (approx).
  • If two or more signals not present, stop doing something.
  • When signals start again, start doing it again.
  • Planning to use RadioHead Library: https://github.com/adafruit/RadioHead

So, with everything above, I thik I should probably use the Ext. interrupts for:

zero cross detector - FP_Sense
RF Input data - Radio_In

Since they are the most time-critical - despite being fairly infrequent, from a uC perspective.

Any suggestions / confirmations / 'you're doing this stupid, here's a better way' comments encouraged!


I do know there are only 2 pins available for external interrupts where as any digital pin for pin change interrupt.

I don't know why you would one type of interrupt vs the other (pin change versus external). The reasons I don't know may invalidate the some of my reasoning listed below. With that said, hopefully someone will provide a complete answer on when to chose one or the other.

In my experience the external interrupt is easier to configure (see attach and detach interrupt).

But since there are more than 2 pins that require interrupts, why not just setup and use one bank of input pin interrupts? That gives access to up to 8 pins and consolidates the programming and evaluation. Ie., all pins will be evaluated for interrupt using the same style and method of programming; opposed to two pins using attach/detach interrupt and 4 pins using pin change interrupts.

Personally, I avoid polling. I use interrupts and time sliced subroutines as much as possible. Granted it is not a one size fits all approach, but I start in that direction and adjust as necessary.

For me: it's polling if you can (e.g. push buttons and switches), interrupts when you must (e.g. short pulses from an encoder or zero crossing, timing sensitive inputs). Interrupts do have the habit of interrupting other code, and potentially causing glitches.

Pin change: you have to check what happened to the which pin - if you have only one pin in a bank it's easy to find which triggered, if you have more pins it's more work.

External interrupt: can be set to RISING, FALLING, CHANGE. Less work in code to figure out what happened to which pin.

Rotary encoder - EncodeA_wPU

Can indeed be polled normally, unless moving faster than your loop is.

Encoder's PB - EnsodeSW_wPU

Also polling - based on PA.

IR Remote Data - IR_Data

Library handles this - may use interrupts internally, but that are normally pin change interrupts.

zero cross detector - FP_Sense

Needs interrupt, very short peaks. Polling will miss them.

Mode Switch PB - ModeSW_wPU

Human operated so slow - polling.

RF Input data - Radio_In

Handled by the library - which may use interrupts, normally pin change interrupt - just poll the library for available data?

So you only have to add one interrupt yourself it seems - but do check on what those libraries do, and choose pins carefully, as otherwise ISRs may clash.


With a combo of writing out my original post & your replies, I think I have a better idea of how I want to implement my code.

Based on this info:
PCINT0_vect for D8 to D13
PCINT1_vect for A0 to A5
PCINT2_vect for D0 to D7

I've decided to set up my physical connections/interrupts like this:

Interrupt Plan:

HW.Int0 zero cross detect - FP_Sense
HW.Int1 Rotary encoder - EncodeA_wPU

PCINT0_vect - IR Remote Data - IR_Data
PCINT1_vect - RF Input data - Radio_In
PCINT2_vect - Encoder's PB - EnsodeSW_wPU

Program needs:
Mode Switch PB - ModeSW_wPU - Poll

My reasoning is: (Big Thanks to wvmarle's reply)

HW.Int0 zero cross detect - FP_Sense

  • Can't afford to miss and short pulse.

HW.Int1 Rotary encoder - EncodeA_wPU

  • Probably don't need it to be an int, but since I have the pin .... Why not

PCint 0 & 1 - Putting the IR and RF lines on separate PCints, just in case the could libraries conflict

PCint2 - Encoder Sw - Probably will ok polling, but here Just in case, to keep it separate from the other PCints

Mode Switch should be alright polling, so I wasn't as concerned.
I expect it to be the least frequently used of all the inputs. It will be connected to D12, so I can use PCint0 if I have to. Just hoping it won't have problems with the IR library. (Which is pretty mature, so I doubt there would be problems)

Any problems with this plan that anyone can see?