From 1ac33cf50fb5849187eadff41e2e1c3f28404a16 Mon Sep 17 00:00:00 2001 From: chrisruk Date: Fri, 31 Mar 2023 12:23:56 +0100 Subject: [PATCH] New firmware support (#190) * New firmware * Changes for new PID * Remove bias test, as no longer exists * Update pwm params * Test down to 10ms interval * Lower speed to improve positioning accuracy --- buildhat/data/firmware.bin | Bin 54168 -> 54360 bytes buildhat/data/signature.bin | 2 +- buildhat/data/version | 2 +- buildhat/motors.py | 77 +++++++++++++++++++++++++++++------- test/motors.py | 17 ++------ 5 files changed, 69 insertions(+), 29 deletions(-) diff --git a/buildhat/data/firmware.bin b/buildhat/data/firmware.bin index 3d1cdb279e6e4d1e208fecabdda50aa65ce2e45d..64358ee52512bf324a5201140895c78b0a7f6556 100644 GIT binary patch delta 26705 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 H7mWV{TfuoU delta 26359 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 diff --git a/buildhat/data/signature.bin b/buildhat/data/signature.bin index 364b0d4..27ef00d 100644 --- a/buildhat/data/signature.bin +++ b/buildhat/data/signature.bin @@ -1 +1 @@ -ktCr>_iۼ*c=Y옢3#lw!HwFZ2 y49d鱾o \ No newline at end of file +Q#E]]-.T~駶e[yEV}A5L}A$I!u9Nzw`l@eK;{E \ No newline at end of file diff --git a/buildhat/data/version b/buildhat/data/version index a2e93cb..e9bf96c 100644 --- a/buildhat/data/version +++ b/buildhat/data/version @@ -1 +1 @@ -1670596313 +1674818421 diff --git a/buildhat/motors.py b/buildhat/motors.py index 0027fff..102a159 100644 --- a/buildhat/motors.py +++ b/buildhat/motors.py @@ -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 @@ -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): @@ -118,7 +117,8 @@ 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() @@ -126,6 +126,13 @@ def __init__(self, port): 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 @@ -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) @@ -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) @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 diff --git a/test/motors.py b/test/motors.py index fad9c65..46d01ec 100644 --- a/test/motors.py +++ b/test/motors.py @@ -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): @@ -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): @@ -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') @@ -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') @@ -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