Current chapter 11

This commit is contained in:
Danny Staple 2022-09-11 20:26:45 +01:00
parent df1d67e42d
commit 3c47ff9874
10 changed files with 30 additions and 41 deletions

View File

@ -10,9 +10,9 @@ async def motor_speed_loop():
while True: while True:
await asyncio.sleep(Settings.time_interval) await asyncio.sleep(Settings.time_interval)
left_new, right_new = robot.left_encoder.read(), robot.right_encoder.read() left_new, right_new = robot.left_encoder.read(), robot.right_encoder.read()
left_speed = robot.ticks_to_mm(left_new - left_last) / Settings.time_interval left_speed = robot.ticks_to_m * (left_new - left_last) / Settings.time_interval
left_last = left_new left_last = left_new
right_speed = robot.ticks_to_mm(right_new - right_last) / Settings.time_interval right_speed = robot.ticks_to_m * (right_new - right_last) / Settings.time_interval
right_last = right_new right_last = right_new
robot.uart.write(f"{left_speed:.3f},{right_speed:.3f},0\n".encode()) robot.uart.write(f"{left_speed:.3f},{right_speed:.3f},0\n".encode())

View File

@ -13,10 +13,7 @@ wheel_circumference_mm = math.pi * wheel_diameter_mm
gear_ratio = 298 gear_ratio = 298
encoder_poles = 28 encoder_poles = 28
ticks_per_revolution = encoder_poles * gear_ratio ticks_per_revolution = encoder_poles * gear_ratio
ticks_to_mm_const = wheel_circumference_mm / ticks_per_revolution ticks_to_m = (wheel_circumference_mm / ticks_per_revolution) / 1000
def ticks_to_mm(ticks):
return ticks_to_mm_const * ticks
motor_A2 = pwmio.PWMOut(board.GP17, frequency=100) motor_A2 = pwmio.PWMOut(board.GP17, frequency=100)
motor_A1 = pwmio.PWMOut(board.GP16, frequency=100) motor_A1 = pwmio.PWMOut(board.GP16, frequency=100)

View File

@ -26,7 +26,7 @@ class SpeedController:
current_ticks = self.encoder.read() current_ticks = self.encoder.read()
speed_in_ticks = (current_ticks - self.last_ticks) / dt speed_in_ticks = (current_ticks - self.last_ticks) / dt
self.last_ticks = current_ticks self.last_ticks = current_ticks
self.actual_speed = robot.ticks_to_mm(speed_in_ticks) / 1000 self.actual_speed = robot.ticks_to_m * speed_in_ticks
# calculate the error # calculate the error
error = (Settings.speed * Settings.motors_enabled) - self.actual_speed error = (Settings.speed * Settings.motors_enabled) - self.actual_speed
# calculate the control signal # calculate the control signal

View File

@ -13,10 +13,7 @@ wheel_circumference_mm = math.pi * wheel_diameter_mm
gear_ratio = 298 gear_ratio = 298
encoder_poles = 28 encoder_poles = 28
ticks_per_revolution = encoder_poles * gear_ratio ticks_per_revolution = encoder_poles * gear_ratio
ticks_to_mm_const = wheel_circumference_mm / ticks_per_revolution ticks_to_m = (wheel_circumference_mm / ticks_per_revolution) / 1000
def ticks_to_mm(ticks):
return ticks_to_mm_const * ticks
motor_A2 = pwmio.PWMOut(board.GP17, frequency=100) motor_A2 = pwmio.PWMOut(board.GP17, frequency=100)
motor_A1 = pwmio.PWMOut(board.GP16, frequency=100) motor_A1 = pwmio.PWMOut(board.GP16, frequency=100)

View File

