himc29
March 18, 2026, 3:48am
1
Hi, I’m using a KY-040 rotary encoder with an Arduino and trying to get exactly one increment per physical detent
The behavior is inconsistent:
Sometimes 1 detent = 1 step (correct)
Sometimes 1 detent = 2 steps (extra trigger in the middle)
Sometimes it even needs 2 detents for 1 step
Here is my code:
int readRotary() {
static int lastState = 0;
static int8_t enc_states[] = {0,-1,1,0, 1,0,0,-1, -1,0,0,1, 0,1,-1,0};
static int8_t accumulator = 0;
int currentState = (digitalRead(clkPin) << 1) | digitalRead(dtPin);
accumulator += enc_states[(lastState << 2) | currentState];
lastState = currentState;
if (accumulator >= 2) { accumulator = 0; return 1; }
if (accumulator <= -2) { accumulator = 0; return -1; }
return 0;
}
I want so that for every detent (click) there is, the function will produce only one 1 or -1
Also btw, no hardware debouncing, and I am using digitalRead() in loop
Thanks, I hope my question can be answered.
himc29
March 18, 2026, 3:54am
2
Hi, I asked ChatGPT and it gave back a solution that actually works! (for once)
int readRotary() {
static int lastState = 0;
static int8_t enc_states[] = {0,-1,1,0, 1,0,0,-1, -1,0,0,1, 0,1,-1,0};
static int8_t accumulator = 0;
int currentState = (digitalRead(clkPin) << 1) | digitalRead(dtPin);
accumulator += enc_states[(lastState << 2) | currentState];
lastState = currentState;
if (accumulator >= 4) { accumulator = 0; return 1; }
if (accumulator <= -4) { accumulator = 0; return -1; }
return 0;
}
No need for anyone helping anymore, as this code works good. Feel free to use this code in your own projects.
I would also add a 0.1uF ceramic capacitor from clock to ground, and another from step to ground. This will help stabilise the lines from high frequency bouncing you get with any mechanical switch.
J-M-L
March 18, 2026, 6:18am
4
Are you sure your rotary’ encoder does not give 2 or 4 ticks per click - always ?
Try with the encoder library and see what it says.
gcjr
March 18, 2026, 9:57am
5
i believe that encoder is designed to recognize just one input as a change and the other input as the direction ... per indent