Rotary encoders are electronic devices that can measure mechanical rotation. They can be used in two fashions – As a control or as a device to measure the rotation of a shaft.

When used as a control, rotary encoders can be much more versatile than a potentiometer.  They can be used when you need a very precision control, and they are not subject to drift due to temperature.

As a device to measure mechanical rotation rotary encoders have several uses. One of them is to measure the rotation of a DC gearmotor.

Rotary Encoders

Today we will look at both types of rotary encoders. I will show you how to hook them up to an Arduino and I’ll give you some demonstration sketches that you can run yourself.

So let’s get started!

Rotary Encoders

A rotary encoder, which can also be referred to as a shaft encoder, is an electro-mechanical device that can convert the angular position (rotation) of a shaft to either an analog or digital output signals.  We will be focusing on digital devices today.

There are two main types of rotary encoder: absolute and incremental. The difference is the absolute encoder gives the precise position of the shaft in degrees, whereas the incremental encoder reports how many increments the shaft has moved, but not its actual position.

Rotary Encoders - 2 Types

Rotary encoders are used in many different applications including industrial controls, robotics, optomechanical mice and trackballs, CNC machines and printers.

Rotary Encoder Operation

There are several different types of rotary encoders. I’m restricting this discussion to the simpler “incremental” encoders. These are sometimes called quadrature or relative rotary encoders.

These encoders have two sensors and output two sets of pulses. The sensors, which can be magnetic (hall effect) or light (LED or Laser), produce pulses when the encoder shaft is rotated.

As there are two sensors in two different positions they will both produce the same pulses, however, they will be out of phase as one sensor will pulse before the other one. Which sensor goes first is determined by the direction of rotation.

Rotary Encoder Operation - CW

In the above example the encoder shaft is spinning clockwise. The sensor on the top is triggered before the bottom one, so the top set of pulses precedes the bottom set.

Rotary Encoder Operation - CCW

If the encoder shaft is rotated counterclockwise then the bottom set of pulses will be delivered before the top set.

In both cases the pulses can be counted to determine how much the shaft has rotated. By checking to see which pulse comes first we can determine the direction of rotation.

Control Encoder

The control encoder we are going to use is a very common device, and it’s available from several sources. It’s also included in the infamous “37 in one” sensor kit that is available at many electronic stores and online.

Control Encoder Pinout

The encoder can be mounted exactly like a potentiometer, and it has a D-shaft to accept a knob. It also has its own push button momentary contact switch that can be activated by pressing down upon the shaft.

The pinouts of the control encoder are as follows:

  • GND – The Ground connection.
  • +V – The VCC or positive supply voltage, usually 3.3 or 5-volts.
  • SW – The pushbutton switch output. When the shaft is depressed this goes to ground level.
  • DT – The Output A connection.
  • CLK – The output B connection.

I will show you how to use this control encoder in a moment, but first, let’s look at the other rotary encoder we will be discussing today.

Motor Encoder

Motor encoders are mounted on the shaft of a DC motor and can count the amount that the motor shaft has moved. Coupled with a motor driver, this will allow you to create a feedback mechanism that can permit you to specify how much you would like the shaft to turn.

You can also use these encoders as a tachometer to measure the speed that the shaft is rotating.

Motor Encoder Pinout

The encoder I’m illustrating here is the one that is attached to the gear motor I am using in my DB1 Robot from my Build a REAL Robot series of articles and videos. It is a goBILDA 5201 Series Spur Gear Motor with a built-in encoder.

Other motor encoders should have similar connections.

The connections are very basic:

  • VCC – the 5-volt power supply input.
  • GND – The Ground connection.
  • CH A – Output A.
  • CH B – Output B.

We will see how to use this with an Arduino to measure the motor RPM very soon.

Reading Control Encoders

We will begin our rotary encoder experiments using the control encoder.

