While looking for a very efficient method to decode quadrature signals directly on the Arduino Nano, I came up with this solution for 2 encoders. While not suitable for high resolution encoders, it is at least fast enough for 400 CPR running at 3000 rpm. Interesting finding was the lookup table method found else where on the internet, is about twice as slow. The subroutine is called from a timer interrupt routine.
// GPL, Hannes de Waal 2019 // Measured 97 KHz, 5.8us duration with lookup table // 128.9 kHz with 3.36us using 2 case statements, instead of lookup void read_encoder() { static uint8_t enc1_ab = 0; static uint8_t enc1_idx = 0; static uint8_t enc2_ab = 0; static uint8_t enc3_ab = 0; /**/ unsigned char port = PINC; enc1_ab <<= 2; //remember previous state enc1_ab |= ( port & 0x03 ); //add current state enc1_idx <<= 1; enc1_idx |= ( port & 0b00000100 ); enc2_ab <<= 2; enc2_ab |= ( port>>2 & 0x03 ); // Pos1 += enc_states[( enc2_ab & 0x0f )]; /* state transitions 10 -> 11 + 11 -> 01 + 01 -> 00 + 00 -> 10 + 10 -> 00 - 00 -> 01 - 01 -> 11 - 11 -> 10 - 10 -> 01 e 01 -> 10 e 00 -> 11 e 11 -> 00 e */ switch( ( enc1_ab & 0x0f ) ) { case 0b00001011 : Pos += 1; break; case 0b00001101 : Pos += 1; break; case 0b00000100 : Pos += 1; break; case 0b00000010 : Pos += 1; break; case 0b00001000 : Pos -= 1; break; case 0b00000001 : Pos -= 1; break; case 0b00000111 : Pos -= 1; break; case 0b00001110 : Pos -= 1; break; case 0b00001001 : Err ++; break; case 0b00000110 : Err ++; break; case 0b00000011 : Err ++; break; case 0b00001100 : Err ++; break; // 0000 hold // 0101 hold // 1010 hold // 1111 hold } switch( ( enc2_ab & 0x0f ) ) { case 0b00001011 : Pos1 += 1; break; case 0b00001101 : Pos1 += 1; break; case 0b00000100 : Pos1 += 1; break; case 0b00000010 : Pos1 += 1; break; case 0b00001000 : Pos1 -= 1; break; case 0b00000001 : Pos1 -= 1; break; case 0b00000111 : Pos1 -= 1; break; case 0b00001110 : Pos1 -= 1; break; case 0b00001001 : Err1 ++; break; case 0b00000110 : Err1 ++; break; case 0b00000011 : Err1 ++; break; case 0b00001100 : Err1 ++; break; } }