Interrupts on PE2/PE3 not working on A*328PB Micro

EDIT: I tried using pins PE0/PE1 (digital pins 22/23) and still no luck.

I’m using the 5V 16Mhz version of the A*328PB Micro and want to use pins PE2 & PE3 (digital pins 20 & 21) for interrupts associated with a rotary encoder. I’ve got this working previously with different pins - are interrupts on those two pins not available?

#define encPinAint 20       // PE2
#define encPinBint 21       // PE3

volatile boolean halfleft  = false, halfright = false;     // Used in both interrupt routines

void setup() {
  // Set up rotary encoder w/ interrupts
  pinMode(encPinAint, INPUT);      // w/ 4.7k pullup resistor
  pinMode(encPinBint, INPUT);      // w/ 4.7k pullup resistor

  attachInterrupt(digitalPinToInterrupt(encPinAint), isr0, FALLING);   // Call isr0 when pin PE2 goes LOW
  attachInterrupt(digitalPinToInterrupt(encPinBint), isr1, FALLING);   // Call isr1 when pin PE3 goes LOW
}

void isr0() {                                                   // PE2 went LOW

  if ( !motorRPMAdj ) {
    return;                                                     // Don't care unless we're in mode to adj speed
  }
  
  delay(1);                                                     // Debounce time
  if(digitalRead(encPinAint) == LOW){                           // PE2 still LOW ?
    if(digitalRead(encPinBint) == HIGH && halfright == false){  // -->
      halfright = true;                                         // One half click clockwise
    } 
    if(digitalRead(encPinBint) == LOW && halfleft == true){     // <--
      halfleft = false;                                         // One whole click counter-clockwise 
      adjustWarpSpeed(-1);                                        
    }
  }
}

void isr1() {                                                 // PE3 went LOW

  if ( !motorRPMAdj ) {
    return;                                                   // Don't care unless we're in mode to adj speed
  }
  
  delay(1);                                                   // Debounce time
  if(digitalRead(encPinBint) == LOW){                         // PE3 still LOW ?
    if(digitalRead(encPinAint) == HIGH && halfleft == false){ // <--
      halfleft = true;                                        // One half  click counter-
    }                                                         // clockwise
    if(digitalRead(encPinAint) == LOW && halfright == true){  // -->
      halfright = false;                                      // One whole click clockwise
      adjustWarpSpeed(1);
    }
  }
}

Rotary Encoder connections. I know this works with other boards on other pins, just not this one.

I found this in …/variants/a-star328pb/pins_arduino.h:

#define digitalPinToInterrupt(p) ((p) == 2 ? 0 : ((p) == 3 ? 1 : NOT_AN_INTERRUPT))

I’m using that method to get the interrupt # from a digital pin but does the above mean it only works for digital pins 2 & 3? What should I use in attachInterrupt()?

Hello.

Yes, on the ATmega328PB, attachInterrupt() will only work with external interrupts INT0 and INT1, which are on Arduino pins 2 and 3, respectively. If those pins are available in your setup, switching to those would probably be the easiest solution. Otherwise, you could try using pin change interrupts instead. If you go with that option, you might find this PinChangeInterruptLibrary by NicoHood helpful.

Brandon

Thanks Brandon. Unfortunately, I need pins 2 & 3 for PWM so they’re not available (unless I could move the LEDs on 2/3 to 0/1 but then those are TX/RX and I need to use the Serial Monitor for debugging).