@ -8,42 +8,41 @@ class DistanceController:
def __init__(self, encoder, motor_fn): def __init__(self, encoder, motor_fn):
self.encoder = encoder self.encoder = encoder
self.motor_fn = motor_fn self.motor_fn = motor_fn
# accel # self.pid = pid_controller.PIDController(1.9, 0.5, 0.3, d_filter_gain=1)
# self.pid = pid_controller.PIDController(0.00000, 0, 0.00008, d_filter_gain=1) self.pid = pid_controller.PIDController(3.25, 0.5, 0.5, d_filter_gain=1)
self.pid = pid_controller.PIDController(0.00000, 0.0000, 0.00001, d_filter_gain=1) # works well with direct pwm control
# started with p at 0, and started increasing until it started to oscillate
# then reduced.
# started increasing i in 0.1 increments, to take up the steady state error
# once this was gone, there was still an overshoot.
# increase d in 0.1 increments until the overshoot was gone.
self.start_ticks = self.encoder.read() self.start_ticks = self.encoder.read()
self.pwm = 0
self.error = 0 self.error = 0
def update(self, dt, expected, debug=False): def update(self, dt, expected):
actual = self.encoder.read() - self.start_ticks self.actual = self.encoder.read() - self.start_ticks
# calculate the error # calculate the error
self.error = expected - actual self.error = (expected - self.actual) / robot.ticks_per_revolution
# calculate the control signal # calculate the control signal
control_signal = self.pid.calculate(self.error, dt) control_signal = self.pid.calculate(self.error, dt)
print(control_signal)
# self.pwm += control_signal
if debug:
robot.uart.write(f"0, {expected:.2f},{actual:.2f}\n".encode())
# self.motor_fn(self.pwm)
self.motor_fn(control_signal) self.motor_fn(control_signal)
class DistanceTracker: class DistanceTracker:
def __init__(self): def __init__(self):
self.speed = 0.10 self.speed = 0.17
self.time_interval = 0.2 self.time_interval = 0.2
self.reset()
def reset(self):
self.start_time = time.monotonic() self.start_time = time.monotonic()
self.current_position = 0
self.total_distance_in_ticks = 0 self.total_distance_in_ticks = 0
self.total_time = 0.1 self.total_time = 0.1
def set_distance(self, new_distance): def set_distance(self, new_distance):
self.reset() # add the last travelled distance to the current position
self.total_distance_in_ticks = robot.mm_to_ticks(new_distance * 1000) self.current_position += self.total_distance_in_ticks
self.total_time = new_distance / self.speed # calculate the new additional distance
self.total_distance_in_ticks = robot.m_to_ticks * new_distance
self.total_time = max(0.1, abs(new_distance / self.speed))
self.start_time = time.monotonic()
async def loop(self): async def loop(self):
left = DistanceController(robot.left_encoder, robot.set_left) left = DistanceController(robot.left_encoder, robot.set_left)
@ -56,9 +55,10 @@ class DistanceTracker:
last_time = current_time last_time = current_time
elapsed_time = current_time - self.start_time elapsed_time = current_time - self.start_time
time_proportion = min(1, elapsed_time / self.total_time) time_proportion = min(1, elapsed_time / self.total_time)
expected = time_proportion * self.total_distance_in_ticks expected = time_proportion * self.total_distance_in_ticks + self.current_position
left.update(dt, expected, debug=True) left.update(dt, expected)
right.update(dt, expected) right.update(dt, expected)
robot.uart.write(f"0, {expected:.2f},{left.actual:.2f}\n".encode())
distance_tracker = DistanceTracker() distance_tracker = DistanceTracker()

View File

@ -13,13 +13,8 @@ wheel_circumference_mm = math.pi * wheel_diameter_mm
gear_ratio = 298 gear_ratio = 298
encoder_poles = 28 encoder_poles = 28
ticks_per_revolution = encoder_poles * gear_ratio ticks_per_revolution = encoder_poles * gear_ratio
ticks_to_mm_const = wheel_circumference_mm / ticks_per_revolution ticks_to_m = (wheel_circumference_mm / ticks_per_revolution) / 1000
m_to_ticks = 1 / ticks_to_m
def ticks_to_mm(ticks):
return ticks_to_mm_const * ticks
def mm_to_ticks(mm):
return mm / ticks_to_mm_const
motor_A2 = pwmio.PWMOut(board.GP17, frequency=100) motor_A2 = pwmio.PWMOut(board.GP17, frequency=100)