Hi,
I am using a rotary encoder by reading the pin with attachInterrupt(pin, ISR, CHANGE) instead of RISING or FALLING, satisfactorily. But I would like to share and discuss it with the forum. Let me post my code first (I am using Arduino Mega 2560):
volatile long encoderPos = 0;
//both pin 21 and 20 is in PORTD. pin 21 is PIND>>PD0, pin 20 is PIND>>PD1
attachInterrupt( digitalPinToInterrupt(21), encode, CHANGE );
void encode() // interrupt service routine
{
if( ((PIND>>PD0) & 1) ^ ((PIND>>PD1) & 1) )
encoderPos++;
else
encoderPos--;
}
I am using both rising and falling edges as one step. First, it doubles the resolution. Second, in my opinion, it simplifies the code (speeds up the execution), but does it?
First I don't have to do all that if-and-else-if thing when only detecting rising or falling edges, because whenever pin 21 state changes (rising or falling), all I have to do is test the difference (the exclusive OR) with pin 20, if different, one direction; if not, the other direction. Here with only one logic test, I get increase or decrease. Although the code looks very neat, one thing I am not sure about is, in this one logic test I have two PORT reads, two binary shifts, and two binary AND, do those all count as single steps or can I lump them all in one step?
I do think using direct port reading speeds things up, BUT is there a better way to do this, instead of reading, shifting ANDing? Or at least I don't want to read the port twice, should read it once and use it twice?
The reason I pick these pins is that they have the highest priority on the data sheet; I don't ever want to lose an encoder pin reading, right?
Appreciate any input.
Hugh