Relocate Interrupts Pin

Hello,
Im currently running into a shortage of interrupt pins. Im using an Arduino Mega 2560 R3.
This arduinos interrupt pins are located at: 2, 3, 18, 19, 20, 21, however, pin 20 and 21 is also SCL and SDA which im using for an IMU. This instantly renders 2 interrupt pins wasted. I also use pin 2 for interrupt for my IMU.
Now i have a set of motors which both need two connections to an interrupt pin, however, i only have 3 left (3, 18, 19).

Ive found that it is impossible to move the location of the SCL and SDA. Another option could be pin change interrupt, but ive read nothing but bad about it, and there should be a way to utilize the wasted interrupts that are overlapped with SCL and SDA.

So i was wondering if there is a way to relocate the interrupt pins, or any other possible solution that you guys know of?

No, you cannot move the interrupt pins any more than you can move the I2C pins. Your only option is to use PCINTs (well, only reasonable one - I guess softi2c and a modified library for the i2c devices is also an option, but a way worse one). I love PCINTs, they work fine, and you can avoid the abomination that is attachInterrupt entirely, and they can be used to wake from sleep. I always use PCINTs in preference to the external interrupt (INTn pins)

DrAzzy:
No, you cannot move the interrupt pins any more than you can move the I2C pins. Your only option is to use PCINTs (well, only reasonable one - I guess softi2c and a modified library for the i2c devices is also an option, but a way worse one). I love PCINTs, they work fine, and you can avoid the abomination that is attachInterrupt entirely, and they can be used to wake from sleep. I always use PCINTs in preference to the external interrupt (INTn pins)

Hmm. You say they work fine. Is that just for basic operations? Im going to use interrupts for encoder steps on the rotation of a motor. Isnt external INT pins inarguably way superior for this application?

Im going to use interrupts for encoder steps on the rotation of a motor. Isnt external INT pins inarguably way superior for this application?

No, pin change interrupts are very good for reading encoders. They are faster than the external interrupt created when using the attachInterrupt() function of the IDE.

cattledog:
No, pin change interrupts are very good for reading encoders. They are faster than the external interrupt created when using the attachInterrupt() function of the IDE.

Thanks for clearing that up! Ive tried following a tutorial now, the interrupt just doesnt seem to happen :frowning:
Do you know if there is a superior library or even guide? :slight_smile:

the interrupt just doesnt seem to happen :frowning:

How do you know that? Please post the code you are using.

There are may tutorials on Arduino pin change interrupts. Here’s one Arduino Pin Change Interrupts – The Wandering Engineer but Goggle will get you to many more.

Pin Change Interrupts are really quite simple and you can easily get along without a library, but if you do want to use a library I recommend Nico Hood’s Pin Change Interrupt Library which is available through the library manage. The syntax is very similar to what you have learned using attachInterrupt() for external interrupts. Enable Interrupt by Mike “GreyGnome” Schwager is also popular and is available with the library manager.

Here’s some simple example code for reading a quadrature encoder with pin change interrupts on an ATmega328 which uses a table to set counts based on the possible quadrature states and the transitions.

const char encTable[16] = {0, 1, -1, 0, -1, 0, -0, 1, 1, 0, 0, -1, 0, -1, 1, 0}; //gives -1, 0 or 1 depending on encoder movement
volatile long encoderCount;
volatile long errorCount;
volatile byte encState;
unsigned long prevDisplay;
unsigned long interval = 1000;

void setup()
{
  Serial.begin(115200);

  pinMode(8,INPUT_PULLUP ); //output A
  pinMode(9,INPUT_PULLUP ); //output B

  //Enable pin change interrupts on pins 8 and 9 PB 0 and 1
  PCICR |= (1 << PCIE0); //enable group interrupts on PORTB PCINT[7:0]
  PCMSK0 |= (1 << PCINT0); //enable interrupt pin 8
  PCMSK0 |= (1 << PCINT1); //enable interrupt pin 9
}
void loop ()
{
  if (millis() - prevDisplay >= interval)
  {
    prevDisplay += interval;
    noInterrupts();
    long copyEncoderCount = encoderCount;
    encoderCount = 0;
    long copyErrorCount = errorCount;
    errorCount = 0;
    interrupts();

    Serial.print(copyEncoderCount);
    Serial.print('\t');
    Serial.println(copyErrorCount);
  }
}

ISR (PCINT0_vect)
{
  encState = ((encState << 2) | ((PINB) & B00000011)) & B00001111; //use encoder bits and last state to form index
  encoderCount += encTable[encState];//update actual position on encoder movement
  if (encTable[encState] == 0)
    errorCount++;
}