Skip to content

Commit 76a7b2d

Browse files
committed
Wheels axel class that handles two motors at once, ended single rotary encoder class
1 parent 39f5b85 commit 76a7b2d

File tree

4 files changed

+132
-57
lines changed

4 files changed

+132
-57
lines changed

coderbot.py

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -365,44 +365,44 @@ def adjust_power(self, power_delta):
365365
class TwinMotorsEncoder(object):
366366
def __init__(self, apigpio, pin_enable, pin_forward_left, pin_backward_left, pin_encoder_left, pin_forward_right, pin_backward_right, pin_encoder_right):
367367
self._straight = False
368-
self._running = False
369-
self._encoder_sem = threading.Condition()
370-
self._motor_left = CoderBot.MotorEncoder(self, apigpio, pin_enable, pin_forward_left, pin_backward_left, pin_encoder_left)
371-
self._motor_right = CoderBot.MotorEncoder(self, apigpio, pin_enable, pin_forward_right, pin_backward_right, pin_encoder_right)
372-
373-
def exit(self):
374-
self._motor_left.exit()
375-
self._motor_right.exit()
376-
377-
def control(self, power_left=100.0, power_right=100.0, elapse=-1, speed_left=-1, speed_right=-1, steps_left=-1, steps_right=-1):
378-
self._straight = power_left == power_right and speed_left == speed_right and steps_left == steps_right
379-
380-
if steps_left >= 0 or steps_right >= 0:
381-
self._encoder_sem.acquire()
382-
383-
self._motor_left.control(power=power_left, elapse=-1, speed=speed_left, steps=steps_left)
384-
self._motor_right.control(power=power_right, elapse=-1, speed=speed_right, steps=steps_right)
385-
self._running = True
386-
387-
if elapse > 0:
388-
time.sleep(elapse)
389-
self.stop()
390-
391-
if steps_left >= 0 or steps_right >= 0:
392-
self._encoder_sem.wait()
393-
self._encoder_sem.release()
394-
self.stop()
395-
396-
def stop(self):
397-
self._motor_left.stop()
398-
self._motor_right.stop()
399-
self._running = False
400-
401-
def distance(self):
402-
return (self._motor_left.distance() + self._motor_right.distance()) / 2
403-
404-
def speed(self):
405-
return (self._motor_left.speed() + self._motor_right.speed()) / 2
368+
#self._running = False
369+
#self._encoder_sem = threading.Condition()
370+
#self._motor_left = CoderBot.MotorEncoder(self, apigpio, pin_enable, pin_forward_left, pin_backward_left, pin_encoder_left)
371+
#self._motor_right = CoderBot.MotorEncoder(self, apigpio, pin_enable, pin_forward_right, pin_backward_right, pin_encoder_right)
372+
373+
#def exit(self):
374+
# self._motor_left.exit()
375+
# self._motor_right.exit()
376+
377+
# def control(self, power_left=100.0, power_right=100.0, elapse=-1, speed_left=-1, speed_right=-1, steps_left=-1, steps_right=-1):
378+
# self._straight = power_left == power_right and speed_left == speed_right and steps_left == steps_right
379+
#
380+
# if steps_left >= 0 or steps_right >= 0:
381+
# self._encoder_sem.acquire()
382+
#
383+
# self._motor_left.control(power=power_left, elapse=-1, speed=speed_left, steps=steps_left)
384+
# self._motor_right.control(power=power_right, elapse=-1, speed=speed_right, steps=steps_right)
385+
# self._running = True
386+
#
387+
# if elapse > 0:
388+
# time.sleep(elapse)
389+
# self.stop()
390+
#
391+
# if steps_left >= 0 or steps_right >= 0:
392+
# self._encoder_sem.wait()
393+
# self._encoder_sem.release()
394+
# self.stop()
395+
396+
#def stop(self):
397+
# self._motor_left.stop()
398+
# self._motor_right.stop()
399+
# self._running = False
400+
401+
#def distance(self):
402+
# return (self._motor_left.distance() + self._motor_right.distance()) / 2
403+
404+
#def speed(self):
405+
# return (self._motor_left.speed() + self._motor_right.speed()) / 2
406406

