Skip to content

Commit a4edde7

Browse files
authored
Only reset port settings for motor on first start() (#125)
* Only reset port settings for motor on first start() Don't allow the motor to start() if some other type of movement is currently running. Additionally, remember what the current speed of a started motor is in order to not allow a serial command to be sent that effectively does nothing. * Switch to enums because minimum python version is 3.7
1 parent 51654fc commit a4edde7

File tree

1 file changed

+42
-1
lines changed

1 file changed

+42
-1
lines changed

buildhat/motors.py

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ def __init__(self, port):
1919
self._default_speed = 20
2020
self.plimit(0.7)
2121
self.bias(0.3)
22+
self.current_freerun_speed = 0
2223

2324
def set_default_speed(self, default_speed):
2425
"""Sets the default speed of the motor
@@ -34,18 +35,24 @@ def start(self, speed=None):
3435
3536
:param speed: Speed ranging from -100 to 100
3637
"""
38+
if self.current_freerun_speed == speed:
39+
# Already running at this speed, do nothing
40+
return
41+
3742
if speed is None:
3843
speed = self._default_speed
3944
else:
4045
if not (speed >= -100 and speed <= 100):
4146
raise MotorException("Invalid Speed")
47+
self.current_freerun_speed = speed
4248
cmd = "port {} ; pwm ; set {}\r".format(self.port, speed/100)
4349
self._write(cmd)
4450

4551
def stop(self):
4652
"""Stops motor"""
4753
cmd = "port {} ; off\r".format(self.port)
4854
self._write(cmd)
55+
self.current_freerun_speed = 0
4956

5057
def plimit(self, plimit):
5158
if not (plimit >= 0 and plimit <= 1):
@@ -57,6 +64,13 @@ def bias(self, bias):
5764
raise MotorException("bias should be 0 to 1")
5865
self._write("port {} ; bias {}\r".format(self.port, bias))
5966

67+
68+
class MotorRunmode(Enum):
69+
NONE = 0
70+
FREE = 1
71+
DEGREES = 2
72+
SECONDS = 3
73+
6074
class Motor(Device):
6175
"""Motor device
6276
@@ -67,6 +81,7 @@ class Motor(Device):
6781
def __init__(self, port):
6882
super().__init__(port)
6983
self.default_speed = 20
84+
self.current_freerun_speed = 0
7085
self.mode([(1,0),(2,0),(3,0)])
7186
self.plimit(0.7)
7287
self.bias(0.3)
@@ -75,6 +90,7 @@ def __init__(self, port):
7590
self._cvqueue = Condition()
7691
self.when_rotated = None
7792
self._oldpos = None
93+
self.runmode = MotorRunmode.NONE
7894

7995
def set_default_speed(self, default_speed):
8096
"""Sets the default speed of the motor
@@ -91,6 +107,7 @@ def run_for_rotations(self, rotations, speed=None, blocking=True):
91107
:param rotations: Number of rotations
92108
:param speed: Speed ranging from -100 to 100
93109
"""
110+
self.runmode = MotorRunmode.DEGREES
94111
if speed is None:
95112
self.run_for_degrees(int(rotations * 360), self.default_speed, blocking)
96113
else:
@@ -99,6 +116,7 @@ def run_for_rotations(self, rotations, speed=None, blocking=True):
99116
self.run_for_degrees(int(rotations * 360), speed, blocking)
100117

101118
def _run_for_degrees(self, degrees, speed):
119+
self.runmode = MotorRunmode.DEGREES
102120
mul = 1
103121
if speed < 0:
104122
speed = abs(speed)
@@ -116,8 +134,10 @@ def _run_for_degrees(self, degrees, speed):
116134
if self._release:
117135
time.sleep(0.2)
118136
self.coast()
137+
self.runmode = MotorRunmode.NONE
119138

120139
def _run_to_position(self, degrees, speed, direction):
140+
self.runmode = MotorRunmode.DEGREES
121141
data = self.get()
122142
pos = data[1]
123143
apos = data[2]
@@ -148,6 +168,7 @@ def _run_to_position(self, degrees, speed, direction):
148168
if self._release:
149169
time.sleep(0.2)
150170
self.coast()
171+
self.runmode = MotorRunmode.NONE
151172

152173
def run_for_degrees(self, degrees, speed=None, blocking=True):
153174
"""Runs motor for N degrees
@@ -157,6 +178,7 @@ def run_for_degrees(self, degrees, speed=None, blocking=True):
157178
:param degrees: Number of degrees to rotate
158179
:param speed: Speed ranging from -100 to 100
159180
"""
181+
self.runmode = MotorRunmode.DEGREES
160182
if speed is None:
161183
speed = self.default_speed
162184
if not (speed >= -100 and speed <= 100):
@@ -174,6 +196,7 @@ def run_to_position(self, degrees, speed=None, blocking=True, direction="shortes
174196
:param degrees: Position in degrees
175197
:param speed: Speed ranging from 0 to 100
176198
"""
199+
self.runmode = MotorRunmode.DEGREES
177200
if speed is None:
178201
speed = self.default_speed
179202
if not (speed >= 0 and speed <= 100):
@@ -188,19 +211,22 @@ def run_to_position(self, degrees, speed=None, blocking=True, direction="shortes
188211
self._run_to_position(degrees, speed, direction)
189212

190213
def _run_for_seconds(self, seconds, speed):
214+
self.runmode = MotorRunmode.SECONDS
191215
cmd = "port {} ; combi 0 1 0 2 0 3 0 ; select 0 ; pid {} 0 0 s1 1 0 0.003 0.01 0 100; set pulse {} 0.0 {} 0\r".format(self.port, self.port, speed, seconds);
192216
self._write(cmd);
193217
with self._hat.pulsecond[self.port]:
194218
self._hat.pulsecond[self.port].wait()
195219
if self._release:
196220
self.coast()
221+
self.runmode = MotorRunmode.NONE
197222

198223
def run_for_seconds(self, seconds, speed=None, blocking=True):
199224
"""Runs motor for N seconds
200225
201226
:param seconds: Time in seconds
202227
:param speed: Speed ranging from -100 to 100
203228
"""
229+
self.runmode = MotorRunmode.SECONDS
204230
if speed is None:
205231
speed = self.default_speed
206232
if not (speed >= -100 and speed <= 100):
@@ -217,16 +243,31 @@ def start(self, speed=None):
217243
218244
:param speed: Speed ranging from -100 to 100
219245
"""
246+
if self.runmode == MotorRunmode.FREE:
247+
if self.current_freerun_speed == speed:
248+
# Already running at this speed, do nothing
249+
return
250+
elif self.runmode != MotorRunmode.NONE:
251+
# Motor is running some other mode, wait for it to stop or stop() it yourself
252+
return
253+
220254
if speed is None:
221255
speed = self.default_speed
222256
else:
223257
if not (speed >= -100 and speed <= 100):
224258
raise MotorException("Invalid Speed")
225-
cmd = "port {} ; combi 0 1 0 2 0 3 0 ; select 0 ; pid {} 0 0 s1 1 0 0.003 0.01 0 100; set {}\r".format(self.port, self.port, speed)
259+
cmd = "port {} ; set {}\r".format(self.port, speed)
260+
if self.runmode == MotorRunmode.NONE:
261+
cmd = "port {} ; combi 0 1 0 2 0 3 0 ; select 0 ; pid {} 0 0 s1 1 0 0.003 0.01 0 100; set {}\r".format(self.port, self.port, speed)
262+
self.runmode = MotorRunmode.FREE
263+
self.current_freerun_speed = speed
226264
self._write(cmd)
227265

266+
228267
def stop(self):
229268
"""Stops motor"""
269+
self.runmode = MotorRunmode.NONE
270+
self.current_freerun_speed = 0
230271
self.coast()
231272

232273
def get_position(self):

0 commit comments

Comments
 (0)