recently a german user posted this code that takes care of all the special situations a mechanical-switch-encoder produces if you change moving direction.
Standard-encoder code fails to count right if the direction-reversion occurs if the mechanical contacts are not exactly
"in the middle" of the contact-zone.
const byte ENCODER_A_PIN = 3;
const byte ENCODER_B_PIN = 2;
const byte SWITCH_PIN = 4;
void setup() {
Serial.begin(115200);
Serial.println("\nStart");
pinMode(ENCODER_A_PIN, INPUT);
pinMode(ENCODER_B_PIN, INPUT);
pinMode(SWITCH_PIN, INPUT);
}
void loop() {
int8_t state = 0;
if (rotaryEncoder(state)) {
Serial.println("- SWITCH -");
}
if (state == -1) {
Serial.println("<-- ");
}
if (state == 1) {
Serial.println(" -->");
}
}
bool rotaryEncoder(int8_t &delta) {
delta = 0;
enum {STATE_LOCKED, STATE_TURN_RIGHT_START, STATE_TURN_RIGHT_MIDDLE, STATE_TURN_RIGHT_END, STATE_TURN_LEFT_START, STATE_TURN_LEFT_MIDDLE, STATE_TURN_LEFT_END, STATE_UNDECIDED};
static uint8_t encoderState = STATE_LOCKED;
bool a = !digitalRead(ENCODER_A_PIN);
bool b = !digitalRead(ENCODER_B_PIN);
bool s = !digitalRead(SWITCH_PIN);
static bool switchState = s;
switch (encoderState) {
case STATE_LOCKED:
if (a && b) {
encoderState = STATE_UNDECIDED;
}
else if (!a && b) {
encoderState = STATE_TURN_LEFT_START;
}
else if (a && !b) {
encoderState = STATE_TURN_RIGHT_START;
}
else {
encoderState = STATE_LOCKED;
};
break;
case STATE_TURN_RIGHT_START:
if (a && b) {
encoderState = STATE_TURN_RIGHT_MIDDLE;
}
else if (!a && b) {
encoderState = STATE_TURN_RIGHT_END;
}
else if (a && !b) {
encoderState = STATE_TURN_RIGHT_START;
}
else {
encoderState = STATE_LOCKED;
};
break;
case STATE_TURN_RIGHT_MIDDLE:
case STATE_TURN_RIGHT_END:
if (a && b) {
encoderState = STATE_TURN_RIGHT_MIDDLE;
}
else if (!a && b) {
encoderState = STATE_TURN_RIGHT_END;
}
else if (a && !b) {
encoderState = STATE_TURN_RIGHT_START;
}
else {
encoderState = STATE_LOCKED;
delta = -1;
};
break;
case STATE_TURN_LEFT_START:
if (a && b) {
encoderState = STATE_TURN_LEFT_MIDDLE;
}
else if (!a && b) {
encoderState = STATE_TURN_LEFT_START;
}
else if (a && !b) {
encoderState = STATE_TURN_LEFT_END;
}
else {
encoderState = STATE_LOCKED;
};
break;
case STATE_TURN_LEFT_MIDDLE:
case STATE_TURN_LEFT_END:
if (a && b) {
encoderState = STATE_TURN_LEFT_MIDDLE;
}
else if (!a && b) {
encoderState = STATE_TURN_LEFT_START;
}
else if (a && !b) {
encoderState = STATE_TURN_LEFT_END;
}
else {
encoderState = STATE_LOCKED;
delta = 1;
};
break;
case STATE_UNDECIDED:
if (a && b) {
encoderState = STATE_UNDECIDED;
}
else if (!a && b) {
encoderState = STATE_TURN_RIGHT_END;
}
else if (a && !b) {
encoderState = STATE_TURN_LEFT_END;
}
else {
encoderState = STATE_LOCKED;
};
break;
}
uint32_t current_time = millis();
static uint32_t switch_time = 0;
const uint32_t bounce_time = 30;
bool back = false;
if (current_time - switch_time >= bounce_time) {
if (switchState != s) {
switch_time = current_time;
back = s;
switchState = s;
}
}
return back;
}
best regards Stefan