Rotary Encoder

Wheel mounts for rotary encoder
Wheel mounts for rotary encoder

Basically, Rotary Encoder converts the angular motion of wheel or shaft intoanalog or digital codes, and by codes we can count the number of rotations of the same. That seems pretty simple. 😛


First thing one faces in robotics, is the motion update of the bot. This motion update requires the tracking of the number of rotation which when multiplied by the circumference of the wheel base gives the distance travelled. However, this approach is not for motion including turns 😛

Types of Rotary Encoders?

Generally, there are two types of rotary encoders: absolute and incremental.

Absolute:An absolute encoder produces a value that is representative of the absolute position of the angle of rotation either in analog or digital code.

Incremental: An incremental encoder generates digital signals that decrease or increase the measurement incrementally, providing information regarding the general position of the shaft.

Depending on the number of output channels, types are : Single channel, Quadrature Rotary encoder.

Single Channel: This only gives the number of rotations, and not the direction. (Scalar Quantity :P)

Quadrature Rotary encoder: This uses two channels for output, and hence can provide the direction as well as number of rotations. (Vector Quantity :P)

I am going to discuss Quadrature Incremental Rotary Encoder here. 

Consider the picture above, where alternate black and white sectors are marked, to be sensed by the IR sensor module. Setup the components as shown below.

Setup for rotary encoder
Setup for rotary encoder

Note: Developement board is just for power supply issues. 😀

For the height of the sensors wrt the motor, see picture below:

Sensor height wrt wheel
Sensor height wrt wheel

Working principle ??

First most important thingy here is the use of interrupts by the two sensors. Pins used are 2, 3. Sensors can be connected to pins in any order. 

Second one is the generation of code bit patterns during motion. Careful observations of the diagram below will show you the generation of GRAY bit pattern. 00,01,11,10,…,00,01,11,10…

Code pattern generation

 

 

A and B are the two sensors.

0- black sector

1- white sector

 

 

 

Thanks to “bilder” for the simplest code. I have done little modifications, while the kernel of the code is same.

Firstly, Attaching interrupts to the pins in arduino is so simple.

Secondly we need a volatile variable to keep track of the number of rotations. Volatile variable are free from any optimization performed by the compiler.

Algorithm for tracking:

The encoder has 2 digital pins that are either HIGH (1) or LOW (0). We read them as 00, 01, 10, or 11.

Sequence generated during CW rotation is 00->01->11->10.

Sequence generated during CCW rotation is 10->11->01->00.

So if you have a reading of 01, the next reading can either be 00 or 11 depending on the direction of the wheel. So by adding the previous encoded value to the beginning of the current encoded value we get 1 of 8 possible numbers (0001, 0010, 0100, 0111, 1000, 1011, 1110 & 1101) As for every reading, two cases are there: one for backward other for forward. Hence for 4, we have 8 total combinations possible. 

1101, 0100, 0010 & 1011 all mean CW movement.

1110, 0111, 0001 & 1000 are all CCW movement.

This can be coded as:

if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++; //clockwise movement
if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --; //counter-clockwise movement

 

Complete code is to be run in arduino is as follows:

 

int encoderPin1 = 2;
int encoderPin2 = 3;

volatile int lastEncoded = 0;
volatile long encoderValue = 0;

long lastencoderValue = 0;

int lastMSB = 0;
int lastLSB = 0;

void setup() {
Serial.begin (9600);

pinMode(encoderPin1, INPUT);
pinMode(encoderPin2, INPUT);

digitalWrite(encoderPin1, HIGH); //turn pullup resistor on
digitalWrite(encoderPin2, HIGH); //turn pullup resistor on

//call updateEncoder() when any high/low changed seen
//on interrupt 0 (pin 2), or interrupt 1 (pin 3)
attachInterrupt(0, updateEncoder, CHANGE);
attachInterrupt(1, updateEncoder, CHANGE);

}

void loop(){

}
void updateEncoder(){
int MSB = digitalRead(encoderPin1); //MSB = most significant bit
int LSB = digitalRead(encoderPin2); //LSB = least significant bit

int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
int sum = (lastEncoded << 2) | encoded; //adding it to the previous encoded value

if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++;
if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue –;

lastEncoded = encoded; //store this value for next time

Serial.println(encoderValue);// this will print the encoder value every time interrupt calls.
}

Here is the video link of the model working…

http://youtu.be/F4QHuH_EZg8

Leave a Reply

Your email address will not be published. Required fields are marked *