Reading a control encoder with an Arduino is actually fairly straightforward. We just need to read input pulses and count them. We also need to determine which set of pulses is occurring first, so that we can determine the direction of rotation.

Arduino Control Encoder Test Hookup

Here is how we will hook up our first rotary encoder experiment.

Arduino Encoder Test Hookup

You will notice that in addition to the rotary encoder I have added a couple of LEDs. These will indicate the direction that we are spinning the encoder shaft.

The dropping resistors for the two LEDs are any value from 150 to 470 ohms, in the illustration I show 220 ohm resistors.

Incidentally, none of the pins used on the Arduino are critical. You can change them around, provided that you alter the sketch accordingly.

Arduino Control Encoder Test Sketch

Now that you have your encoder and LEDs hooked up you’ll need a sketch to make it all work. Here is the one I came up with:

We start the sketch by defining some constants to represent the inputs from the encoder and the outputs to the two LEDs.

Next, a few integer variables are defined. The counter variable represents the count that will be modified by turning the controller, it can be a positive or negative number..

The currentStateCLK and previousStateCLK variables hold the state of the CLK output (Output B), these are used as part of the system to determine the direction of rotation.

A string called encdir is defined, it will be used when we print the current direction of rotation to the serial monitor.

Now on the the Setup section.

The Setup is pretty straightforward, we setup the serial monitor, define the connections to the encoder as inputs and the connections to the two LEDs as outputs.

At the end of the Setup we read the current value of the CLK pin and assign it to the previousStateCLK variable.

And now the Loop, where all the action takes place!

We check the CLK input and compare it to the previousStateCLK value. If it has changed then a pulse has occurred.

Next the logic to determine the direction of rotation. We now look at the DT pin on the encoder module and compare it to the current state of the CLK pin.

If it is different then we are rotating counterclockwise. We then decrement the counter variable value, set encdir to hold a value of “CCW” and turn on the red (CCW) LED.

If, on the other hand, the two values are the same then we are moving clockwise. We do the opposite – increment the counter, write “CW” to the encdir variable and turn on the Green (CW) LED.

After we print our results to the serial monitor we update previousStateCLK with the current state of CLK.

Then we do it all over again.

Arduino Encoder Demo

Load the sketch and observe both the serial monitor and the two LEDs. When the CW LED is lit the value in the serial monitor should increment. Otherwise, the CCW LED will be lit and the value will decrement.

You may use this sketch as the basis for your own encoder projects. In fact, the next demo does exactly that!

Control Encoder with Servo Motor

The next experiment we will perform is to use a rotary encoder to control the position of a servo motor.

This is a great application for a rotary encoder as it will let you position the servo motor very precisely. It would be a great way to operate a robot arm, for example, as it would let you precisely position the arm and its grip. Of course, you would need to add more encoders and more servo motors to the design.

Arduino Servo Hookup

The hookup for the servo motor controller is illustrated below:

Arduino Servo Hookup

One thing to note is that I have used a separate power supply for the servo motor. I always recommend doing this as the servo can induce electrical noise onto the 5-volt line that the Arduino uses. But, if you really must, you can eliminate the extra supply and use the Arduino 5-volt output.

Again the pinouts are not critical but if you do change them you’ll need to make sure to use a digital I/O pin on the Arduino that supports PWM for the servo control lead.

Arduino Servo Control Sketch

Here is the sketch you will need to use to control the servo motor with the rotary encoder.

If you compare this sketch to the previous one you’ll undoubtedly notice many similarities. It starts out by defining many of the same variables, without the LEDs of course as they are not used here.

We also include the built-in Arduino Servo library and define a myservo object to represent our servo motor.

The counter, currentStateCLK and previousStateCLK variables are used again.

In the Setup we attach the myservo object to pin 9, which is where the control lead of the servo motor is connected.

The Loop is also very much like the previous sketch, with some notable exceptions.

Since a servo motor only accepts a value between 0 and 180 we limit our results to this range.

