2560 Interrupts do not act the same for MODE = CHANGE

The 2560 board interrupts apparently do not behave the same when the interrupts are used in the CHANGE mode.

I found that pins 2 and 3 behave as expected but 18, 19, 20 and 21 do not for mode =CHANGE
using ==> attachInterrupt(digitalPinToInterrupt(pin), ISR, mode)

I have both the Elegoo and Arduino boards…both behave the same.

I have scoped the signals and can see the difference. See attached (code for both pin tests within)

Pin 21 does not work in CHANGE mode with a LOGIC 1 derived from the 2560 board for simulation BUT pin 2 does work with CHANGE with the LOGIC 1 derived from the 2560 board for simulation…no real difference. Same code and flow

I know 21 will work on FALLING but that will require more time to get to that falling edge for the external system to do what’s needed.

My total of 3 interrupts to be monitored can be either a LOGIC 1 or LOGIC 0 when first arriving so I need to to see a CHANGE to do what’s needed…need to know immediately when a CHANGE is detected

Arduino tech support doesn’t get too involved with the “whats actually going on” but respond in general thoughts which we all know that general thoughts never really solved many software/hardware issues.

I isolated the code to 2 sketches so the interrupts investigated only exercised each interrupt.

The issue if my tests are valid may actually lie in the architecture of the chip…but then again…

PIN 2 TO 21 COMPARISON.pdf (1.92 MB)

Is your experience consistent with the information in the Atmega 2560 datasheet?


I ... that's a very detailed write-up with lovely pictures, but I can't quite figure out what "doesn't work" means; too much extra data, or something. Maybe you could put it in a table:

pin  transition result     comments

 2     0->1     interrupt
 2     1->0     interrupt
21     0->1     interrupt
21     1->0     no Interrupt  (why not?)

Or something similar.
Also, try putting in some debugging code:

