Skip to content

Commit 4aa21e0

Browse files
committed
Refactoring of encoder motors, new test case
1 parent 8034440 commit 4aa21e0

File tree

4 files changed

+252
-117
lines changed

4 files changed

+252
-117
lines changed

coderbot.py

Lines changed: 103 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -257,109 +257,109 @@ def _cb_button(self, gpio, level, tick):
257257
cb()
258258

259259
class MotorEncoder(object):
260-
def __init__(self, parent, _pigpio, pin_enable, pin_forward, pin_backward, pin_encoder):
261-
self._parent = parent
262-
self._pigpio = _pigpio
263-
self._pin_enable = pin_enable
264-
self._pin_forward = pin_forward
265-
self._pin_backward = pin_backward
266-
self._pin_encoder = pin_encoder
267-
self._direction = False
268-
self._pin_duty = 0
269-
self._pin_reverse = 0
270-
self._power = 0.0
271-
self._power_actual = 0.0
272-
self._encoder_dist = 0
273-
self._encoder_speed = 0.0
274-
self._encoder_last_tick = 0
275-
self._encoder_dist_target = 0
276-
self._encoder_speed_target = 0.0
277-
self._encoder_k_s_1 = 20
278-
self._encoder_k_v_1 = 80
279-
self._motor_stopping = False
280-
self._motor_running = False
281-
self._motor_stop_fast = True
282-
self._pigpio.set_mode(self._pin_encoder, pigpio.INPUT)
283-
self._cb = self._pigpio.callback(self._pin_encoder, pigpio.RISING_EDGE, self._cb_encoder)
284-
self._motor_lock = threading.RLock()
285-
286-
def exit(self):
287-
self._cb.cancel()
288-
289-
def _cb_encoder(self, gpio, level, tick):
290-
self._motor_lock.acquire()
291-
self._encoder_dist += 1
292-
delta_ticks = tick - self._encoder_last_tick if tick > self._encoder_last_tick else tick - self._encoder_last_tick + 4294967295
293-
self._encoder_last_tick = tick
294-
self._encoder_speed = 1000000.0 / delta_ticks #convert speed in steps per second
295-
#print "pin: " + str(self._pin_forward) + " dist: " + str(self._encoder_dist) + " target: " + str(self._encoder_dist_target)
296-
if self._encoder_dist_target >= 0 and self._motor_stop_fast:
297-
#delta_s is the delta (in steps)before the target to reverse the motor in order to arrive at target
298-
delta_s = max(min(self._encoder_speed / self._encoder_k_s_1, 100), 0)
299-
#print "pin: " + str(self._pin_forward) + " dist: " + str(self._encoder_dist) + " target: " + str(self._encoder_dist_target) + " delta_s: " + str(delta_s)
300-
if (self._encoder_dist >= self._encoder_dist_target - delta_s and
301-
not self._motor_stopping and self._motor_running):
302-
self._motor_stopping = True
303-
self._pigpio.write(self._pin_duty, 0)
304-
self._pigpio.set_PWM_dutycycle(self._pin_reverse, self._power)
305-
elif (self._motor_running and
306-
((self._motor_stopping and
307-
self._encoder_speed < self._encoder_k_v_1) or
308-
(self._motor_stopping and
309-
self._encoder_dist >= self._encoder_dist_target))):
310-
self.stop()
311-
logging.info("dist: " + str(self._encoder_dist) + " speed: " + str(self._encoder_speed))
312-
if self._encoder_dist_target >= 0 and not self._motor_stop_fast:
313-
if self._encoder_dist >= self._encoder_dist_target:
314-
self.stop()
315-
self._parent._cb_encoder(self, gpio, level, tick)
316-
self._motor_lock.release()
317-
if not self._motor_running:
318-
self._parent._check_complete()
319-
320-
def control(self, power=100.0, elapse=-1, speed=100.0, steps=-1):
321-
self._motor_lock.acquire()
322-
self._direction = speed > 0
323-
self._encoder_dist_target = steps
324-
self._motor_stopping = False
325-
self._motor_running = True
326-
self._encoder_dist = 0
327-
self._encoder_speed_target = abs(speed)
328-
self._power = abs(power) #TODO: initial power must be a function of desired speed
329-
self._power_actual = abs(power) #TODO: initial power must be a function of desired speed
330-
self._pin_duty = self._pin_forward if self._direction else self._pin_backward
331-
self._pin_reverse = self._pin_backward if self._direction else self._pin_forward
332-
self._pigpio.write(self._pin_reverse, 0)
333-
self._pigpio.set_PWM_dutycycle(self._pin_duty, self._power)
334-
self._pigpio.write(self._pin_enable, True)
335-
self._motor_lock.release()
336-
if elapse > 0:
337-
time.sleep(elapse)
338-
self.stop()
339-
340-
def stop(self):
341-
self._motor_lock.acquire()
342-
self._motor_stopping = False
343-
self._motor_running = False
344-
self._pigpio.write(self._pin_forward, 0)
345-
self._pigpio.write(self._pin_backward, 0)
346-
self._motor_lock.release()
347-
348-
def distance(self):
349-
return self._encoder_dist
350-
351-
def speed(self):
352-
return self._encoder_speed
353-
354-
def stopping(self):
355-
return self._motor_stopping
356-
357-
def running(self):
358-
return self._motor_running
359-
360-
def adjust_power(self, power_delta):
361-
self._power_actual = min(max(self._power + power_delta, 0), 100)
362-
self._pigpio.set_PWM_dutycycle(self._pin_duty, self._power_actual)
260+
# def __init__(self, parent, _pigpio, pin_enable, pin_forward, pin_backward, pin_encoder):
261+
# self._parent = parent
262+
# #self._pigpio = _pigpio
263+
# #self._pin_enable = pin_enable
264+
# #self._pin_forward = pin_forward
265+
# #self._pin_backward = pin_backward
266+
# #self._pin_encoder = pin_encoder
267+
# #self._direction = False
268+
# self._pin_duty = 0
269+
# self._pin_reverse = 0
270+
# self._power = 0.0
271+
# #self._power_actual = 0.0
272+
# #self._encoder_dist = 0
273+
# #self._encoder_speed = 0.0
274+
# self._encoder_last_tick = 0
275+
# self._encoder_dist_target = 0
276+
# self._encoder_speed_target = 0.0
277+
# self._encoder_k_s_1 = 20
278+
# self._encoder_k_v_1 = 80
279+
# self._motor_stopping = False
280+
# self._motor_running = False
281+
# self._motor_stop_fast = True
282+
# #self._pigpio.set_mode(self._pin_encoder, pigpio.INPUT)
283+
# #self._cb = self._pigpio.callback(self._pin_encoder, pigpio.RISING_EDGE, self._cb_encoder)
284+
# #self._motor_lock = threading.RLock()
285+
286+
# def exit(self):
287+
# self._cb.cancel()
288+
289+
def _cb_encoder(self, gpio, level, tick):
290+
self._motor_lock.acquire()
291+
self._encoder_dist += 1
292+
delta_ticks = tick - self._encoder_last_tick if tick > self._encoder_last_tick else tick - self._encoder_last_tick + 4294967295
293+
self._encoder_last_tick = tick
294+
self._encoder_speed = 1000000.0 / delta_ticks #convert speed in steps per second
295+
#print "pin: " + str(self._pin_forward) + " dist: " + str(self._encoder_dist) + " target: " + str(self._encoder_dist_target)
296+
if self._encoder_dist_target >= 0 and self._motor_stop_fast:
297+
#delta_s is the delta (in steps)before the target to reverse the motor in order to arrive at target
298+
delta_s = max(min(self._encoder_speed / self._encoder_k_s_1, 100), 0)
299+
#print "pin: " + str(self._pin_forward) + " dist: " + str(self._encoder_dist) + " target: " + str(self._encoder_dist_target) + " delta_s: " + str(delta_s)
300+
if (self._encoder_dist >= self._encoder_dist_target - delta_s and
301+
not self._motor_stopping and self._motor_running):
302+
self._motor_stopping = True
303+
self._pigpio.write(self._pin_duty, 0)
304+
self._pigpio.set_PWM_dutycycle(self._pin_reverse, self._power)
305+
elif (self._motor_running and
306+
((self._motor_stopping and
307+
self._encoder_speed < self._encoder_k_v_1) or
308+
(self._motor_stopping and
309+
self._encoder_dist >= self._encoder_dist_target))):
310+
self.stop()
311+
logging.info("dist: " + str(self._encoder_dist) + " speed: " + str(self._encoder_speed))
312+
if self._encoder_dist_target >= 0 and not self._motor_stop_fast:
313+
if self._encoder_dist >= self._encoder_dist_target:
314+
self.stop()
315+
self._parent._cb_encoder(self, gpio, level, tick)
316+
self._motor_lock.release()
317+
if not self._motor_running:
318+
self._parent._check_complete()
319+
320+
def control(self, power=100.0, elapse=-1, speed=100.0, steps=-1):
321+
self._motor_lock.acquire()
322+
self._direction = speed > 0
323+
self._encoder_dist_target = steps
324+
self._motor_stopping = False
325+
self._motor_running = True
326+
self._encoder_dist = 0
327+
self._encoder_speed_target = abs(speed)
328+
self._power = abs(power) #TODO: initial power must be a function of desired speed
329+
self._power_actual = abs(power) #TODO: initial power must be a function of desired speed
330+
self._pin_duty = self._pin_forward if self._direction else self._pin_backward
331+
self._pin_reverse = self._pin_backward if self._direction else self._pin_forward
332+
self._pigpio.write(self._pin_reverse, 0)
333+
self._pigpio.set_PWM_dutycycle(self._pin_duty, self._power)
334+
self._pigpio.write(self._pin_enable, True)
335+
self._motor_lock.release()
336+
if elapse > 0:
337+
time.sleep(elapse)
338+
self.stop()
339+
340+
# def stop(self):
341+
# self._motor_lock.acquire()
342+
# self._motor_stopping = False
343+
# self._motor_running = False
344+
# self._pigpio.write(self._pin_forward, 0)
345+
# self._pigpio.write(self._pin_backward, 0)
346+
# self._motor_lock.release()
347+
348+
# def distance(self):
349+
# return self._encoder_dist
350+
351+
# def speed(self):
352+
# return self._encoder_speed
353+
354+
def stopping(self):
355+
return self._motor_stopping
356+
357+
def running(self):
358+
return self._motor_running
359+
360+
def adjust_power(self, power_delta):
361+
self._power_actual = min(max(self._power + power_delta, 0), 100)
362+
self._pigpio.set_PWM_dutycycle(self._pin_duty, self._power_actual)
363363

