Skip to content

Commit a6ac1fb

Browse files
authored
Ensure mixed blocking/nonblocking functions work together (#189)
1 parent 68e5293 commit a6ac1fb

File tree

3 files changed

+24
-0
lines changed

3 files changed

+24
-0
lines changed

buildhat/motors.py

+9
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ def run_for_degrees(self, degrees, speed=None, blocking=True):
232232
if not blocking:
233233
self._queue((self._run_for_degrees, (degrees, speed)))
234234
else:
235+
self._wait_for_nonblocking()
235236
self._run_for_degrees(degrees, speed)
236237

237238
def run_to_position(self, degrees, speed=None, blocking=True, direction="shortest"):
@@ -253,6 +254,7 @@ def run_to_position(self, degrees, speed=None, blocking=True, direction="shortes
253254
if not blocking:
254255
self._queue((self._run_to_position, (degrees, speed, direction)))
255256
else:
257+
self._wait_for_nonblocking()
256258
self._run_to_position(degrees, speed, direction)
257259

258260
def _run_for_seconds(self, seconds, speed):
@@ -284,6 +286,7 @@ def run_for_seconds(self, seconds, speed=None, blocking=True):
284286
if not blocking:
285287
self._queue((self._run_for_seconds, (seconds, speed)))
286288
else:
289+
self._wait_for_nonblocking()
287290
self._run_for_seconds(seconds, speed)
288291

289292
def start(self, speed=None):
@@ -292,6 +295,7 @@ def start(self, speed=None):
292295
:param speed: Speed ranging from -100 to 100
293296
:raises MotorError: Occurs when invalid speed specified
294297
"""
298+
self._wait_for_nonblocking()
295299
if self._runmode == MotorRunmode.FREE:
296300
if self._currentspeed == speed:
297301
# Already running at this speed, do nothing
@@ -316,6 +320,7 @@ def start(self, speed=None):
316320

317321
def stop(self):
318322
"""Stop motor"""
323+
self._wait_for_nonblocking()
319324
self._runmode = MotorRunmode.NONE
320325
self._currentspeed = 0
321326
self.coast()
@@ -444,6 +449,10 @@ def release(self, value):
444449
def _queue(self, cmd):
445450
Device._instance.motorqueue[self.port].put(cmd)
446451

452+
def _wait_for_nonblocking(self):
453+
"""Wait for nonblocking commands to finish"""
454+
Device._instance.motorqueue[self.port].join()
455+
447456

448457
class MotorPair:
449458
"""Pair of motors

buildhat/serinterface.py

+1
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ def motorloop(self, q):
299299
func(*data)
300300
func = None # Necessary for 'del' to function correctly on motor object
301301
data = None
302+
q.task_done()
302303

303304
def callbackloop(self, q):
304305
"""Event handling for callbacks

test/motors.py

+14
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,20 @@ def test_nonblocking_multiple(self):
6969
diff = abs((last - pos2 + 180) % 360 - 180)
7070
self.assertLess(diff, self.THRESHOLD_DISTANCE)
7171

72+
def test_nonblocking_mixed(self):
73+
"""Test motor nonblocking mode mixed with blocking mode"""
74+
m = Motor('A')
75+
m.run_for_seconds(5, blocking=False)
76+
m.run_for_degrees(360)
77+
m.run_for_seconds(5, blocking=False)
78+
m.run_to_position(180)
79+
m.run_for_seconds(5, blocking=False)
80+
m.run_for_seconds(5)
81+
m.run_for_seconds(5, blocking=False)
82+
m.start()
83+
m.run_for_seconds(5, blocking=False)
84+
m.stop()
85+
7286
def test_position(self):
7387
"""Test motor goes to desired position"""
7488
m = Motor('A')

0 commit comments

Comments
 (0)