Serial.print("pinToInterrupt(2) ="; Serial.println(digitalPinToInterrupt(2, HEX);
Serial.print("EICRA="); Serial.println(EICRA, HEX);
Serial.print("EICRB="); Serial.println(EICRB, HEX);
Serial.print("EIMSK="); Serial.println(EIMSK, HEX);

after your attachInterrupt calls, so we can see if the registers are being set correctly.

Thanks all for responses

First response .. the code is consistent with the command structure. Evidence is that pins 2 (and 3) work just fine but pin 21 (actually 18-21) fails in MODE=CHANGE for 'attachinterupt'. They (18-21) immediately respond whereas pins 2 and 3 "wait a bit" before creating an ISR when I introduced a change via push button at the interrupt pin I was testing. I have some idea why the reactions are different but can't do much about it.


Second response...the scope shots shows whats going on....the issue shown in the pix depicts pin 21 immediately going to LOGIC 1 when it sees a LOGIC 1 with no interaction of a simulated interrupt via push button whereas pins 2 and 3 just "wait a bit" for CHANGE and react as advertised .

PIN 2....after download....When I simulate with a push button after 5 seconds or 1 minute, ISR directed pin goes HIGH after remaining LOW after download. Pin 2 saw a CHANGE when I used the pushbutton to drive it LOW. The interrupt reacts properly for pin 2 (and 3 when tested) and the LED turns on via the pin in the ISR call...pin 21 "locks up" immediately as noted in scope pix with NO interactions by me via any interrupt simulation...

As a user/customer, I should not have to go looking into registers to see whats going on as the chip does not respond properly on all interrupts as advertised for its 5 interrupts with no differential conditions. There may be some folks who want to get to that level but I'm not interested. Its advertised to do something and it doesn't. Sorta like if I buy a brand new car and it only does 32 MPH max....I'm bringing it back to the dealer LOL

I see nothing different in the code when I run pin 2 by itself and pin 21 by itself. The result should be the same but aren't...now whats going on in the board is really a concern of Arduino which I have reported.

As an outside viewer, the CHANGE mode probably works on the concept of either a RISE or a FALL in the architecture but pin 21 only works properly in the FALLING mode for my needs. I have no need to interrupt on a FALL or RISE...just CHANGE as timing is critical and those defined edge polarities may come up a bit late.

Ruining identical software to 2 supposedly identical defined functions and getting different results should be troubling to Arduino. As a consumer let them look it over...in the mean time I do have a work around.

I brought this out for all to see.....the 2560 has an interesting history about interrupts....I'm not the first. But I may be one of the few to attempt to use more than 2 on the one board and maybe many didn't have to....

Here is the matrix I first created while first trying to see the issue . I think its still valid but it is a few days old…then I grabbed my scope a bit later to begin documenting the signal interactions. This matrix indicated pin 21 (and 18-21 as it turns out) are not identical. But it does show 2 and 3 work as expected

Matrix during troubleshooting.pdf (33.8 KB)

I do not think you are running into a specific problem with the Mega. In my opinion the Arduino IDE could do better in how it handles interrupts.

The EIFR (external interrupt flag register) is not specifically configured to clear any preexisting flags. Before attaching/enabling an interrupt it is always a good idea to clear the corresponding interrupt flag. You clear a flag by writing 1 to the register bit.

Nick Gammon discusses this issue here.

Since you are attaching and testing multiple external interrupts you may do well to clear the entire register before you call any attachInterrupt().

EIFR = 0xFF; //write 1 to all locations to clear flags.

See if clearing the EIFR solves your issue.

Thank you for your time looking at this

I entered the line in main loop as you suggested and the problem still exists...CHANGE just drops right thru..I put it in the first line to be executed in the main loop so I assume the resetting would be needed after each loop

EIFR = 0xFF; //write 1 to all locations to clear flags.

I am leaning more toward the architecture of the gating in the chip since it will work on FALLING so my guess is the architecture did not take into account a RISE or a FALL while in CHANGE mode..or there wasn't enough gating delay when in CHANGE mode. My thinking is hardware is needed to detect the change, rise, fall, high and low.

I am just going to use another 2560 board to watch the 3rd interrupt. I would go with 2 Uno's but I have the 2560 and I'm using a lot lines for status and job assignments so the additional 2560 will be used pretty decently.

It didn't require much change to the mother board they will go on....dropping in a few new headers and re-assigning/re-routing signal names in Orcad Capture (schematic), the system board ran fine in Orcad Layout (PCB) and all the new stuff now on motherboard and routed....bought these software packages when they first came out and still running on an old XP machine. Old may be old but it all makes sense to me. The free stuff on the web for this is a bit much as it open source and seems to go thru changes..I'll stick with what I know LOL

I now have 2 sketches written..one for each board.

Both sketches work fine since they will only use pins 2 and 3 on board 1 and pin 2 on the 2nd board.


I am having difficulty accepting that there is such a fundamental flaw in the chip architecture. You can not be the first person working with a CHANGE interrupt on pin 21.

I wonder about the entire set up with the driving pins and the buttons.

There are two more simple tests to confirm the expected CHANGE mode performance of pin 21 interrupt.

A pin set as output, can still respond with an interrupt. First test is to write a blink sketch with pin 21 set as output. Also attach an interrupt on pin 21 which will blink an led. You should see the led blink with the output switching both HIGH and LOW.
You could also do this with a different output pin jumpered to 21 set as an INPUT.

void setup() {
  attachInterrupt(digitalPinToInterrupt(21), ledBlink, CHANGE);
void loop() {
  static unsigned long blinkTime = 500;
  const unsigned long interval = 500;
  static byte pinState = LOW;
  if (millis() - blinkTime >= interval)
    blinkTime = millis();
    pinState = !pinState;

void ledBlink()

A second test using buttons would simply connect the interrupt pins to buttons wired so as to pull the input to ground when pressed. Use pinMode INPUT_PULLUP on the interrupt pin. Confirm with digitalRead() that the button is wired correctly and that you see HIGH when not pressed, and LOW with pressed.

You should be able to see the interrupt executed when the button is pressed and released. There may be an issue of switch bounce to be dealt with, but the hardware wiring for the test is far simpler.

Thanks again for your time.

Not quite sure about 21 not being used by folks but 18, 19 and 20 also don't work right. All I did was move wires around and changed the sketch to address the moves....There is history on the interrupts. My matrix shows pin 21 in all its modes.

I tried the pull up before and it just "flies" through and the LED fires..also observed the scope jumping up by itself right after a download. You'll notice about a 10ms delay after the input gets to pin 21 and then LED fires away on pin 38.. that doesn't happen on pins 2 and 3 as pin 38 stays at Logic 0.

We all know somethings are left alone as people work around their design...

I have a lot of system hardware testing outside this board. Time for me to put this behind me and get the parts ordered for system testing.

The wiring is exactly the same for pins 2 and 3 as I showed in the fritzin drawing. The 2 drawings only differ in the push button source to create the interrupt. I have scoped the push button action along with watching the all pins involved.

A 2nd 2560 is on its way...

As noted the 2 board will have their own code and thats OK with me....

Thanks for looking it over...if you can get 21 to work on a ! or a 0 coming in, when in CHANGE mode only, please notify me here....I have been trying to get answers for many weeks.. even with Arduino...no luck there.

Have a good week