adding motor test
This commit is contained in:
+76
-2
@@ -4,6 +4,7 @@ motor_test.py - Yahboom 4-ch driver over UART, motors on M3 + M4.
|
|||||||
|
|
||||||
python3 motor_test.py hand # motors stay OFF. Turn wheels by hand, watch the counts.
|
python3 motor_test.py hand # motors stay OFF. Turn wheels by hand, watch the counts.
|
||||||
python3 motor_test.py spin # WHEELS OFF THE GROUND. Low PWM steps, one motor at a time.
|
python3 motor_test.py spin # WHEELS OFF THE GROUND. Low PWM steps, one motor at a time.
|
||||||
|
python3 motor_test.py reverse # WHEELS OFF THE GROUND. Why does the board go silent on reversing?
|
||||||
|
|
||||||
Ctrl-C always stops the motors.
|
Ctrl-C always stops the motors.
|
||||||
"""
|
"""
|
||||||
@@ -89,6 +90,77 @@ def hold(d, ch, value, seconds):
|
|||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
|
||||||
|
def measure(d, ch, p, seconds=1.0):
|
||||||
|
"""Hold PWM p and return (counts/s, encoder messages received)."""
|
||||||
|
t0, n0, _ = d.get(); s0 = time.perf_counter()
|
||||||
|
hold(d, ch, p, seconds)
|
||||||
|
t1, n1, _ = d.get(); s1 = time.perf_counter()
|
||||||
|
return (t1[ch] - t0[ch]) / (s1 - s0), n1 - n0
|
||||||
|
|
||||||
|
|
||||||
|
def ramp(d, ch, start, end, steps=10, dt=0.1):
|
||||||
|
for k in range(1, steps + 1):
|
||||||
|
hold(d, ch, start + (end - start) * k / steps, dt)
|
||||||
|
|
||||||
|
|
||||||
|
def report(label, cps, msgs):
|
||||||
|
print(f"{label:<36} {cps:+8.0f} counts/s {msgs:4d} msgs")
|
||||||
|
return msgs > 0
|
||||||
|
|
||||||
|
|
||||||
|
def diagnose(d, gentle):
|
||||||
|
print("\nEncoder stream STOPPED. Re-sending motor type + upload command...")
|
||||||
|
d.send("$mtype:1#")
|
||||||
|
_, n0, _ = d.get()
|
||||||
|
d.send("$upload:1,0,0#")
|
||||||
|
time.sleep(0.5)
|
||||||
|
_, n1, other = d.get()
|
||||||
|
if n1 > n0:
|
||||||
|
print("-> Stream came back after re-sending the settings: the board rebooted and lost them.")
|
||||||
|
if gentle:
|
||||||
|
print(" It died even on a GENTLE reverse, so negative PWM itself is the trigger, not a current spike.")
|
||||||
|
else:
|
||||||
|
print(" Gentle reverse was fine, only the hard one killed it: power dip (brownout) on the board.")
|
||||||
|
else:
|
||||||
|
print("-> Still silent. The board is hung or stopped transmitting. Power-cycle it.")
|
||||||
|
print(" non-encoder lines from the board:", other if other else "none")
|
||||||
|
|
||||||
|
|
||||||
|
def reverse(d):
|
||||||
|
ch = CHANNELS["M3"]
|
||||||
|
input("Are the wheels OFF the ground? Press Enter to start, Ctrl-C to abort... ")
|
||||||
|
|
||||||
|
print("\nTest A: gentle reverse on M3 (ramp up, ramp to 0, pause, ramp to -800)")
|
||||||
|
ramp(d, ch, 0, 800)
|
||||||
|
ok = report(" +800 (ramped up)", *measure(d, ch, 800))
|
||||||
|
ramp(d, ch, 800, 0); d.stop(); time.sleep(1.0)
|
||||||
|
ramp(d, ch, 0, -800)
|
||||||
|
ok = report(" -800 (ramped, after a full stop)", *measure(d, ch, -800)) and ok
|
||||||
|
ramp(d, ch, -800, 0); d.stop(); time.sleep(1.0)
|
||||||
|
if not ok:
|
||||||
|
diagnose(d, gentle=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
print("\nTest B: hard reverse on M3 (+1200 -> -1200 instantly)")
|
||||||
|
hold(d, ch, 1200, 0.5)
|
||||||
|
report(" +1200", *measure(d, ch, 1200))
|
||||||
|
ok = report(" -1200 (instant reverse)", *measure(d, ch, -1200))
|
||||||
|
d.stop(); time.sleep(1.0)
|
||||||
|
if not ok:
|
||||||
|
diagnose(d, gentle=False)
|
||||||
|
return
|
||||||
|
|
||||||
|
print("\nTest C: hard reverse on M3 (+2500 -> -1600 instantly, same as the spin test)")
|
||||||
|
hold(d, ch, 2500, 0.5)
|
||||||
|
report(" +2500", *measure(d, ch, 2500))
|
||||||
|
ok = report(" -1600 (instant reverse)", *measure(d, ch, -1600))
|
||||||
|
d.stop(); time.sleep(1.0)
|
||||||
|
if not ok:
|
||||||
|
diagnose(d, gentle=False)
|
||||||
|
return
|
||||||
|
print("\nAll three survived - the spin-test failure didn't reproduce.")
|
||||||
|
|
||||||
|
|
||||||
def hand(d):
|
def hand(d):
|
||||||
base, _, _ = d.get()
|
base, _, _ = d.get()
|
||||||
print("Motors are OFF.")
|
print("Motors are OFF.")
|
||||||
@@ -125,7 +197,7 @@ def spin(d):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
if len(sys.argv) != 2 or sys.argv[1] not in ("hand", "spin"):
|
if len(sys.argv) != 2 or sys.argv[1] not in ("hand", "spin", "reverse"):
|
||||||
sys.exit(__doc__)
|
sys.exit(__doc__)
|
||||||
d = Driver()
|
d = Driver()
|
||||||
try:
|
try:
|
||||||
@@ -139,8 +211,10 @@ def main():
|
|||||||
print(f"Driver board is talking ({n} encoder messages so far).\n")
|
print(f"Driver board is talking ({n} encoder messages so far).\n")
|
||||||
if sys.argv[1] == "hand":
|
if sys.argv[1] == "hand":
|
||||||
hand(d)
|
hand(d)
|
||||||
else:
|
elif sys.argv[1] == "spin":
|
||||||
spin(d)
|
spin(d)
|
||||||
|
else:
|
||||||
|
reverse(d)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
pass
|
pass
|
||||||
finally:
|
finally:
|
||||||
|
|||||||
Reference in New Issue
Block a user