After getting the counter value we use it to position the servo motor. The value should represent the position of the servo arm in degrees.

We print this position to the serial monitor, reset the previousStateCLK variable and do it all over again.

Arduino Servo Demo

When you run the sketch observe both the arm on the servo motor and your serial monitor. The arm position should correspond to the reading on the serial monitor.

This is a very accurate method of positioning a servo motor.

Using Gearmotor Encoders

Now that we have seen how to use control encoders let’s turn our attention to encoders used with gearmotors.

As with the control encoders, the motor encoders have two outputs. This will allow you to determine the direction that the motor is spinning.

I am actually NOT going to decode the motor direction as I don’t really see the point – after all I am the one spinning the motor in a specific direction so I already know which way it is going!

Motor Encoder Output

Before I hook up the encoder to an Arduino thought it might be a good opportunity to take a look at the pulses that it produces. So I hooked the two outputs up to my oscilloscope.

Motor Encoder Output

As you can see from the scope traces the two outputs are nice square waves, offset from each other.  

You could also use the two square waves to make a more accurate encoder, reading the combination of pulses to get much finer resolution. However, as my encoder gives out 374 pulses per rotation it is already accurate to less than a degree. That is accurate enough for my purposes.

Arduino Motor Encoder Hookup

Now let’s test the encoder with an Arduino. We will hook it up, along with a motor driver and a potentiometer to control speed and read the RPM of the motor.

Arduino Motor Encoder Hookup

The motor driver I am using is the Cytron MD10C, which I have used in the article Controlling Large DC Gearmotors. You can read more details about it there if you like. It is very simple to use, requiring only a power supply for the motor to power its internal logic circuits.

I also used a 12-volt power supply, as that is the recommended voltage for my motor.  

The potentiometer I used was a 10k linear-taper. Any value from 5k or higher will work.

The connections from the Arduino to the encoder are as follows:

Arduino Pin Encoder Pin
5V (5-volt output) VCC
Ground GND
3 CH A (Output A)

Actually, you could have used Output B instead, as I’m not measuring the direction of rotation, just the position.

The input connections to the Cytron MD10C motor driver are as follows:

Arduino Pin Cytron MD10C Input Pin
12 DIR (Direction)
10 PWM
Ground GND

I’m not actually using the DIR pin as in this sketch I’m not controlling the motor direction, so you can leave it out if you wish.

The output of the motor controller is connected to, what else, the motor! And the power supply is connected to the power inputs, be sure to observe the proper polarity.

The potentiometer is hooked to analog input A0, so we can control the motor speed.

Arduino Motor Encoder Sketch

Now that we have our motor hooked up it’s time to run the sketch to control and read its speed.

In this sketch we will need to use interrupts to count pulses from our encoder, this is because our pulses will be arriving pretty quickly as compared to reading an encoder control.

Before we can use the sketch we need to know how many pulses our encoder will produce for one rotation of the motor. You can determine this from the specification sheet for your motor.   Without this value, you won’t be able to get an accurate RPM reading.

My motor produces 374 pulses per rotation, so I set the constant ENC_COUNT_REV to this value.

The next few lines define the pins that connect to the motor encoder, motor driver and to the potentiometer.

We will use the long encoderValue to keep track of the pulses we receive from the encoder. Then we will count how many of these occur in one second. By multiplying this by 60 we’ll know how many pulses we should get in a minute. If we divide this value by the ENC_COUNT_REV then we can determine the RPM of the motor shaft.

We will measure the one-second interval by keeping track of the number of milliseconds that have elapsed. The Arduino millis() function counts the number of milliseconds since the Arduino was last reset or powered on, so we can get out interval using this.

At the bottom of the sketch is an interrupt handler, it simply increments the value of encoderValue when it is triggered by a pulse from the encoder.

In the Setup we attach the interrupt handler to the pin connected to the encoder (pin 3), we trigger on a rising pulse.

