Become a subscriber (Free)

Join 29,000 other subscribers to receive subscriber sale discounts and other free resources.
Don't worry -- your e-mail address is totally secure. I promise to use it only to send you MicroZine.

Rotary Encoder : How to use the Keys KY-040 Encoder on the Arduino

A rotary encoder is an input device that you can rotate in either direction continuously. As you turn the device it generates digital pulses that indicate an incremental change - the coding of the pulses also indcates the rotational direction (Clockwise or Counter-Clockwise). They are extremely useful for use in control panels where you want to control a parameter and allow accurate incremental control to change a parameter up or down.

The type of encoder used below for demonstration is also known as an incremental rotary encoder since it generates pulses indicating single step changes.

The purpose of this tutorial is to provide an example for the arduino of a simple rotary encoder implementaion.

Rotational Encoders allow you to easily increase or decrease paramaters by a single value.

As well as generating directional information and step change pulses the device has a physical feedback mechanism that lets you feel when you move from one position to the next. These points are known as detents and range from 12 to 24 positions within a 360° rotation. For the device used here there are 20 detents.

Unlike a potentiometer the rotary encoder has no end stops so you can use one to continually increase or decrease a parameter (once decoded by the microcontroller) and there is no need to set the control position back to a start point (there is none).

They also often have a push button switch built into the shaft that activates when you push it.

You can use them for many applications ranging from:

  • Volume control
  • Illumination level control
  • Parameter control e.g. for a process e.g. speed, height, temperature etc.
  • Menu selection (the push button is useful to select the menu item).

Since the outputs are digital signals you can process them using a microcontroller and use the result in any way you want i.e. to change the value of a variable representing a system parameter.

The Keys-040 device, described here, has a 20 positions (detents) and includes a push button switch that activates (momentary push to make) when you push the control shaft.

In fact rotary encoders look simple, but there is quite a lot going on inside these small devices (~11mm x ~13mm ).

Here's what is going on:

  • Two outputs providing quadrature coded signals.
  • Physical position feedback and bump stop (known as detents) - for this device there are 20 detents.
  • Main shaft push button (a push to make switch).

As you turn the control knob you can feel the each of the 'detent' position stops, so you know when you have turned the device by exactly one position. This provides fine grained physical feedback allowing exact parameter changing. This is very different to using a potentiometer to set the volume level etc. where there is no physical feedback.

Quadrature Phase Shift Encoding

This rather technical sounding encoding method is in fact very simple. all it means is that two signals are offset from one another by a quarter of a period (or phase shifted by 90°). It also falls out in the wash that the signals generated are grey coded which just means that no two signals edges are aligned i.e. signal outputs do not change state at the same time.

Gray coding is useful for electro-mechanical devices to generate signals that are unambiguous. For example if the output was binary coded then at the point of transition (due to small delays in signal paths) you might decode a completely erroneous value i.e. at the point of transition any codes could be generated.

This could be a problem especially if only combinatorial logic is used as the decoder. Gray code stops that from happening (although it does not stop switch bounce).

The following diagram shows the rotary encoder waveform output on pins A and B (CLK) and (DT) respectively.

rotary encoder quadrature signals A and B

[Source PEC11L datasheet]

Note: The D in the diagram above shows where the detent position is located. In fact this is where the outputs are not connected to ground hence they are pulled high by the 10k resistors on the breakout board.

Inside the Rotary Encoder

The following diagram shows the inner workings of the rotary encoder. Each of the three connections 8A, 8B and 8C is formed of a spring arm that pushes down on the substrate.

There are three signals, one connected to the metal substrate (Ground) and two others that move over the alternating substrate pattern. So the outputs are shorted to ground as the device is rotated and then are left floating (unconnected) when the contact is in the substrate gap.

Note how the spring arm contacts are physically offset by a quarter of the period (defined by the physical substrate) - contacts 8B and 8C in the diagram below - this is how the quadrature encoded outputs are generated.

internal rotary encoder operation

Source: Expired Patent (Now in the public domain).

Note: The contacts 8A, 8B, 8C are springs that bounce on and off the contact substrate causing the output signals to bounce between high and low i.e. switch bounce.


