Skip to content

Commit abed986

Browse files
committed
Support multiple non-blocking commands simultaneously
1 parent 48b6017 commit abed986

File tree

3 files changed

+42
-8
lines changed

3 files changed

+42
-8
lines changed

buildhat/motors.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ def run_for_degrees(self, degrees, speed=None, blocking=True):
230230
if not (speed >= -100 and speed <= 100):
231231
raise MotorError("Invalid Speed")
232232
if not blocking:
233-
Device._instance.mqueue.put((self._run_for_degrees, (degrees, speed)))
233+
self._queue((self._run_for_degrees, (degrees, speed)))
234234
else:
235235
self._run_for_degrees(degrees, speed)
236236

@@ -251,7 +251,7 @@ def run_to_position(self, degrees, speed=None, blocking=True, direction="shortes
251251
if degrees < -180 or degrees > 180:
252252
raise MotorError("Invalid angle")
253253
if not blocking:
254-
Device._instance.mqueue.put((self._run_to_position, (degrees, speed, direction)))
254+
self._queue((self._run_to_position, (degrees, speed, direction)))
255255
else:
256256
self._run_to_position(degrees, speed, direction)
257257

@@ -282,7 +282,7 @@ def run_for_seconds(self, seconds, speed=None, blocking=True):
282282
if not (speed >= -100 and speed <= 100):
283283
raise MotorError("Invalid Speed")
284284
if not blocking:
285-
Device._instance.mqueue.put((self._run_for_seconds, (seconds, speed)))
285+
self._queue((self._run_for_seconds, (seconds, speed)))
286286
else:
287287
self._run_for_seconds(seconds, speed)
288288

@@ -441,6 +441,9 @@ def release(self, value):
441441
raise MotorError("Must pass boolean")
442442
self._release = value
443443

444+
def _queue(self, cmd):
445+
Device._instance.motorqueue[self.port].put(cmd)
446+
444447

445448
class MotorPair:
446449
"""Pair of motors

buildhat/serinterface.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ def __init__(self, firmware, signature, version, device="/dev/serial0", debug=Fa
8888
self.pulsecond = []
8989
self.rampcond = []
9090
self.vincond = []
91+
self.motorqueue = []
9192
self.fin = False
9293
self.running = True
9394
if debug:
@@ -100,6 +101,7 @@ def __init__(self, firmware, signature, version, device="/dev/serial0", debug=Fa
100101
self.portcond.append([])
101102
self.pulsecond.append([])
102103
self.rampcond.append([])
104+
self.motorqueue.append(queue.Queue())
103105

104106
self.ser = serial.Serial(device, 115200, timeout=5)
105107
# Check if we're in the bootloader or the firmware
@@ -149,10 +151,10 @@ def __init__(self, firmware, signature, version, device="/dev/serial0", debug=Fa
149151
self.cb.daemon = True
150152
self.cb.start()
151153

152-
self.mqueue = queue.Queue()
153-
self.ml = threading.Thread(target=self.motorloop, args=(self.mqueue,))
154-
self.ml.daemon = True
155-
self.ml.start()
154+
for q in self.motorqueue:
155+
ml = threading.Thread(target=self.motorloop, args=(q,))
156+
ml.daemon = True
157+
ml.start()
156158

157159
# Drop timeout value to 1s
158160
listevt = threading.Event()
@@ -270,7 +272,8 @@ def shutdown(self):
270272
self.running = False
271273
self.th.join()
272274
self.cbqueue.put(())
273-
self.mqueue.put((None, None))
275+
for q in self.motorqueue:
276+
q.put((None, None))
274277
self.cb.join()
275278
turnoff = ""
276279
for p in range(4):

test/motors.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,34 @@ def test_nonblocking(self):
3939
diff = abs((last - pos1 + 180) % 360 - 180)
4040
self.assertLess(diff, 10)
4141

42+
def test_nonblocking_multiple(self):
43+
"""Test motor nonblocking mode"""
44+
m1 = Motor('A')
45+
m2 = Motor('B')
46+
last = 0
47+
for delay in [1, 0]:
48+
for _ in range(3):
49+
m1.run_to_position(90, blocking=False)
50+
m2.run_to_position(90, blocking=False)
51+
time.sleep(delay)
52+
m1.run_to_position(90, blocking=False)
53+
m2.run_to_position(90, blocking=False)
54+
time.sleep(delay)
55+
m1.run_to_position(90, blocking=False)
56+
m2.run_to_position(90, blocking=False)
57+
time.sleep(delay)
58+
m1.run_to_position(last, blocking=False)
59+
m2.run_to_position(last, blocking=False)
60+
time.sleep(delay)
61+
# Wait for a bit, before reading last position
62+
time.sleep(7)
63+
pos1 = m1.get_aposition()
64+
diff = abs((last - pos1 + 180) % 360 - 180)
65+
self.assertLess(diff, 10)
66+
pos2 = m2.get_aposition()
67+
diff = abs((last - pos2 + 180) % 360 - 180)
68+
self.assertLess(diff, 10)
69+
4270
def test_position(self):
4371
"""Test motor goes to desired position"""
4472
m = Motor('A')

0 commit comments

Comments
 (0)