From 4f44ffe177d306b3a42850474a34caafbe065f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Van=C4=9Bk?= <linuxtardis@gmail.com> Date: Fri, 30 Jun 2023 08:02:23 +0200 Subject: [PATCH] motor model experiments (current estimation) --- programs/examples/ev3/motor_ident.py | 45 +++++++++++++++++++++++ programs/hbridge_test.py | 54 +++++++++++++++++++++++----- 2 files changed, 91 insertions(+), 8 deletions(-) create mode 100644 programs/examples/ev3/motor_ident.py diff --git a/programs/examples/ev3/motor_ident.py b/programs/examples/ev3/motor_ident.py new file mode 100644 index 0000000..8ae6b36 --- /dev/null +++ b/programs/examples/ev3/motor_ident.py @@ -0,0 +1,45 @@ +import machine +import uarray +import utime + +import lib.hw_defs.pins +from lib.ev3 import Motor +from lib.robot_consts import Port + + +def main(): + global robot + robot.battery.deinit() + adc = machine.ADC(machine.Pin(lib.hw_defs.pins.VBATT_ADC_PIN)) + m = Motor(Port.M1) + samples = 2048 + time = uarray.array('L', [0] * samples) + pos = uarray.array('l', [0] * samples) + power = uarray.array('b', [0]*samples) + vbatt = uarray.array('H', [0]*samples) + + tstart = utime.ticks_us() + tnext = utime.ticks_add(tstart, 1000) + idx = 0 + while idx < samples: + if idx == 48: + m.dc(100) + + time[idx] = utime.ticks_diff(utime.ticks_us(), tstart) + pos[idx] = m.angle() + power[idx] = m.power() + vbatt[idx] = adc.read_u16() + idx += 1 + + tremain = utime.ticks_diff(tnext, utime.ticks_us()) + tnext = utime.ticks_add(tnext, 1000) + if tremain > 0: + utime.sleep_us(tremain) + + print("================") + print("time,pos,power,vbatt") + for i in range(0, idx): + print(f"{time[i]},{pos[i]},{power[i]},{vbatt[i]}") + print("================") + +main() diff --git a/programs/hbridge_test.py b/programs/hbridge_test.py index b011534..e027a5e 100644 --- a/programs/hbridge_test.py +++ b/programs/hbridge_test.py @@ -1,10 +1,36 @@ -import utime +import math +import machine + +from lib.cube.sh1106 import SH1106_I2C from lib.ev3 import Motor from lib.hw_defs.ports import * -from lib.cube.sh1106 import SH1106_I2C -from lib.robot_consts import Button +from lib.robot_consts import Button + +K_MOTOR = 0.459 * math.pi / 180 +# R_POWERED = 6.148 +# R_SHORTED = 7.0 + +# R_MOTOR = 5.2 # direct measurement (ohmmeter across the motor) +# R_SHORTED = 6.0 # direct measurement (ohmmeter in the shorted loop) +I_FULL = 1.21 # measured in-loop +U_BATT_FULL = 7.28 # value on display +U_VM_FULL = 6.20 # measured across the motor pins + +I_SHORTED = 0.35 # measured in the loop +U_SHORTED = 0.212 # measured across the motor when shorted +W_SHORTED = 280 # value on display; very rough estimate + +R_HBRIDGE_SHORTED = U_SHORTED / I_SHORTED +R_MOTOR = U_VM_FULL / I_FULL +R_HBRIDGE_POWERED = (U_BATT_FULL - U_VM_FULL) / I_FULL +R_POWERED = R_HBRIDGE_POWERED + R_MOTOR +R_SHORTED = R_HBRIDGE_SHORTED + R_MOTOR + +# W_FREERUN = 840 +# U_FREERUN = 6.65 +# I_FREERUN = 0 class Hbridge: def __init__(self, port: int): @@ -30,7 +56,7 @@ class Hbridge: if self.is_enabled: self.motor.dc(self.power_pct) else: - self.motor.brake() + self.motor.coast() def get_position(self) -> int: return self.motor.angle() @@ -41,6 +67,8 @@ class Hbridge: def main(): global robot + robot.battery.deinit() + vbatt_adc = machine.ADC(machine.Pin(VBATT_ADC_PIN)) display: SH1106_I2C = robot.display ports = [ Hbridge(i) @@ -68,8 +96,18 @@ def main(): current_port_idx = (current_port_idx + 1) % 4 current_port = ports[current_port_idx] - vbatt = robot.battery.voltage() + pmot = current_port.motor.power() + xmot = current_port.get_position() + wmot = current_port.get_speed() + + vbatt = vbatt_adc.read_u16() / 65535 * 3.2 * 4 vbatt_str = f"{vbatt:3.2f}V" + if current_port.is_enabled: + p = pmot / 100 + vemf = K_MOTOR * wmot + imot = (vbatt - vemf) / R_POWERED * p - vemf / R_SHORTED * (1 - p) + else: + imot = 0 display.fill(0) display.text(f"Motor test", 0, 0) @@ -80,10 +118,10 @@ def main(): display.text(f"Port {current_port_idx + 1}:", 0, 0 + TOP_SPACER) display.text(f" hbridge {'ON' if current_port.is_enabled else 'OFF'}", 0, 8 + TOP_SPACER) display.text(f" pwm: {current_port.power_pct:+5d} %", 0, 16 + TOP_SPACER) - display.text(f" pos: {current_port.get_position():+5d} d", 0, 24 + TOP_SPACER) - display.text(f" spd: {current_port.get_speed():+5d} d/s", 0, 32 + TOP_SPACER) + display.text(f" pos: {xmot:+5d} d", 0, 24 + TOP_SPACER) + display.text(f" spd: {wmot:+5d} d/s", 0, 32 + TOP_SPACER) + display.text(f" cur: {imot:+5.2f} A", 0, 40 + TOP_SPACER) display.show() - utime.sleep_ms(100) main() -- GitLab