In this post we will go over how to use a Rotary Encoder (KY-040) with Arduino. We’ll focus on basics, module pins, how to connect to Arduino, programming in Arduino IDE, and testing.
What is a rotary encoder?
A rotary encoder is a sensor used to determine the angular position of a rotating shaft. The shaft itself can be part of the sensor or the sensor can have a hole for a shaft to go through (ideal when you want to attach the sensor to a piece of rotating equipment). In this post, we will focus on a rotary encoder with a shaft attached to it in the form of a knob.
You might be familiar with potentiometers, which are also able to measure the angular position of the knob. The main difference (from an application point of view) is that the potentiometer can only rotate through a ~70% of the total circle, while rotary encoders can rotate endlessly in any direction (think of the volume of AC control knob in a car’s dashboard).
Without getting too complex, the encoder will two separate output signals A and B which will switch between a High output and a Low output as the rotary encoder knob rotates. Depending on the direction of rotation, the A signal maybe happen first (before the B signal), or vice versa. This can be used to determine the direction of rotation, which can then be used to determine the total position as it’s rotated clockwise or counter-clockwise.
Sensor Pins and Connection to Arduino
CLK (Output A) – Output to determine the encoder rotation.
DT (Output B) – 2nd output to determine the encoder position (if used along with CLK, can be used to determine the direction of rotation).
SW – Pin for the sensor’s built-in push button.
VCC – Sensor input voltage pin (can connect to 3.3V or 5V).
GND – Ground connection pin.

Rotary Encoder – Example #1
We’ll now go through a simple example to introduce you to the use of a rotary encoder. In this example we will:
- Determine the absolute position of the encoder going from -100 to 100.
- Each point is equal to one click in the encoder.
- If you continue rotating past +100 or past -100, the code will max out the count at +100 and -100.
- Think of it as getting to the max/min volume on a radio or the max/min temperature on the car A/C.
- Determine the input into the encoder push button.
- Detect a single push, double push, or long push.
- We will use an Arduino library for this.
Required Arduino Libraries
We will be using the ButtonFever library by Mickey9801. You can read more about it on GitHub –> LINK.
To installed the ButtonFever library go to the top menu, click on “Sketch”, then “Include Library”, “Manage Libraries…”. Then type “ButtonFever”, then click install on the row for the ButtonFever library.
Arduino Code – Example #1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
//Arduino Code - Rotary Encoder w push button #include <BfButton.h> int btnPin=3; //GPIO #3-Push button on encoder int DT=4; //GPIO #4-DT on encoder (Output B) int CLK=5; //GPIO #5-CLK on encoder (Output A) BfButton btn(BfButton::STANDALONE_DIGITAL, btnPin, true, LOW); int counter = 0; int angle = 0; int aState; int aLastState; //Button press hanlding function void pressHandler (BfButton *btn, BfButton::press_pattern_t pattern) { switch (pattern) { case BfButton::SINGLE_PRESS: Serial.println("Single push"); break; case BfButton::DOUBLE_PRESS: Serial.println("Double push"); break; case BfButton::LONG_PRESS: Serial.println("Long push"); break; } } void setup() { // put your setup code here, to run once: Serial.begin(9600); Serial.println(angle); pinMode(CLK,INPUT_PULLUP); pinMode(DT,INPUT_PULLUP); aLastState = digitalRead(CLK); //Button settings btn.onPress(pressHandler) .onDoublePress(pressHandler) // default timeout .onPressFor(pressHandler, 1000); // custom timeout for 1 second } void loop() { // put your main code here, to run repeatedly: //Wait for button press to execute commands btn.read(); aState = digitalRead(CLK); //Encoder rotation tracking if (aState != aLastState){ if (digitalRead(DT) != aState) { counter ++; angle ++; } else { counter--; angle --; } if (counter >=100 ) { counter =100; } if (counter <=-100 ) { counter =-100; } Serial.println(counter); } aLastState = aState; } |
Rotary Encoder – Example #1 Results
Once you connect the Arduino UNO as shown above and run the code above, open the serial monitor. Once you do, you can rotate the rotary encoder’s knob and push the button. You will see:
- A count increase/decrease based on the direction of rotation.
- If you push the button once, you will get a “Single push” message.
- If you push and hold the button, you’ll see a “Long push” message.
- If you do a double tap, you’ll see a “Double push” message.
Rotary Encoder – Example #2 (LED Flash Brightness Control)
In this example we will use the rotary encoder to control the brightness of an LED flash.
- Rotating the encoder will result in an increase or decrease of LED brightness.
- Pressing the push button once will take the brightness to the maximum level.
- Pressing and holding the push button will turn off the LED.
- Double tapping the push button will take the brightness to a pre-defined level (in this case low brightness).
*Note that this LED flash comes built-in with the appropriate resistance to ensure we don’t burn it, so it’s not the same as your typical LED that needs a resistor in series.
Connections to Arduino for Example #2