The Loop starts with reading the value of the analog input connected to the potentiometer.  We use the Arduino Map Function to change its range to 0-255 and an analogWrite command to send a PWM signal with this value to the motor controller. This results in the motor turning at the desired speed.

We see if 1000 milliseconds have elapsed, if so we read the count and do the math to determine the RPM. We then print the values to the serial monitor. Note the use of the tab character to format these results in nice columns.

After printing the value we reset the encoderValue variable to zero so we can begin counting again.

Arduino Motor Encoder Demo

Load the sketch and power everything up. Turn the potentiometer and observe the motor turning, as well as the value on the serial monitor.


Rotary encoders are pretty versatile, they can be used as both controls and as sensors.

As controls, they have much greater precision than a potentiometer, and they cost just a little bit more. I know that I’m planning to create many of my future designs using them.

I also will be building a complete motor controller using the rotary encoder included with my gear motor.  Being able to position my robot to within less than a millimeter is an extremely attractive proposition.

I hope this article, and its associated video, have opened your eyes to some tasks you can perform with a rotary encoder.



Sketches – ZIP file with all of the sketches used in this article.



Using Rotary Encoders with Arduino
Using Rotary Encoders with Arduino
Article Name
Using Rotary Encoders with Arduino
Rotary Encoders can be used in two fashions - as a control with more versatility than a potentiometer, and as a device to measure mechanical rotation. Today I will show you how to use both types of rotary encoders.
Publisher Name
DroneBot Workshop
Publisher Logo
Tagged on:

If you have a question...

Comments about this article are encouraged and appreciated. However, due to the large volume of comments that I receive, it may not be possible for me to answer you directly here on the website.

You are much more likely to get answers to technical questions by making a post on the DroneBot Workshop Forum. Your post will be seen not only by myself, but by a large group of tech enthusiasts who can quickly answer your question. You may also add code samples, images and videos to your forum posts.

Having said that, please feel free to leave constructive comments here. Your input is always welcome. Please note that all comments may be held for moderation.

Newest Most Voted
Inline Feedbacks
View all comments
Jesper S. Nielsen
1 year ago

Hi Bill,
I have just built the Control Encoder Test Hookup. It’s like every time I turn the encoder one tick it counts two in value on the serial monitor. Is that normal ?


Jesper S. Nielsen
1 year ago

Hi Bill,
I think the rotary encoder I have from e-bay KY-040 is supposed to have double count per tick.

1 year ago

Hi Jesper,
see my comment made above…

4 months ago

The encoder might be experiencing some mechanical noise. To help alleviate this you can innroduce a debouncing method. Initialise a currentTick value by assigning the current millis() value to it. In the first if statement include the && operation that the statement can only execute once a certain amount of milliseconds have passed. I think 50 – 100 should be fine. At the end of each execution stage assign the currentTick value to a new variable previousTick value. This will ensure that the conditional execution is only exectued after a certain amount of time has passed after mechanical bounce has… Read more »

Abdulrahman Mostafa
1 year ago

If i bought motors with encoders built in but i don’t have any specification sheet to know how many pulses in one rotation.
So what can i do to know without specification sheet ?

Abdulrahman Mostafa
1 year ago

can you help me in my project

1 year ago

You make all this look like very simple. Thank you.

leonard HOYLAND
1 year ago

