Question 11.7: You want to detect rotation using a rotary encoder....

You want to detect rotation using a rotary encoder.

Step-by-Step
The 'Blue Check Mark' means that this solution was answered by an expert.
Learn more on how do we answer questions.

Use a rotary (quadrature encoder) connected to two GPIO pins, as shown in Figure 11-9.

To make this recipe, you will need:

• Breadboard and jumper wires (see “Prototyping Equipment” on page 380)

• Rotary encoder (quadrature type; see “Miscellaneous” on page 382)

This type of rotary encoder is called a quadrature encoder, and it behaves like a pair of switches. The sequence in which they open and close as the rotary encoder’s shaft is turned determines the direction of rotation.

The rotary encoder shown has the center lead as the common lead and the two leads on either side as A and B. Not all rotary encoders use this layout, so check the pinout on the datasheet for the rotary encoder that you are using. The issue is often confused further because many rotary encoders include a push switch, which will have a separate pair of contacts.

Open an editor (nano or IDLE) and paste in the following code. As with all the program examples in this book, you can also download the program from the Code section of the Raspberry Pi Cookbook website, where it is called rotary_encoder.py.

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
input_A = 18
input_B = 23
GPIO.setup(input_A, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(input_B, GPIO.IN, pull_up_down=GPIO.PUD_UP)

old_a = True
old_b = True
def get_encoder_turn():
# return -1, 0, or +1
global old_a, old_b
result = 0
new_a = GPIO.input(input_A)
new_b = GPIO.input(input_B)
if new_a != old_a or new_b != old_b :
if old_a == 0 and new_a == 1 :
result = (old_b * 2 – 1)
elif old_b == 0 and new_b == 1 :
result = -(old_a * 2 – 1)
old_a, old_b = new_a, new_b
time.sleep(0.001)
return result
x = 0
while True:
change = get_encoder_turn()
if change != 0 :
x = x + change
print(x)

The test program simply counts up as you turn the rotary encoder clockwise and counts down when you rotate it counterclockwise.

pi@raspberrypi ~ $ sudo python rotary_encoder.py
1
2
3
4
5
6
7
8
9
10
9
8
7
6
5
4

Discussion

Figure 11-10 shows the sequence of pulses that you will get from the two contacts, A and B. You can see that the pattern repeats itself after four steps (hence the name quadrature encoder).

When rotating clockwise (left to right in Figure 11-10), the sequence will be:

When rotating in the opposite direction, the sequence of phases will be reversed.

The Python program listed previously implements the algorithm for determining the rotation direction in the function get_encoder_turn. The function will return 0 (if there has been no movement), 1 for a rotation clockwise, or -1 for a rotation counterclockwise. It uses two global variables, old_a and old_b, to store the previous states of the switches A and B; by comparing them with the newly read values, it can determine (using a bit of clever logic) which direction the encoder is turning.

The sleep period of 1 millisecond is to ensure that the next new sample does not occur too soon after the previous sample; otherwise, the transitions can give false readings.

The test program should work reliably no matter how fast you twiddle the knob on the rotary encoder; however, try to avoid doing anything time-consuming in the loop, or you may find that turn steps are missed.

See Also

You can also measure the rotated position of a knob by using a variable resistor with the step response method (Recipe 12.1) or by using an analog-to-digital converter (Recipe 12.4).

Table A-3. Prototyping equipment
Description Suppliers
M-M jumper wires SparkFun: PRT-08431, Adafruit: 759
M-F jumper wires SparkFun: PRT-09140, Adafruit: 825
F-F jumper wires SparkFun: PRT-08430, Adafruit: 794
Half-sized breadboard SparkFun: PRT-09567 Adafruit: 64
Pi Cobbler Adafruit: 1105
Table A-9. Miscellaneous
1200mAh LiPo battery Adafruit: 258
5V relay SparkFun: COM-00100
5V panel meter SparkFun: TOL-10285
Servo motor SparkFun: ROB-09065, Adafruit: 1449
5V 1A power supply Adafruit: 276
Low power 6V DC motor Adafruit: 711
0.1 inch header pins SparkFun: PRT-00116, Adafruit: 392
5 V 5-pin unipolar stepper motor Adafruit: 858
12 V, 4-pin bipolar stepper motor Adafruit: 324
Magician chassis with gearmotors SparkFun: ROB-10825
Tactile push switch SparkFun: COM-00097, Adafruit: 504
Miniature slide switch SparkFun: COM-09609, Adafruit: 805
Rotary encoder Adafruit: 377
4×3 keypad SparkFun: COM-08653
Piezo buzzer SparkFun: COM-07950, Adafruit: 160
Phase A B
1 0 0
2 0 1
3 1 1
4 1 0
Phase A B
4 1 0
3 1 1
2 0 1
1 0 0
11.9
11.10

Related Answered Questions

Question: 11.13

Verified Answer:

Use an RTC (real-time clock) module. A very common...
Question: 11.8

Verified Answer:

Keypads are arranged in rows and columns, with a p...
Question: 11.2

Verified Answer:

Record the last state of the button and invert tha...
Question: 11.1

Verified Answer:

Connect a switch to a GPIO pin and use the RPi.GPI...
Question: 11.9

Verified Answer:

Use a PIR (passive infrared) motion detector modul...
Question: 11.12

Verified Answer:

The solution to this is very similar to that of us...
Question: 11.11

Verified Answer:

There are at least two ways to solve this problem....
Question: 11.10

Verified Answer:

A 3.3V serial GPS module can be connected directly...