Rotary Encoders



Rotary Encoder1


Connect CLK to Pin 2 on Arduino Board  (CLK is Data Output 1 of KY-040)
Connect DT  to Pin 3 on Arduino Board  (DT is Data Output 2 of KY-040)
Connect SW  to Pin 4 on Arduino Board  (Switch – goes LOW when pressed)
Connect GND to ground
Connect +   to +5V  (this will pull up CLK and DT with 10 KiloOhm resistors)
Connect a 0,47µ capacitor from ground to CLK   (debouncing)
Connect a 0,47µ capacitor from ground to DT    (debouncing)
Connect a 10 KiloOhm resistor from +5V to SW (no integrated pullup for SW !!)
It is better NOT to use internal pull-up resistors on the Arduino, instead
use the integrated pull-ups of KY-040 (this requires “+” to be connected to 5V).
You can check if your version of the KY-040 has pull-up resistors on the bottom
side ouf the printed circuit board.
If not, use internal pull-ups from Arduino or external pull-ups.
In the stopping positions the KY-040 has always HIGH signals on both CLK and DT.
When you turn the encoder from one position to another, either CLK or DT goes LOW
before the other signal goes LOW as well.
The signal that goes LOW first determines if the encoder is turned left or right.
Once you reach the next stopping position both signals will be HIGH again.

If you press the push button, the current count can be reset to ZERO.

For faster response you might increase the speed of the serial connection.
(Make sure, that the Serial Monitor is also set to a higher speed,
otherwise you will get no output).

My rotary encoder came from china for 2 dollars, and after some debugging i found out, that it sometimes
behaves strange (e.g. it gives a signal to the SW pin – although I did not press the button.)
So for serious projects invest a dollar more and buy a quality product.


Try this state machine based code. It uses two pins for pin-change interrupts. It’s nearly unbreakable.

It’s really pointless to try to filter an encoder with caps. What are the characteristics of your “noise”? What is the worst case period and rise-time of your bounce? What is the typical frequency of your bounce? No one knows, but somehow they know what capacitor value to use. On top of that, you are also filtering your “real” signal. You’re slowing the rise time and shortening the period of the signal you ARE interested in.

This state machine just follows the bounce. You can use a high dollar encoder or a very cheap one that has terrible bounce. The state machine will handle them both without the extra cost more components and a degraded signal.


If you count a pulse every time aVal changes state, (LOW to HIGH and HIGH to LOW) and don’t otherwise account for it, you will negate your counts and only count the spurious ones. Therefore use aVal *only* when it transitions from HIGH to LOW (or visa-versa, but this works, so I use it.) This seems to be the reason many have resorted to using Interrupts so they can use FALLING or RISING in their code. A change in the ‘if’ statement mimics the FALLING interrupt and made it all work with my encoders:

if ((aVal != aLast)&&(aVal==LOW)) {

The bold text above is the change. Now we use the datapoint only when transitioning from HIGH to LOW to indicate that the knob moved. And…

if(bVal == LOW){ encoderCount++; }
else { encoderCount–; } }

Gives direction. If bVal is also LOW, then the knob was turned CW, so lets increment our counter by one step. Else, if bVal was HIGH, CCW and let’s decrement our counter.

This works from fairly slow up to a fairly fast knob rotation. And NO USE OF INTERRUPTS!

Full Code with Serial Print to Monitor:


Board Interrupt
(do not use)
Teensy 3.0 All Digital Pins 13
Teensy 2.0 5, 6, 7, 8 11
Teensy 1.0 0, 1, 2, 3, 4, 6, 7, 16
Teensy++ 2.0 0, 1, 2, 3, 18, 19, 36, 37 6
Teensy++ 1.0 0, 1, 2, 3, 18, 19, 36, 37
Arduino Due All Digital Pins 13
Arduino Uno 2, 3 13
Arduino Leonardo 0, 1, 2, 3 13
Arduino Mega 2, 3, 18, 19, 20, 21 13
Sanguino 2, 10, 11 0


Leave a Reply

Your email address will not be published.