-
-
Notifications
You must be signed in to change notification settings - Fork 7
Description
Discussed in https://github.com/orgs/pybricks/discussions/749
Originally posted by BertLindeman October 24, 2022
Not sure if this is a defect or feature or not, so started a discussion about this.
(Very nice that beta.pybricks.com now handles newer firmware again. Happy!)
The download and run button in v3.2.0b4 (Pybricks Beta v2.0.0-beta.6) takes longer to start the circle progress animation..
I often wonder if I really clicked the button.
As an example: it takes about 4 seconds after "click" for the progress circle comes up.
This is a program of just over 400 lines.
Assume this has to do with loading / including other sources.
Remarkable
-
Connected to Robot Inventor hub at beta6 firmware
('primehub', '3.2.0b4', 'v3.2.0b4 on 2022-10-21')the button reacts very slow. -
Connected to Spike Prime at CI firmware 2016
('primehub', '3.2.0b3', 'v3.2.0b3-55-gc126dd6b on 2022-08-26')this behaviour is "normal" and feels snappy.
My testcase for this issue (in no way a good program):
# program structure:
# init program
# set constants
# connect remote
# calibrate gearbox
# calibrate steering
# set mode drive
# run in a loop
# check and process buttons on the remote
# wait a bit
# /BL 2022-10-22 try to add a function to determine
# the correct gearbox motor angles
from pybricks.hubs import ThisHub
from pybricks.parameters import Port, Button, Stop, Color, Direction
from pybricks.pupdevices import Motor, Remote
from pybricks.tools import wait, StopWatch
from pybricks import version
print(version)
# set constants
DEBUG = True # or False
GEARBOX_ROTATE_SPEED = 350 # gearbox motor rotate speed
STEER_ROTATE_SPEED = 200 # steering motor rotate speed
DRIVE_WITH_SPEED = 1000 # Speed in drive mode
# Used for calibration of gearbox motor:
TEST_SPEED = 350 # was 150
TEST_TIME = 3000
# mode names
MODEDICT = {0: "driveSlow", 1: "driveFast", 2: "height", 3: "winch"}
# motor angle per mode
# gearbox angle zero is for the winch
MODEANGLES = {0: 100, 1: 180, 2: 0, 3: 0}
# remote and hub LED color to show the current mode
MODECOLORS = {0: Color.GREEN, 1: Color.YELLOW, 2: Color.MAGENTA, 3: Color.GRAY}
# Motordirection for checking the stall of the gearbox, speed for the drive motors
motor_direction = 1 # Or -1 to turn left or right (flip-flop)
mode = 0 # 0 - drive mode
# . 1 - drive fast
# . 2 - height ajustment mode
# . 3 - winch mode
MAX_MODE = len(MODEDICT) - 1
if DEBUG:
print("MAX_MODE =", MAX_MODE)
for __i in range(len(MODEDICT)):
print("mode:%2d name: %-10s Gearbox angle:%4d" % (__i, MODEDICT[__i], MODEANGLES[__i]))
gearbox_reset_angle = MODEANGLES[mode]
# define StopWatch
watch = StopWatch()
def set_mode(mode_to_set):
global hub, remote, mode, DEBUG, watch
print("in set_mode to set mode\t", mode_to_set)
print("in set_mode to set MODEDICT\t", MODEDICT[mode_to_set])
print("in set_mode to set MODEANGLES\t", MODEANGLES[mode_to_set])
# set gearbox mode:
mode = mode_to_set
# if DEBUG:
print("Gearbox go to", MODEDICT[mode], "mode", MODEANGLES[mode], "now at", gearbox.angle())
watch.reset()
gearbox.run_target(GEARBOX_ROTATE_SPEED, MODEANGLES[mode], wait=True)
print("Gearbox run_target to", MODEDICT[mode], "mode", MODEANGLES[mode], "now at", gearbox.angle(), "in", watch.time())
hub.light.on(MODECOLORS[mode])
print("Go set remote.light.on(", MODECOLORS[mode], ")")
wait(20) # Needed? so remote command does not interfere with print buffer ? ? ?
remote.light.on(MODECOLORS[mode])
wait(10)
print("Have set remote.light.on(", MODECOLORS[mode], ")")
def connect_remote():
global hub, remote, DEBUG
print("Waiting for remote connection to hub:", end=" ")
print('"' + str(hub.system.name()) + '" as a ' + version[0], "\n")
try:
remote = Remote()
except Exception as e:
print("No remote connected\n\t", e)
raise(SystemExit())
print("Connected to remote:", remote.name(), "\n")
def try_motor_move(diff_angle):
global gearbox, TEST_SPEED, TEST_TIME, gearbox_right_angle, motor_direction, DEBUG
duration = -9
# just see if shaking back to zero has any influence:
gearbox.run_target(TEST_SPEED, gearbox_right_angle - 5, wait=False)
wait(10)
gearbox.run_target(TEST_SPEED, 10, wait=False)
wait(10)
gearbox.run_target(TEST_SPEED, 0, wait=False)
wait(10)
gearbox.run_target(TEST_SPEED, diff_angle, wait=False)
wait(10)
gearbox.run_target(TEST_SPEED, diff_angle, wait=False)
wait(10)
gearbox.run_target(TEST_SPEED, diff_angle, wait=True)
wait(10)
# swap the direction
motor_direction = -1 * motor_direction
motorA.run(TEST_SPEED * motor_direction)
motorB.run(TEST_SPEED * motor_direction)
watch.reset()
while (not motorA.stalled()):
duration = watch.time()
if (watch.time() > TEST_TIME):
break
stall_A = motorA.stalled()
stall_B = motorB.stalled()
print("Duration %4d ms gearbox tgt %3d at %3d | A stall %-5s at angle %4d | B stall %-5s at angle %4d" %
(duration, diff_angle, gearbox.angle(), stall_A, motorA.angle(), stall_B, motorB.angle()))
# set drive motors back to zero angle
motorA.run_target(TEST_SPEED, 0, wait=False)
motorB.run_target(TEST_SPEED, 0, wait=False)
wait(100)
motorA.stop()
motorB.stop()
def calibrate_gearbox():
global gearbox, hub, remote, TEST_SPEED, TEST_TIME, gearbox_right_angle, DEBUG
calibrate_gearbox_fixed_angles()
if DEBUG:
print("done calibrate to fixed angles, Going to try the settings\n")
# Try different angles to prevent stall later
mode = 0 # start with mode: driveSlow
set_mode(mode)
# wiggle gearmotor from zero to right_end and back
print("gearmotor from zero to right_end and back - 0")
gearbox.run_target(TEST_SPEED, 0, wait=True)
wait(10)
print("gearmotor from zero to right_end and back - ", gearbox_right_angle)
gearbox.run_target(TEST_SPEED, gearbox_right_angle, wait=True)
wait(10)
print("gearmotor from zero to right_end and back - 0")
gearbox.run_target(TEST_SPEED, 0, wait=True)
wait(1000)
# try the whole gearbox motor range from 50 to gearbox_right_angle in steps of 5
for try_angle in range(50, gearbox_right_angle + 1, 5):
try_motor_move(try_angle)
if gearbox.stalled():
print("wrong()")
else:
print("gearbox.stalled():", gearbox.stalled(), "gearbox.speed():", gearbox.speed())
raise SystemExit()
def calibrate_gearbox_fixed_angles():
global gearbox, gearbox_right_angle, DEBUG
# Find the steering endpoint on the left and right.
left_end = -999
right_end = 999
for _ in range(2):
watch.reset()
left_end = max(left_end,
gearbox.run_until_stalled(0 - GEARBOX_ROTATE_SPEED, duty_limit=30, then=Stop.HOLD))
print("\tgearbox stall - takes", watch.time(), "ms")
gearbox.stop()
print("a left", left_end, " \tnow", gearbox.angle())
gearbox.reset_angle(0)
left_end = gearbox.angle()
print("have reset angle now to", gearbox.angle())
for _ in range(2):
watch.reset()
right_end = min(right_end,
gearbox.run_until_stalled(GEARBOX_ROTATE_SPEED, duty_limit=30, then=Stop.HOLD))
print("\tgearbox stall + takes", watch.time(), "ms")
gearbox.stop()
if DEBUG:
print("b left", left_end, "\tright", right_end, "\tnow", gearbox.angle())
# gearbox_right_end = right_end
gearbox.run_target(GEARBOX_ROTATE_SPEED, 0, wait=True)
print("Gearbox run_target to ZERO, now at", gearbox.angle())
wait(50)
gearbox.run_target(GEARBOX_ROTATE_SPEED, right_end, wait=True)
print("Gearbox run target right_end, now at", gearbox.angle())
wait(50)
gearbox_right_angle = gearbox.angle()
def calibrate_steering():
global steer, steering_range, gearbox_reset_angle, DEBUG
# Find the steering endpoint on the left and right.
# center steer
if DEBUG:
print("Start to center steer\n")
# The run_until_stalled gives us the angle at which it stalled.
# We want to know this value for both endpoints, left and right.
# use duty_limit to be gentle
left_end = steer.run_until_stalled(0 - STEER_ROTATE_SPEED, duty_limit=30)
right_end = steer.run_until_stalled(STEER_ROTATE_SPEED, duty_limit=30)
# We have just moved to the rightmost endstop.
# Now we can set the angle to be half the distance between the two endpoints.
# So the middle corresponds to 0 degrees.
steering_range = int((right_end - left_end) / 2)
steer.reset_angle(steering_range)
steering_range -= 5 # just a bit less to prevent stall
# From now on we can simply run towards zero to reach the middle.
steer.run_target(STEER_ROTATE_SPEED, 0)
wait(100)
print("angle set to ZERO and run_target 0 angle now", steer.angle())
steer.run_target(STEER_ROTATE_SPEED, 0)
print("have set steer in the middle \tnow at", steer.angle())
print("Steering centered\n")
def left_button_plus(steer_angle):
global pressed, mode, remote, DEBUG
global steer, steering_range
steer_angle += steering_range
steer.run_target(STEER_ROTATE_SPEED, steer_angle, wait=True)
# wait until the button has been released:
while Button.LEFT_PLUS in pressed:
pressed = remote.buttons.pressed()
wait(10)
def left_button_minus(steer_angle):
global pressed, mode, remote, DEBUG
global steer, steering_angle
steer_angle -= steering_range
steer.run_target(STEER_ROTATE_SPEED, steer_angle, wait=True)
# wait until the button has been released:
while Button.LEFT_MINUS in pressed:
pressed = remote.buttons.pressed()
wait(10)
def left_button_center(steer_angle): # Set steering to straight =-> 0
global pressed, mode, remote, DEBUG
global steer
steer.run_target(STEER_ROTATE_SPEED, steer_angle, wait=True)
while Button.LEFT in pressed:
pressed = remote.buttons.pressed()
wait(10)
def right_button_plus(drive_speed_to_set):
global pressed, mode, remote, DEBUG
global drive_speed
drive_speed = drive_speed_to_set
drive_speed += DRIVE_WITH_SPEED
print("Drive speed + set at", drive_speed)
while Button.RIGHT_PLUS in pressed:
pressed = remote.buttons.pressed()
wait(10)
def right_button_minus(drive_speed_to_set):
global pressed, mode, remote, DEBUG
global drive_speed # not allowed as both parameter AND global
drive_speed = drive_speed_to_set
drive_speed -= DRIVE_WITH_SPEED
print("Drive speed - set at", drive_speed)
while Button.RIGHT_MINUS in pressed:
pressed = remote.buttons.pressed()
wait(10)
def right_button_center(drive_speed_to_set):
global pressed, mode, remote, DEBUG
global drive_speed
drive_speed = drive_speed_to_set
print("Drive speed 0 set at", drive_speed)
while Button.RIGHT in pressed:
pressed = remote.buttons.pressed()
wait(10)
def center_button():
global pressed, mode, remote, DEBUG
mode_prev = mode
mode += 1
if mode > MAX_MODE:
mode = 0
print("in center_button: new mode from", mode_prev, "to", mode)
set_mode(mode)
wait(10)
while Button.CENTER in pressed:
pressed = remote.buttons.pressed()
wait(10)
# define motors:
motorA = Motor(Port.A, Direction.COUNTERCLOCKWISE)
motorB = Motor(Port.B, Direction.COUNTERCLOCKWISE)
steer = Motor(Port.C)
gearbox = Motor(Port.D)
hub = ThisHub()
connect_remote()
calibrate_gearbox()
calibrate_gearbox_fixed_angles()
calibrate_steering()
# gear_angle = gearbox_reset_angle
motor_speed = 0
# reported = False
try:
print("start")
mode = 0 # start with mode: driveSlow
set_mode(mode)
# just to be sure stop the drive motors
drive_speed = 0
motorA.reset_angle(0)
motorB.reset_angle(0)
motorA.run(drive_speed)
motorB.run(drive_speed)
# main loop
while True:
# Check which button(s) are pressed, if any.
pressed = remote.buttons.pressed()
# we only steer if a steering button on the remote is pressed.
# if no steering button is pressed, we drive straight.
steer_angle = 0
motor_speed = 0
# Steer the front wheels
if Button.LEFT_MINUS in pressed:
left_button_minus(steer_angle)
if DEBUG:
print("After left_button_minus(steer_angle) steer_angle=", steer_angle)
if Button.LEFT_PLUS in pressed:
left_button_plus(steer_angle)
if DEBUG:
print("After left_button_plus(steer_angle) steer_angle=", steer_angle)
if Button.LEFT in pressed:
steer_angle = 0
left_button_center(steer_angle)
if DEBUG:
print("After left_button_center(steer_angle) steer_angle=", steer_angle)
# Choose the current speed based upon the RIGHT remote controls.
if Button.RIGHT_MINUS in pressed:
right_button_minus(drive_speed)
if DEBUG:
print("After right_button_minus(", drive_speed, ") drive_speed=", drive_speed)
if Button.RIGHT_PLUS in pressed:
right_button_plus(drive_speed)
if DEBUG:
print("After right_button_plus(", drive_speed, ") drive_speed=", drive_speed)
if Button.RIGHT in pressed:
right_button_center(0) # stop
if DEBUG:
print("After right_button_center(", drive_speed, ") drive_speed=", drive_speed)
if Button.CENTER in pressed: # The green button on the remote
center_button()
if DEBUG:
print("After center_button() new mode=", mode)
# Apply the selected speed.
speed_to_set = drive_speed
motorA.run(speed_to_set)
motorB.run(speed_to_set)
# Wait just a bit
wait(50)
except Exception as e:
print('Got exception:', e)
# global remote
# global hub
#
# stop the motors
motorA.stop()
motorB.stop()
steer.stop()
gearbox.stop()
# drop connection to the remote
# /BL Rationale:
# Sometimes the program on the hub runs on after "stop" on beta.pybricks.comp
# and only stops if the battery of the remote is pulled out.
del remote
del hub
print("End of exception processing.")
finally:
print("Leaving the program in 'finally'.")
SystemExit()