Click to enlarge
*Note that the LED flash used in this example is a ready-to-use component with a built-in resistor, which is why a separate resistor is not needed.
Arduino Code – Example #2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
//Arduino Code - LED Brightness Control with Rotary Encoder #include <BfButton.h> int btnPin=3; //GPIO #3-Push button on encoder int DT=4; //GPIO #4-DT on encoder (Output B) int CLK=5; //GPIO #5-CLK on encoder (Output A) int LED_Pin=6; //Pin used for PWM signal to control LED brightness BfButton btn(BfButton::STANDALONE_DIGITAL, btnPin, true, LOW); int counter = 0; int angle = 0; int aState; int aLastState; int prev_counter = 0; //Button press hanlding function void pressHandler (BfButton *btn, BfButton::press_pattern_t pattern) { switch (pattern) { case BfButton::SINGLE_PRESS: Serial.println("Single push"); counter = 255; Serial.println(counter); break; case BfButton::DOUBLE_PRESS: Serial.println("Double push"); counter = 70; Serial.println(counter); break; case BfButton::LONG_PRESS: Serial.println("Long push"); counter = 0; Serial.println(counter); break; } } void setup() { // put your setup code here, to run once: Serial.begin(9600); Serial.println(angle); pinMode(CLK,INPUT_PULLUP); pinMode(DT,INPUT_PULLUP); pinMode(LED_Pin, OUTPUT); aLastState = digitalRead(CLK); //Button settings btn.onPress(pressHandler) .onDoublePress(pressHandler) // default timeout .onPressFor(pressHandler, 1000); // custom timeout for 1 second } void loop() { // put your main code here, to run repeatedly: //Wait for button press to execute commands btn.read(); //Encoder rotation tracking aState = digitalRead(CLK); if (aState != aLastState){ if (digitalRead(DT) != aState) { counter ++; angle ++; } else { counter--; angle --; } if (counter >=255 ) { counter =255; } if (counter <=0 ) { counter =0; } Serial.println(counter); } aLastState = aState; analogWrite(LED_Pin,counter);//Set the LED brightness } |
Rotary Encoder – Example #2 Results
Connect the Arduino UNO, rotary encoder, and other components as shown in the previous image, then upload the code above, and then proceed to test. You should get the results described at the beginning of this example section and as shown below:

Components used in this example
*As an Amazon & Ebay Associate I earn from qualifying purchases.
Component | Link |
Arduino UNO | https://amzn.to/3uYVAMC https://ebay.us/veZdKX |
Rotary Encoder (KY-040) | https://amzn.to/3bPnOm5 https://ebay.us/gJKeKc |
Hilitchi Transistors Assortment Kit | https://amzn.to/3gf2nOl https://ebay.us/8BLbQA |
Breadboard (Elenco 9440) | https://amzn.to/3x23dnq https://ebay.us/FcwSdb |
Super bright LED Flash (not an affiliate link) | https://www.superbrightleds.com/moreinfo/led-wired-bolts/little-dot-smd-led-accent-light/639/ |