A rotary encoder has 2 square wave outputs (A and B) which are 90 degrees out of phase with each other. Every time the A signal pulse is on the falling edge, the value of the B pulse is read. From the figure above, when the encoder is turned clockwise, the B pulse is always positive. The B pulse is negative when the encoder is turned counter-clockwise. By connecting both outputs with a microcontroller, it is possible to determine the direction of turn. By counting the number of A pulses, we can determine how far it has turned. The two outputs (A and B) represent the motion of the encoder disc as a quadrature modulated pulse train. By adding a third index signal that pulses once for each revolution, the exact position of the rotor can be known.
Specifications:
The LPD3806 600BM G5 24C Rotary Encoder has the following specifications:
- 600 pulses/revolution for a single phase. Therefore, two-phase output leads to 2400 pulses/revolution
- Maximum mechanical speed: 5000 Revolutions / minute
- Response frequency: 0-20KHz
Connections:
Colour -> Connection
Red -> 5-24V DC
Black -> Ground
Green -> A phase
White -> B phase
The rotary encoder is open collector encoder, so it is necessary to connect pull-up resistors of 10KOhms to the A and B phase outputs, otherwise it will not function properly. Note that A and B phase outputs must not be directly connected with Vcc, otherwise, will burn the output triode. The connection is shown below:
Measuring RPM Using an Encoder
Revolutions Per Minute (RPM), or how fast something turns, can be sensed in a variety of ways. Two of the most common sensors used to determine RPM are optical encoders and Hall effect sensors. These sensors output one or more pulses per revolution (depending on the sensor). There are differences in waveforms for varying RPMs. As RPM increases, the period (T) and pulse width (W) becomes smaller. Both period and pulse width are proportional to RPM. The frequency (or period) of either A or B signal gives the RPM of the joint. Counting the number of pulses gives motor position. A-B phase provides motor direction.
Arduino Code:
The Arduino Code gotten from Arduino Playground is given below. I included a line in the void loop() function to measure the angle of the joint or motor. Since I am using the LPD3806 600BM G5 24C Rotary Encoder, and it produces 2400 pulses for one complete revolution which is 360 degrees, Therefore, the angle is given by:
Note that in the code, the pulses keep counting to 216 = 65536 after which it resets. In order to avoid this, the pulse count needs to be reset to 0 after it gets to 2400. For my application, the joint would not make a complete 360 degrees so there was no need to reset it.
Another important point when installing the encoder is that the direction of positive rotation matters. If the encoder is installed such that its rotation is in the counter clockwise position, the variable encoder0Pos will start from 65536 and start counting down.
#define encoder0PinA 2 #define encoder0PinB 3 volatile unsigned int encoder0Pos = 0; float angle = 0.0; void setup() { pinMode(encoder0PinA, INPUT); pinMode(encoder0PinB, INPUT); void doEncoderA(); void doEncoderB(); // encoder pin on interrupt 0 (pin 2) attachInterrupt(0, doEncoderA, CHANGE); // encoder pin on interrupt 1 (pin 3) attachInterrupt(1, doEncoderB, CHANGE); Serial.begin (9600); } void loop(){ Serial.println (encoder0Pos, DEC); angle = encoder0Pos * (3.0/20.0); Serial.println (angle); } void doEncoderA(){ // look for a low-to-high on channel A if (digitalRead(encoder0PinA) == HIGH) { // check channel B to see which way encoder is turning if (digitalRead(encoder0PinB) == LOW) { encoder0Pos = encoder0Pos + 1; // CW } else { encoder0Pos = encoder0Pos - 1; // CCW } } else // must be a high-to-low edge on channel A { // check channel B to see which way encoder is turning if (digitalRead(encoder0PinB) == HIGH) { encoder0Pos = encoder0Pos + 1; // CW } else { encoder0Pos = encoder0Pos - 1; // CCW } } } void doEncoderB(){ // look for a low-to-high on channel B if (digitalRead(encoder0PinB) == HIGH) { // check channel A to see which way encoder is turning if (digitalRead(encoder0PinA) == HIGH) { encoder0Pos = encoder0Pos + 1; // CW } else { encoder0Pos = encoder0Pos - 1; // CCW } } // Look for a high-to-low on channel B else { // check channel B to see which way encoder is turning if (digitalRead(encoder0PinA) == LOW) { encoder0Pos = encoder0Pos + 1; // CW } else { encoder0Pos = encoder0Pos - 1; // CCW } } }
Thanks for this post. Can you upload an arduino-encoder wiring schematic? Thanks!
ReplyDeletethis model provides 1200 pulses per revolution. not 2400
ReplyDeleteYour encoder shows 5 wires I don't understand how it is to be hooked up. I need to get a pulse like pushing a switch. thanks bob
ReplyDeleteHello Bob, Did you ever figure out how to hook it up?
DeleteI have purchased the same encoder but I need to know if it is waterproof or not. Can you please tell me?
ReplyDeleteI haven't used the encoder in a water-based environment. But I think if used otherwise, the wires should be protected from the water as much as possible
Deletethanks
ReplyDeletea simple code is available at arduino with encoder