I am using the same code for a rotary encoder in my UNO project (both hardware interrupts). It works great and, it's fast! This is my ISR and the main line code. Maybe you can find something useful.
Based on my understanding, using Serial.print in the ISR violates the principle of keeping the ISR brief and uncomplicated.
// interrupt variables
int IRQActivity = 0; // IRQ activity flag
volatile int IRQcounter = 0; // Encoder direction value, set by 'rotate' ISR
/*
After clearing any previous encoderTurned value, check
the count value returned from the ISR to see if the
rotary encoder has moved. If it has, then a new IRQ has
been recognized and encoderTurned will be loaded with
and hold the direction value for one scan only.
*/
encoderTurned = 0; // Reset previous turned value.
if (IRQActivity != IRQcounter) {
if (IRQcounter > IRQActivity) encoderTurned = DIR_CW;
if (IRQcounter < IRQActivity) encoderTurned = DIR_CCW;
IRQActivity = IRQcounter; // reset one-shot value to be ready for next IRQ
}
/*
/* Interrupt Service Routine for rotary encoder:
An interrupt is generated any time either of
the rotary inputs change state.
*/
void rotate() {
byte result = rotary.process();
if (result == DIR_CW) {
IRQcounter++;
} else if (result == DIR_CCW) {
IRQcounter--;
}
}