The rotary encoder used in the KY-040 looks like a Bourns PEC11L device - you can download that rotary encoder datasheet from the link below. All that the breakout board does is add two 10k pullup resistors (R2 and R3) while the space for the switch pullup has been left blank.

Download PEC11L datasheet.

Types of Rotary Encoder

Contacting Incremental Rotary Encoders

This is the type of device used in the demonstration on this page. At each detent position two quadrature signals are generated indicating a single position change and showing the direction of rotation.

This particular device has quite a high rotational life - 100k rotations (see datasheet) - but since there is physical contact, the device will eventually wear out. In the Bourns catalogue other physical devices range from 15k to 200k maximum rotations.

Optical Encoder

The PEC11Lhas a maximum RPM of 60RPM whereas optical encoders, in that catalogue, have a 10 million revolution life and can operate at 3000rpm - these are the types you could use for measurements in high speed machinery but see magnetic encoder below which has an even higher life and of course a higher cost!

Magnetic Encoder

For even higher rotational life, a magnetic encoder offers the best choice (since there is no physical contact within the device) the only part that will wear out is the shaft bearings. These offer a rotational life of 100 million revolutions!

These devices come in 4 different flavours:

  1. Incremental Quadrature (same as the PEC11L used here).
  2. Direction/Step encoder - offers better resolution (up to 512 pulses per revolution).
  3. Absolute encoder - allows the absolute position detection of the encoder (1024 codes define the position).
  4. PWM Encoder - generates a PWM output from 1us to 1024us width - advantages claimed, are noise immunity and faster data acquisition.

Decoding Methods

There are two methods for decoding the rotary encoder outputs:

  • Polling
  • Interrupts

On the KY-040 there are two signals labelled DT and CLK meaning CLOCK and DATA. If you look at the timing diagrams for these signals it seems obvious to use the CLOCK as a clock and read the DATA input on the rising edge of the clock. However this ignores the fact that the signals bounce all over the place.

If you use the CLK signal as an interrupt you will get into deep trouble as the random bouncing of the input will trigger interrupts all the time (and not at the time when you want to read the data signal) so you will get incorrect data.

There are polling methods to decode the grey coded signals using a state machine so that bouncing signals are ignored i.e. error states are ignored. These are quite complex and sometimes get out of sync.

The way I use these devices is a combination of a small amount of smoothing capacitor and a simple digital debounce algorithm. (See code below). This provides easy to understand code (also small code size) and works to accurately obtain individual detent position information and also accurate directional rotation information.

Measurements: Using Rotary Incremental Encoders

The following examples cover the following measurements:

  • Velocity
  • logarithmic change


You might want to measure velocity to use as a parameter in your code e.g. if you turn the wheel faster then perform a different action e.g. change the parameter at a different rate.


This is a parameter adjustment that measures the rotation speed and if found to be constant periodically increases the parameter. This is very useful for devices that have a large range of control e.g. a DDS (Direct Digital Synthesis) that can output frequency form 1 to 10MHz. You really don't want to sit there turning the knob by 1Hz periods to get to 10MHz!

Device Decoding

You can use many clever ways to decode the outputs involving complex state machines and gray decoding algorithms. Some use interrupts and most use polling. The problem with connecting the outputs to an interrupt pin is that you have no control over the bounce that you may experience and the processor could be interrupted too much to do any useful work (and may even hang) and will get the wrong value from the data input anyway.

Warning: Rotary encoders are extremely noisy because of switch bounce due to the internal construction of the device (using physical contact springs that bounce over the substrate connections). This makes it extremely difficult to accurately decode the device outputs.

Switch bounce occurs as the contacts are springs that bounce on and off a substrate contact - even the data sheet indicates the switch bounce you can get for each turn is up to 10ms (Bourns PEC11L).

rotary encoder quadrature signals A and B

[Source PEC11L datasheet]

You can see that the signals labelled A and B can be changed to CLK (clock) and DT (data) and that a rising edge on a clock signal (A) will give a a logic low on DT (B) if turned clockwise and a logic high if turned anti-clockwise (when turned in the opposite direction the falling edge becomes the rising edge!).

Capacitor Smoothing

