Thanks guys! I just received my KY-040 encoders for a project I'm going to start (a B737 MSC panel) so this example was very useful for me to understand encoders principles!
Btw, I suggest enabling internal pull-up for SW pin, as KY-040 SW output is not pulled-up (there is a spot for a 10k resistor below, but the resistor isn't there...), then a few other little changes like adding a LED to show current value, so this is my version.
const int PinCLK = 2; // Used for generating interrupts using CLK signal
const int PinDT = 3; // Used for reading DT signal
const int PinSW = 4; // Used for the push button switch
const int PinLED = 9;
int SW;
int oldSW;
volatile boolean encChanged;
volatile long encPosition = 0;
volatile boolean up;
void isr() { // Interrupt service routine is executed when a HIGH to LOW transition is detected on CLK
volatile boolean CLK = digitalRead(PinCLK);
volatile boolean DT = digitalRead(PinDT);
up = ((!CLK && DT) || (CLK && !DT));
if (!up)
encPosition++;
else
encPosition--;
if (encPosition < 0) encPosition = 0;
encChanged = true;
delay(10);
}
void setup() {
pinMode(PinCLK, INPUT);
pinMode(PinDT, INPUT);
pinMode(PinSW, INPUT_PULLUP);
pinMode(PinLED, OUTPUT);
SW = HIGH;
oldSW = HIGH;
attachInterrupt(0, isr, FALLING); // interrupt 0 is always connected to pin 2 on Arduino UNO
Serial.begin(115200);
Serial.println("Start");
}
void loop() {
SW = digitalRead(PinSW);
if ( SW == LOW && oldSW == HIGH) { // check if pushbutton is pressed
encPosition = 0; // if YES, then reset counter to ZERO
Serial.print("Reset");
encChanged = true;
}
oldSW = SW;
if (encChanged) { // do this only if rotation was detected
encChanged = false; // do NOT repeat IF loop until new rotation detected
Serial.print("Count = ");
Serial.println(encPosition);
analogWrite(PinLED, encPosition);
}
}