407407
def _cb_encoder(self, motor, gpio, level, tick):
408408
if (self._straight and self._running and not self._motor_left.stopping() and not self._motor_right.stopping() and

rotary_encoder/motorencoder.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ class MotorEncoder:
1515
concurrency problems on GPIO READ/WRITE """
1616

1717
# default constructor
18-
def __init__(self, pigpio, enable_pin, forward_pin, backward_pin, encoder_feedback_pin):
18+
def __init__(self, pi, enable_pin, forward_pin, backward_pin, encoder_feedback_pin):
1919
# setting pin variables
20-
self._pigpio = pigpio
20+
self._pi = pi
2121
self._enable_pin = enable_pin
2222
self._forward_pin = forward_pin
2323
self._backward_pin = backward_pin
@@ -33,7 +33,7 @@ def __init__(self, pigpio, enable_pin, forward_pin, backward_pin, encoder_feedba
3333

3434
# other
3535
self._motor_lock = threading.RLock()
36-
self._rotary_decoder = RotaryDecoder(pigpio, encoder_feedback_pin, self.rotary_callback)
36+
self._rotary_decoder = RotaryDecoder(pi, encoder_feedback_pin, self.rotary_callback)
3737

3838
# GETTERS
3939
# ticks
@@ -66,16 +66,20 @@ def is_moving(self):
6666

6767
def control(self, power=100.0, time_elapse=0):
6868
self._motor_lock.acquire() # acquiring lock
69+
6970
self._direction = 1 if power > 0 else -1 # setting direction according to speed
7071
self._power = power
7172
self.stop() # stopping motor to initialize new movement
73+
self._pi.write(self._enable_pin, True) # enabling motors
7274

7375
# going forward
7476
if (self._direction):
75-
self._pigpio.set_PWM_dutycycle(self._forward_pin, abs(power))
77+
self._pi.set_PWM_dutycycle(self._forward_pin, abs(power))
78+
self._direction = 1
7679
# going bacakward
7780
else:
78-
self._pigpio.set_PWM_dutycycle(self._backward_pin, abs(power))
81+
self._pi.set_PWM_dutycycle(self._backward_pin, abs(power))
82+
self._direction = -1
7983

8084
self._is_moving = True
8185

@@ -95,8 +99,8 @@ def stop(self):
9599
self._motor_lock.acquire()
96100

97101
# stopping motor
98-
self._pigpio.write(self._backward_pin, 0)
99-
self._pigpio.write(self._forward_pin, 0)
102+
self._pi.write(self._backward_pin, 0)
103+
self._pi.write(self._forward_pin, 0)
100104

101105
# returning state variables to consistent state
102106
self._distance = 0 # resetting distance travelled
@@ -109,7 +113,7 @@ def stop(self):
109113
# releasing lock
110114
self._motor_lock.release()
111115

112-
# CALLBACKS
116+
# CALLBACK
113117
""" The callback function rotary_callback is called on FALLING_EDGE by the
114118
rotary_decoder with a parameter value of 1 (1 new tick)
115119
- Gearbox ratio: 120:1 (1 wheel revolution = 120 motor revolution)
@@ -127,6 +131,7 @@ def rotary_callback(self, tick):
127131
self._ticks += tick # updating ticks
128132
# self._encoder_speed = ? # encoder speed (mm/s)
129133
self._distance = self._ticks * 0.196 # (mm) travelled
134+
self._motor_lock.release()
130135

131136
# callback cancelling
132137
def cancel_callback(self):

rotary_encoder/rotarydecoder.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,30 @@ class RotaryDecoder:
66

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

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

11-
self._pigpio = pigpio
11+
self._pi = pi
1212
self._encoder_feedback_pin = encoder_feedback_pin # encoder feedback pin
1313
self._callback = callback # callback function on event
1414
self._value = 0 # value of encoder feedback
1515

1616
# setting up GPIO
17-
self._pigpio.set_mode(encoder_feedback_pin, pigpio.INPUT)
18-
self._pigpio.set_pull_up_down(encoder_feedback_pin, pigpio.PUD_UP)
17+
self._pi.set_mode(encoder_feedback_pin, pigpio.INPUT)
18+
self._pi.set_pull_up_down(encoder_feedback_pin, pigpio.PUD_UP)
1919

2020
# callback function on EITHER_EDGE
21-
self._callback_trigger = self._pigpio.callback(encoder_feedback_pin, pigpio.EITHER_EDGE, self._pulse)
21+
self._callback_trigger = self._pi.callback(encoder_feedback_pin, pigpio.EITHER_EDGE, self._pulse)
2222

2323
""" pulse is the callback function on EITHER_EDGE
2424
it returns a 1 if the feedback square wave is on a falling edge
2525
It simply returns a 1 on FALLING EDGE, i've detached this class in order
2626
to make it easier in case of extension with PIN A attached too """
27-
def _pulse(self, level):
28-
self.levB = level;
27+
def _pulse(self, pi, level, tick):
28+
self._value = level
2929

3030
# RAISING EDGE
31-
if self.levB == 1:
32-
self.callback(1)
31+
if self._value == 1:
32+
self._callback(1)
3333

3434

3535
def cancel(self):
@@ -38,6 +38,6 @@ def cancel(self):
3838
Cancel the rotary encoder decoder.
3939
"""
4040

41-
self.callback_trigger.cancel()
41+
self._callback_trigger.cancel()
4242

4343

rotary_encoder/wheelsaxel.py

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,77 @@
11
import pigpio
2+
import threading
3+
from time import sleep
24

35
from motorencoder import MotorEncoder
46

57
class WheelsAxel:
6-
pass
8+
""" Class that handles both motor encoders, left and right
79
10+
This class works like a wheels axle, coordinating left and right
11+
wheels at the same time
12+
13+
It also tries to handle the inconsistent tension on wheels
14+
that makes one wheel go slower than the other """
15+
16+
def __init__(self, pi, enable_pin,
17+
left_forward_pin, left_backward_pin, left_encoder_feedback_pin,
18+
right_forward_pin, right_backward_pin, right_encoder_feedback_pin):
19+
20+
# state variables
21+
self._is_moving = False
22+
23+
# left motor
24+
self._left_motor = MotorEncoder(pi,
25+
enable_pin,
26+
left_forward_pin,
27+
left_backward_pin,
28+
left_encoder_feedback_pin)
29+
# right motor
30+
self._right_motor = MotorEncoder(pi,
31+
enable_pin,
32+
right_forward_pin,
33+
right_backward_pin,
34+
right_encoder_feedback_pin)
35+
36+
# other
37+
self._wheelsAxle_lock = threading.Condition() # race condition lock
38+
39+
# STATE GETTERS
40+
""" Distance and speed are calculated by a mean of the feedback
41+
from the two motors """
42+
# distance
43+
def distance(self):
44+
l_dist = self._left_motor.distance()
45+
r_dist = self._right_motor.distance()
46+
return (l_dist + r_dist) / 2
47+
48+
#speed
49+
def speed(self):
50+
l_speed = self._left_motor.speed()
51+
r_speed = self._right_motor.speed()
52+
return (l_speed + r_speed) / 2
53+
54+
# MOVEMENT
55+
def control(self, power_left = 100, power_right = 100, time_elapse = 0):
56+
57+
self._left_motor.control(power_left, time_elapse)
58+
self._right_motor.control(power_right, time_elapse)
59+
self._is_moving = True
60+
61+
if(time_elapse > 0):
62+
sleep(time_elapse)
63+
self.stop()
64+
65+
""" The stop function calls the two stop functions of the two
66+
correspondent motors """
67+
def stop(self):
68+
self._left_motor.stop()
69+
self._right_motor.stop()
70+
self._is_moving = False
71+
72+
# CALLBACK
73+
74+
75+
def cancel_callback(self):
76+
self._right_motor.cancel_callback()
77+
self._left_motor.cancel_callback()

0 commit comments

Comments
 (0)