Adding a huge smoothing capacitor to stop the bounce (plus resistor) will stop the bounce but also slows the input signal level to the point where it will go through the undefined logic input level (neither high or low) of the microcontroller. In this input region noise on that input could trigger the input to high or low causing oscillation i.e. making more bounce signals and not solving the problem at all.

You can get around this by using a schmitt triger device such as a 74HC14 to create the correct fast edge signals but you may alter the timing too much.

RC pair and digital Filter

The best way I have found is to use a small smoothing capacitor resistor pair along with a digital debounce filter. This allows individual detent positions to be accurately identified (slow turning of the control shaft is accurately decoded). At faster revolutions codes are missed but the real point of the rotary encoder is to allow accurate individual detent (and direction) detection. You don't need to know exact detent stops for fast revolutions - all you need is to know that the user wants to increase the parameter faster.

Arduino Rotary Encoder Software Setup:

IDE Version Used : 1.6.4
Board used : Arduino Uno R3
Device Used : KY-040 (breakout board)

Other components 10k resistor and 10nF capacitor - only for the clock signal, connected as shown below:

rotary encoder connections

[Source PEC11L datasheet]

Note: 10k and 10n are extra to the breakout board (A and B have the 10k pulups on the board). Only add them to the clock signal (A).

Example Rotary Encoder Code:

This is a an arduino ky-040 rotary encoder example that shows you how to decode the 20 turn encoder by removing switch bounce.

Note: The quality of the encoder will affect the output signal (one of mine skips codes whereas a higher quality one does not!).

Note: Clicking any text in the box below will copy the whole lot to the clipboard.

#define CLK_PIN  2
#define DATA_PIN 7
#define YLED A1

void setup() {

   Serial.println("Rotary Encoder KY-040");

void loop() {
static uint16_t state=0,counter=0;

    delayMicroseconds(100); // Simulate doing somehing else as well.

    state=(state<<1) | digitalRead(CLK_PIN) | 0xe000;

    if (state==0xf000){

New! Comments

Have your say about what you just read! Leave me a comment in the box below.

Privacy Policy | Contact | About Me

Site Map | Terms of Use


Visit our Facebook Page:

   Click Here

Recent Articles

  1. Rotary Encoder

    How to easily use a rotary encoder on an Arduino without lots of complex code.

    Read more

  2. The 16F877A PIC microcontroller.

    Using the 16F877A and the differences between the 16F877A and the 16F887

    Read more

  3. Which PIC device is closest to Arduino Uno?

    In fact the 18F series 18F2550 is closest but in addition it has a built in USB interface. Leran ore by following the link...

    Read more

Sign up for MicroZine
''The'' Microcontroller Newsletter

Enter your first Name and primary email address in the form below:

And receive absolutely FREE a full project for:

"Measuring Analogue Voltages
Without An ADC"

(Using only one pin).

Instant Download:
You Can
Get It Right Now

Warning: This project could be  Removed 
at any time.  

It will  NOT be 
available indefinitely SO
To avoid 
disappointment  get it:


Don't worry -- your e-mail address is totally secure. I promise to use it only to send you MicroZine
Remember this is a project with full description and fully debugged C Source code - and it's not available from the main website.

You can only get it through this newsletter.

To get exclusive access Enter your first name Name and primary email address Now in the form above.:

But wait !

There's more...

You'll receive more
free and exclusive reports as well as site information and site product updates

Scroll up to the form above and sign up NOW. Don't forget it's FREE and if you don't like it, you can unsubscribe at any time.

Click Here Now to use the form above to get your Valuable information absolutely free.

Readers Comments

"I wanted to thank
you so so so much
for all the information
you have provided in
your site it's


- Ranish Pottath

"This site really is
the best and my favorite.
I find here many useful
projects and tips."

- Milan


"Awesome site,
very, very easy and nice
to navigate!"

- Matt

Learn Microcontrollers

"Interested in

Sign up for The
Free 7 day guide:


"I am a newbie to PIC
and I wanted to say
 how great your
site has been for me."

- Dave


"Your site is a great
and perfect work.

- Suresh


"I couldn't find the correct
words to define
yourweb site.

Very useful, uncovered,
honest and clear.

Thanks so much for
your time and works.

- Anon

Back to Top