Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified buildhat/data/firmware.bin
Binary file not shown.
2 changes: 1 addition & 1 deletion buildhat/data/signature.bin
Original file line number Diff line number Diff line change
@@ -1 +1 @@
�kt�Cr�>_iۼ*����c=Y옢3#��lw!H�w�F�Z2y���4���9��d鱾o
Q#�E]��]-.T~�駶�e[yE�V}A5�L��}���A�$I!�u�9Nzw`��l�@eK��;�{E�
2 changes: 1 addition & 1 deletion buildhat/data/version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1670596313
1674818421
77 changes: 63 additions & 14 deletions buildhat/motors.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ def __init__(self, port):
self._default_speed = 20
self._currentspeed = 0
self.plimit(0.7)
self.bias(0.3)

def set_default_speed(self, default_speed):
"""Set the default speed of the motor
Expand Down Expand Up @@ -79,10 +78,10 @@ def bias(self, bias):

:param bias: Value 0 to 1
:raises MotorError: Occurs if invalid bias value passed
"""
if not (bias >= 0 and bias <= 1):
raise MotorError("bias should be 0 to 1")
self._write(f"port {self.port} ; bias {bias}\r")

.. deprecated:: 0.6.0
""" # noqa: RST303
raise MotorError("Bias no longer available")


class MotorRunmode(Enum):
Expand Down Expand Up @@ -118,14 +117,22 @@ def __init__(self, port):
self._combi = "1 0 2 0 3 0"
self._noapos = False
self.plimit(0.7)
self.bias(0.3)
self.pwmparams(0.65, 0.01)
self._rpm = False
self._release = True
self._bqueue = deque(maxlen=5)
self._cvqueue = Condition()
self.when_rotated = None
self._oldpos = None
self._runmode = MotorRunmode.NONE

def set_speed_unit_rpm(self, rpm=False):
"""Set whether to use RPM for speed units or not

:param rpm: Boolean to determine whether to use RPM for units
"""
self._rpm = rpm

def set_default_speed(self, default_speed):
"""Set the default speed of the motor

Expand Down Expand Up @@ -200,11 +207,13 @@ def _run_positional_ramp(self, pos, newpos, speed):
:param newpos: New motor postion in decimal rotations (from preset position)
:param speed: -100 to 100
"""
# Collapse speed range to -5 to 5
speed *= 0.05
if self._rpm:
speed = self._speed_process(speed)
else:
speed *= 0.05 # Collapse speed range to -5 to 5
dur = abs((newpos - pos) / speed)
cmd = (f"port {self.port}; select 0 ; selrate {self._interval}; "
f"pid {self.port} 0 1 s4 0.0027777778 0 5 0 .1 3; "
f"pid {self.port} 0 1 s4 0.0027777778 0 5 0 .1 3 0.01; "
f"set ramp {pos} {newpos} {dur} 0\r")
ftr = Future()
self._hat.rampftr[self.port].append(ftr)
Expand Down Expand Up @@ -258,9 +267,14 @@ def run_to_position(self, degrees, speed=None, blocking=True, direction="shortes
self._run_to_position(degrees, speed, direction)

def _run_for_seconds(self, seconds, speed):
speed = self._speed_process(speed)
self._runmode = MotorRunmode.SECONDS
if self._rpm:
pid = f"pid_diff {self.port} 0 5 s2 0.0027777778 1 0 2.5 0 .4 0.01; "
else:
pid = f"pid {self.port} 0 0 s1 1 0 0.003 0.01 0 100 0.01;"
cmd = (f"port {self.port} ; select 0 ; selrate {self._interval}; "
f"pid {self.port} 0 0 s1 1 0 0.003 0.01 0 100; "
f"{pid}"
f"set pulse {speed} 0.0 {seconds} 0\r")
ftr = Future()
self._hat.pulseftr[self.port].append(ftr)
Expand Down Expand Up @@ -309,10 +323,15 @@ def start(self, speed=None):
else:
if not (speed >= -100 and speed <= 100):
raise MotorError("Invalid Speed")
speed = self._speed_process(speed)
cmd = f"port {self.port} ; set {speed}\r"
if self._runmode == MotorRunmode.NONE:
if self._rpm:
pid = f"pid_diff {self.port} 0 5 s2 0.0027777778 1 0 2.5 0 .4 0.01; "
else:
pid = f"pid {self.port} 0 0 s1 1 0 0.003 0.01 0 100 0.01; "
cmd = (f"port {self.port} ; select 0 ; selrate {self._interval}; "
f"pid {self.port} 0 0 s1 1 0 0.003 0.01 0 100; "
f"{pid}"
f"set {speed}\r")
self._runmode = MotorRunmode.FREE
self._currentspeed = speed
Expand Down Expand Up @@ -401,10 +420,23 @@ def bias(self, bias):

:param bias: Value 0 to 1
:raises MotorError: Occurs if invalid bias value passed

.. deprecated:: 0.6.0
""" # noqa: RST303
raise MotorError("Bias no longer available")