364364
class TwinMotorsEncoder(object):
365365
def __init__(self, apigpio, pin_enable, pin_forward_left, pin_backward_left, pin_encoder_left, pin_forward_right, pin_backward_right, pin_encoder_right):

rotary_encoder/motorencoder.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import pigpio
2+
import threading
3+
4+
from rotarydecoder import RotaryDecoder
5+
6+
class MotorEncoder:
7+
"""
8+
Class that handles rotary decoder motors modelisation
9+
10+
The support class RotaryDecoder decodes mechanical rotary encoder
11+
pulses. See the file for more.
12+
13+
Every movement method must acquire lock in order not to have
14+
concurrency problems on GPIO READ/WRITE
15+
"""
16+
17+
# default constructor
18+
def __init__(self, pi, enable_pin, forward_pin, backward_pin, encoder_feedback_pin):
19+
# setting pin variables
20+
self._pi = pi
21+
self._enable_pin = enable_pin
22+
self._forward_pin = forward_pin
23+
self._backward_pin = backward_pin
24+
self._encoder_feedback_pin = encoder_feedback_pin
25+
26+
# setting movement variables
27+
self._direction = 0
28+
self._distance = 0
29+
self._ticks = 0
30+
self._PWM_value = 0
31+
self._speed = 0
32+
self._is_moving = False
33+
34+
# other
35+
self._callback = self._pi.callback()
36+
self._motor_lock = threading.RLock()
37+
self._rotary_decoder = RotaryDecoder(pi, encoder_feedback_pin, callback)
38+
39+
40+
# GETTERS
41+
42+
# ticks
43+
def ticks(self):
44+
return self._ticks
45+
46+
# distance
47+
def distance(self):
48+
return self._distance
49+
50+
# direction
51+
def direction(self):
52+
return self._direction
53+
54+
# speed
55+
def speed(self):
56+
return self._speed
57+
58+
# is_moving
59+
def is_moving(self):
60+
return self._is_moving
61+
62+
63+
# MOVEMENT
64+
65+
def control(self, ):
66+
67+
68+
""" The stop function acquires the lock to operate on motor
69+
then writes a 0 on movement pins to stop the motor
70+
and releases the lock afterwards """
71+
def stop(self):
72+
self._motor_lock.acquire()
73+
self._pi.write(self._backward_pin, 0)
74+
self._pi.write(self._forward_pin, 0)
75+
self._is_moving = False
76+
self._motor_lock.release()
77+
78+
# OTHER
79+
80+
# callback cancelling
81+
def cancel_callback(self):
82+
self._rotary_decoder.cancel()
83+

rotary_encoder/rotarydecoder.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/usr/bin/env python
2+
3+
import pigpio
4+
5+
class RotaryDecoder:
6+
7+
""" Class to decode mechanical rotary encoder pulses """
8+
9+
def __init__(self, pi, encoder_feedback_pin, callback):
10+
11+
self.pi = pi
12+
self.encoder_feedback_pin = encoder_feedback_pin # encoder feedback pin
13+
self.callback = callback # callback function on event
14+
self.value = 0 # value of encoder feedback
15+
16+
# 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)
19+
20+
# callback function on EITHER_EDGE
21+
self.callback_trigger = self.pi.callback(encoder_feedback_pin, pigpio.EITHER_EDGE, self._pulse)
22+
23+
# pulse is the callback function on EITHER_EDGE
24+
# it returns a 1 if the feedback square wave is on a falling edge
25+
def _pulse(self, level):
26+
self.levB = level;
27+
28+
if self.levB == 1:
29+
self.callback(1)
30+
31+
32+
def cancel(self):
33+
34+
"""
35+
Cancel the rotary encoder decoder.
36+
"""
37+
38+
self.callback_trigger.cancel()
39+
40+

0 commit comments

Comments
 (0)