Hi Bill
I had trouble compiling the sketch to control the servo motor with the rotary encoder.
I subsequently found that the “{” is missing from line 43 at start of loop.
Hope this helps others!

robert isringhausen
1 year ago

rotary Encoder with servo motor when i try to to upload the sketch to the ardino uno it gives me a error on line 46 expected Arduino: 1.8.9 (Windows 10), Board: “Arduino/Genuino Uno”Arduino: 1.8.9 (Windows 10), Board: “Arduino/Genuino Uno” boat_control:46:2: error: expected initializer before ‘currentStateCLK’ currentStateCLK = digitalRead(inputCLk); ^ boat_control:49:1: error: expected unqualified-id before ‘if’ if (currentStateCLK != previousStateCLK);{ ^ boat_control:49:42: error: expected unqualified-id before ‘{‘ token if (currentStateCLK != previousStateCLK);{ ^ exit status 1 expected initializer before ‘currentStateCLK’ This report would have more information with “Show verbose output during compilation” option enabled in File -> Preferences. boat_control:46:2: error: expected… Read more »

1 year ago

Hi Bill
I had trouble compiling the sketch to control the servo motor with the rotary encoder.
I subsequently found that the “{” is missing from line 43 at start of loop.
Hope this helps others!

1 year ago

This is the answer
Hi Bill
I had trouble compiling the sketch to control the servo motor with the rotary encoder.
I subsequently found that the “{” is missing from line 43 at start of loop.
Hope this helps others!

1 year ago

Hi Bill, Thank you very much for your excellent lessons and how you made them, great fun! My rotary encoder also counts 2 counts with 1 click using your sketch. I think it has to do with the fact that in the sketch you DO check if there is a transition in the clock ((currentStateCLK != previousStateCLK)) but you do NOT check if that signal is a high->low or a low-> high transition as with one click/turn on the encoder you both have a 1->0 (falling edge) as well as a 0->1 (rising edge). What I added is after the… Read more »

1 year ago

hi bill, I was testing my encoder gear DC motor. i uploaded your code as above. On serial monitor it just shows counter value only 0 or 1 or -1 . Moreover when i rotate it alternates between CW and CCW . I even tried with encoder library but still same problem

1 year ago
Reply to  ahmed

Hi bill now w this problem is solved but another problem is that whether i rotate it CW or CCW it always run either “if ” or either “else” in both type of rotations.

Shengming Hu
1 year ago

Can you do the same operation with 3 V DC coin vibrating motors? I am working on a project that requires 16 – 32 motors to vibrate uniformly between 40 – 60 Hz. Thank you!

1 year ago

Thank you for the lesson on rotary encoders! Long time viewer, first time caller. Not sure if you enjoy reading stories from fans, but it couldn’t hurt to leave this here if you didn’t: I run a small PC gaming community, and enjoy flight simulators. I wanted to create a project I could share with our little group that others could make at home. A week ago, I had a little idea that I could make a super simple USB game controller for a PC flight simulator that consisted of just two rotary encoders, and in a matter of an… Read more »

1 year ago

Sir the … second program where you attach the encoder with the servo is not working when uploaded …
the error they gave is….. in this line.

// Read the current state of inputCLK
currentStateCLK = digitalRead(inputCLK);

error is :
exit status 1
expected initializer before ‘currentStateCLK’

what should i do?

Julio Oliveira
7 months ago
Reply to  muhammad

Line 43
void loop() is missing one “{” so it should be “void loop() {“

Wilfrido Tamayo
1 year ago

Hi Bill, with the system you set up or similar is it possible to control the motor to a precise constant speed? precise I mean keep it a earth sidereal speed (star tracking motor)?

1 year ago

Hi! Which specific rotary encoder is suitable for measuring number of rotations of a rotating shaft

Ar Dhoub
11 months ago

do you ever test detect rotation position and then using this control the rotation location? that would be very useful.

11 months ago

It registers two pulses per click.
The ALPS encoder (EC11J1524413) has two variants: One with two dents per cycle and the other with one dent per cycle.
The one on my devkit has one dent and goes trough all 4 states (quadrature/gray code) in one click.
Your code uses both the falling and rising edges of the clk(pin a) so it detects two transitions per click.
I changed the code so it only samples data (pin b) on the falling edge of clk (pin a).

Paul Castro
10 months ago

Hello Bill!!! How´s going???
Can I show the angle in a 16×2 display instead of a serial monitor???

Miklos Antal
10 months ago

Hi Bill,
I have just built the Encoder tester circuit and load your sketch.
I’ve used Grayhill 61BY22050 optical encoder with push button for my menu system.
I turn the encoder, and only for two steps with encoder counted the value on the serial monitor.
Is that normal?
Thx Mike

9 months ago

Hi Bill,
how would I implement a PID controller in the encoder hookup engine with arduino, because it helps me to control my autonomous robot. Thank you for your work.

8 months ago

Hello, I am from an “old Europe” country. I have an idea: It should be possible to control the stepping motors driving a cnc, to detect lost steps. I ordered encoders to be coupled to the stepping motors with 600 pulses per revolution, and two phases output signals, so I have to gain the direction signal myself; as far as I remember there are special chips for this purpose on the market. The program than has to compare the number of step pulses from the steering program with the number of encoder pulses and has to stop the cnc when… Read more »

Ray H
8 months ago

Hello Bill, LOVE your methodical approach, clear presentations too.! how ‘hard’ is it to ‘map’ 2 x 600 line encoder outputs so that the arduino stores the mapped positions of these X-Y encoders, in 10 memory slots, on an SD card, then be able to read back & output those stored X-Y postions as step & dir o/p’s to 2 x stepper drivers? the rate of output pulses would be the same rate as the collected X-Y coordinates data.(at this point). each memory slot would have to store multiple “passes” of the encoder positions to not cause the steppers to… Read more »

8 months ago

Line 43 of the servo demo is missing a curly brace.

Julio Oliveira
7 months ago
Reply to  fortney

Yeah, got it too today. “void loop() {“

6 months ago

I am working on a project to generate square signal with a 50% duty cycle.
I want to use Encoder to increase or decrease frequency.
Is there any idea and code

Steve Paschke
6 months ago

I love the way you explain the circuits and code. It makes it very easy to understand.

Andrew McMahon
5 months ago

Could you add some code to keep the motor at a constant speed under load, im doing a project with a wire feeder and when the wire reel is full it labours the motor opposed to when the reel is empty then the wire feeds at different rates which i need a constant wire rate.
Thank you

Josh Kindhart
5 months ago

I don’t understand why resistors aren’t included in the circuit between the rotary encoders and the 5v supplied by the Arduino. Isn’t the potential difference infinite when their is no resistor in the circuit? Does the rotary encoder have an included resistor?

3 months ago

Thank you so much for sharing your knowledge but I need your help with my rotary encoder it has a 600 ppr and I cannot get it to work properly with an arduino I need to measure distance at a 9M a minute
Thank you for your time
Much appreciated

Pedro A. Vazquez
3 months ago

You can write a very important book about any Arduino and all of the information about all the topics you publish here.

2 months ago

First off ,thank you for the great website and body of work that you share. yours is my “Go to” site. Your presentation is the best!   I have been attempting to make a liquid mirror telescope over the past couple of years and my present iteration is using a rotary encoded geared motor to drive my dish. Of course my first port of call for information was this site.   I have since used your sketch as the basis of mine with a couple of differences which I thought you may like to make a future video of.  … Read more »

1 month ago

Wow it amazing how I find the blog more interesting and it is good that I came by. Very excellent tutorials

1 month ago

Hi Bill,
thank you so much for the servo control sketch. finally I can use it on my model train for rotate the track at the engine shed. greetings from germany

Dave White
30 days ago

Erm, *expected initializer*
You missing { just after the void loop…
Just thought I’d share this or it will not work as shown.

This thing sucks
21 days ago

Can anyone please get the shitty subscribe and comments buttons away?

Neil Barnett
14 days ago

The double count is a fault in the code. You test for change in clock, but not which edge it is, then you test for change in the data, but not which direction it is. I’m surprised it ever worked right. This example code has been used by many writers showing how to use these encoders and it always does the same thing. Jurgen’s comment below shows how to get just one count at a time. Or you can divide by 2 if you don’t want to change the code. There are now libraries that simplify encoders and debounce them… Read more »

Would love your thoughts, please comment.x