def pwmparams(self, pwmthresh, minpwm):
"""PWM thresholds

:param pwmthresh: Value 0 to 1, threshold below, will switch from fast to slow, PWM
:param minpwm: Value 0 to 1, threshold below which it switches off the drive altogether
:raises MotorError: Occurs if invalid values are passed
"""
if not (bias >= 0 and bias <= 1):
raise MotorError("bias should be 0 to 1")
self._write(f"port {self.port} ; bias {bias}\r")
if not (pwmthresh >= 0 and pwmthresh <= 1):
raise MotorError("pwmthresh should be 0 to 1")
if not (minpwm >= 0 and minpwm <= 1):
raise MotorError("minpwm should be 0 to 1")
self._write(f"port {self.port} ; pwmparams {pwmthresh} {minpwm}\r")

def pwm(self, pwmv):
"""PWM motor
Expand Down Expand Up @@ -453,6 +485,13 @@ def _wait_for_nonblocking(self):
"""Wait for nonblocking commands to finish"""
Device._instance.motorqueue[self.port].join()

def _speed_process(self, speed):
"""Lower speed value"""
if self._rpm:
return speed / 60
else:
return speed


class MotorPair:
"""Pair of motors
Expand All @@ -473,6 +512,7 @@ def __init__(self, leftport, rightport):
self._rightmotor = Motor(rightport)
self.default_speed = 20
self._release = True
self._rpm = False

def set_default_speed(self, default_speed):
"""Set the default speed of the motor
Expand All @@ -481,6 +521,15 @@ def set_default_speed(self, default_speed):
"""
self.default_speed = default_speed

def set_speed_unit_rpm(self, rpm=False):
"""Set whether to use RPM for speed units or not

:param rpm: Boolean to determine whether to use RPM for units
"""
self._rpm = rpm
self._leftmotor.set_speed_unit_rpm(rpm)
self._rightmotor.set_speed_unit_rpm(rpm)

def run_for_rotations(self, rotations, speedl=None, speedr=None):
"""Run pair of motors for N rotations

Expand Down
17 changes: 4 additions & 13 deletions test/motors.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def test_rotations(self):
def test_nonblocking(self):
"""Test motor nonblocking mode"""
m = Motor('A')
m.set_default_speed(10)
last = 0
for delay in [1, 0]:
for _ in range(3):
Expand All @@ -44,7 +45,9 @@ def test_nonblocking(self):
def test_nonblocking_multiple(self):
"""Test motor nonblocking mode"""
m1 = Motor('A')
m1.set_default_speed(10)
m2 = Motor('B')
m2.set_default_speed(10)
last = 0
for delay in [1, 0]:
for _ in range(3):
Expand Down Expand Up @@ -118,13 +121,6 @@ def test_plimit(self):
self.assertRaises(MotorError, m.plimit, -1)
self.assertRaises(MotorError, m.plimit, 2)

def test_bias(self):
"""Test setting motor bias"""
m = Motor('A')
m.bias(0.5)
self.assertRaises(MotorError, m.bias, -1)
self.assertRaises(MotorError, m.bias, 2)

def test_pwm(self):
"""Test PWMing motor"""
m = Motor('A')
Expand Down Expand Up @@ -157,11 +153,6 @@ def handle_motor(speed, pos, apos):
m.run_for_seconds(5)
self.assertGreater(handle_motor.evt, 0.8 * ((1 / ((m.interval) * 1e-3)) * 5))

handle_motor.evt = 0
m.interval = 5
m.run_for_seconds(5)
self.assertGreater(handle_motor.evt, 0.8 * ((1 / ((m.interval) * 1e-3)) * 5))

def test_none_callback(self):
"""Test setting empty callback"""
m = Motor('A')
Expand Down Expand Up @@ -234,7 +225,7 @@ def test_dual_interval(self):
"""Test dual motor interval"""
m1 = Motor('A')
m2 = Motor('B')
for interval in [10, 5]:
for interval in [20, 10]:
m1.interval = interval
m2.interval = interval
count = 1000
Expand Down