Skip to content

Commit 9974e96

Browse files
committed
Modified encoder motors to read both A and B signals (quadrature encoder)
1 parent 94fc8ff commit 9974e96

10 files changed

+128
-123
lines changed

rotary_encoder/rotarydecoder.py

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,74 @@ class RotaryDecoder:
66

77
""" Class to decode mechanical rotary encoder pulses """
88

9-
def __init__(self, pi, encoder_feedback_pin, callback):
9+
def __init__(self, pi, feedback_pin_A, feedback_pin_B, callback):
1010

1111
self._pi = pi
12-
self._encoder_feedback_pin = encoder_feedback_pin # encoder feedback pin
12+
self._feedback_pin_A = feedback_pin_A # encoder feedback pin A
13+
self._feedback_pin_B = feedback_pin_B # encoder feedback pin B
1314
self._callback = callback # callback function on event
14-
self._value = 0 # value of encoder feedback
15+
self._direction = 0 # direction, forward = 1, backward = -1, steady = 0
16+
17+
self._levelA = 0 # value of encoder feedback pin A
18+
self._levelB = 0 # value of encoder feedback pin B
1519

1620
# setting up GPIO
17-
self._pi.set_mode(encoder_feedback_pin, pigpio.INPUT)
18-
self._pi.set_pull_up_down(encoder_feedback_pin, pigpio.PUD_UP)
21+
self._pi.set_mode(feedback_pin_A, pigpio.INPUT)
22+
self._pi.set_mode(feedback_pin_B, pigpio.INPUT)
23+
self._pi.set_pull_up_down(feedback_pin_A, pigpio.PUD_UP)
24+
self._pi.set_pull_up_down(feedback_pin_B, pigpio.PUD_UP)
25+
26+
# callback function on EITHER_EDGE for each pin
27+
self._callback_triggerA = self._pi.callback(feedback_pin_A, pigpio.EITHER_EDGE, self._pulse)
28+
self._callback_triggerB = self._pi.callback(feedback_pin_B, pigpio.EITHER_EDGE, self._pulse)
1929

20-
# callback function on EITHER_EDGE
21-
self._callback_trigger = self._pi.callback(encoder_feedback_pin, pigpio.EITHER_EDGE, self._pulse)
30+
self._lastGpio = None
2231

2332
""" pulse is the callback function on EITHER_EDGE
24-
it returns a 1 if the feedback square wave is on a falling edge
25-
It simply returns a 1 on FALLING EDGE, i've detached this class in order
26-
to make it easier in case of extension with PIN A attached too """
27-
def _pulse(self, pi, level, tick):
28-
self._value = level
33+
We have two feedback input from pin A and B (two train waves)
34+
it returns a 1 if the square waves have A leading B because we're moving forward
35+
It returns a -1 if the square waves have B leading A because we're moving backwards
36+
In either case, A is staggered from B by (+-)pi/2 radiants
37+
38+
+---------+ +---------+ 0
39+
| | | |
40+
A | | | |
41+
| | | |
42+
----+ +---------+ +----------+ 1 # A leading B
43+
+---------+ +---------+ 0 # forward
44+
| | | |
45+
B | | | |
46+
| | | |
47+
+---------+ +---------+ +----- 1
48+
"""
49+
def _pulse(self, gpio, level, tick):
50+
# interrupt comes from pin A
51+
if (gpio == self._feedback_pin_A):
52+
self._levelA = level # set level of squared wave (0, 1) on A
53+
# interrupt comes from pin B
54+
else:
55+
self._levelB = level # set level of squared wave (0, 1) on B
56+
57+
if (gpio != self._lastGpio): # debounce
58+
self._lastGpio = gpio
2959

30-
# RAISING EDGE
31-
if self._value == 1:
32-
self._callback(1)
60+
if (gpio == self._feedback_pin_A and level == 1):
61+
if (self._levelB == 1):
62+
self._callback(1) # A leading B, moving forward
63+
self._direction = 1 # forward
64+
65+
elif (gpio == self._feedback_pin_B and level == 1):
66+
if (self._levelA == 1):
67+
self._callback(-1) # B leading A, moving forward
68+
self._direction = -1 # backwards
3369

3470

3571
def cancel(self):
3672

3773
"""
38-
Cancel the rotary encoder decoder.
74+
Cancel the rotary encoder decoder callbacks.
3975
"""
40-
41-
self._callback_trigger.cancel()
76+
self._callback_triggerA.cancel()
77+
self._callback_triggerB.cancel()
4278

4379

rotary_encoder_tries/rotary_encoder_original.py renamed to rotary_encoder_tests/rotary_encoder_original.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,13 @@ def _pulse(self, gpio, level, tick):
7979
| | | |
8080
B | | | |
8181
| | | |
82-
----+ +---------+ +---------+ 1
82+
----+ +---------+ +----------+ 1
8383
"""
8484

