/* Based on Oleg Mazurov's code for rotary encoder interrupt service routines for AVR micros
here https://chome.nerpa.tech/mcu/reading-rotary-encoder-on-arduino/
and using interrupts https://chome.nerpa.tech/mcu/rotary-encoder-interrupt-service-routine-for-avr-micros/
This example does not use the port read method. Tested with Nano and ESP32 & Megga
both encoder A and B pins must be connected to interrupt enabled pins, see here for more info:
https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/
*/
// Define rotary encoder pins
#define ENC_A 18
#define ENC_B 19
#define ENC_button 17
byte UpperLimit = 255;
byte LowerLimit = 0;
unsigned long _lastIncReadTime = micros();
unsigned long _lastDecReadTime = micros();
int _pauseLength = 20000;
int _fastIncrement = 10;
volatile int Rcounter = 0;
void setup() {
// Set encoder pins and attach interrupts
pinMode(ENC_A, INPUT_PULLUP);
pinMode(ENC_B, INPUT_PULLUP);
pinMode(ENC_button, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(ENC_A), read_encoder, CHANGE);
attachInterrupt(digitalPinToInterrupt(ENC_B), read_encoder, CHANGE);
Serial.begin(115200);
}
void loop() {
static int lastCounter = 0;
// If count has changed print the new value to serial
if(counter != lastCounter){
Serial.println(counter);
lastCounter = counter;
}
}
void read_encoder() {
// Encoder interrupt routine for both pins. Updates counter
// if they are valid and have rotated a full indent
static uint8_t old_AB = 3; // Lookup table index
static int8_t encval = 0; // Encoder value
static const int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0}; // Lookup table
old_AB <<=2; // Remember previous state
if (digitalRead(ENC_A)) old_AB |= 0x02; // Add current state of pin A
if (digitalRead(ENC_B)) old_AB |= 0x01; // Add current state of pin B
encval += enc_states[( old_AB & 0x0f )];
// Update counter if encoder has rotated a full indent, that is at least 4 steps
if( encval > 3 ) { // Four steps forward
int changevalue = 1;
if((micros() - _lastIncReadTime) < _pauseLength) {
changevalue = _fastIncrement * changevalue;
}
_lastIncReadTime = micros();
counter = counter + changevalue;
if(counter>UpperLimit) { // limit the counter upper value
counter =0;
} // Update counter
encval = 0;
}
else if( encval < -3 ) { // Four steps backward
int changevalue = -1;
if((micros() - _lastDecReadTime) < _pauseLength) {
changevalue = _fastIncrement * changevalue;
}
_lastDecReadTime = micros();
counter = counter + changevalue; // Update counter
if(counter<LowerLimit) { // limit the counter upper value
counter =255;
}
encval = 0;
}
}