8585
if gpio == self.gpioA:
8686
self.levA = level
8787
else:
88-
self.levB = level;
88+
self.levB = level
8989

9090
if gpio != self.lastGpio: # debounce
9191
self.lastGpio = gpio
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
PIN_ENCODER_LEFT_A = 14
2+
PIN_ENCODER_LEFT_B = 6
3+
PIN_ENCODER_RIGHT_A = 15
4+
PIN_ENCODER_RIGHT_B = 12
5+
6+
from time import sleep
7+
import pigpio
8+
9+
pi = pigpio.pi()
10+
11+
print("connected")
12+
13+
pi.set_mode(PIN_ENCODER_LEFT_A, pigpio.INPUT)
14+
pi.set_mode(PIN_ENCODER_LEFT_B, pigpio.INPUT)
15+
pi.set_mode(PIN_ENCODER_RIGHT_A, pigpio.INPUT)
16+
pi.set_mode(PIN_ENCODER_RIGHT_B, pigpio.INPUT)
17+
18+
pi.set_pull_up_down(PIN_ENCODER_LEFT_A, pigpio.PUD_UP)
19+
pi.set_pull_up_down(PIN_ENCODER_LEFT_B, pigpio.PUD_UP)
20+
pi.set_pull_up_down(PIN_ENCODER_RIGHT_A, pigpio.PUD_UP)
21+
pi.set_pull_up_down(PIN_ENCODER_RIGHT_B, pigpio.PUD_UP)
22+
23+
24+
while(True):
25+
print("LEFT: A: %d, B: %d" % (pi.read(PIN_ENCODER_LEFT_A), pi.read(PIN_ENCODER_LEFT_B)))
26+
print("RIGHT: A: %d, B: %d" % (pi.read(PIN_ENCODER_RIGHT_A), pi.read(PIN_ENCODER_RIGHT_B)))
27+
sleep(.05)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
PIN_ENCODER_LEFT_A = 14
2+
PIN_ENCODER_LEFT_B = 6
3+
PIN_ENCODER_RIGHT_A = 15
4+
PIN_ENCODER_RIGHT_B = 12
5+
6+
7+
if __name__ == "__main__":
8+
9+
import time
10+
import pigpio
11+
12+
from rotarydecoder import RotaryDecoder
13+
14+
pos_left = 0
15+
pos_right = 0
16+
17+
def callback_left(way):
18+
19+
global pos_left
20+
21+
pos_left += way
22+
23+
print("pos_LEFT={}".format(pos_left))
24+
25+
def callback_right(way):
26+
27+
global pos_right
28+
29+
pos_right += way
30+
31+
print("pos_RIGHT={}".format(pos_right))
32+
33+
34+
# pi = pigpio.pi('coderbot.local')
35+
pi = pigpio.pi()
36+
37+
decoder_left = RotaryDecoder(pi, PIN_ENCODER_LEFT_A, PIN_ENCODER_LEFT_B, callback_left)
38+
decoder_right = RotaryDecoder(pi, PIN_ENCODER_RIGHT_A, PIN_ENCODER_RIGHT_B, callback_right)
39+
40+
time.sleep(1000)
41+
42+
decoder_left.cancel()
43+
decoder_right.cancel()
44+
45+
pi.stop()

rotary_encoder_tries/rotary_encoder.py

Lines changed: 0 additions & 42 deletions
This file was deleted.

rotary_encoder_tries/rotary_encoder_raw_test.py

Lines changed: 0 additions & 20 deletions
This file was deleted.

rotary_encoder_tries/rotary_encoder_ticks_test.py

Lines changed: 0 additions & 41 deletions
This file was deleted.

0 commit comments

Comments
 (0)