pm-kit: fix jog-mode step-rate cap (loop overhead, not the motor)

The ~330 steps/s ceiling was the CircuitPython loop, not the stepper: an analog
read + time.sleep(0.0005) every iteration made each pass ~3ms (1/0.003 ~ 330).
Tighten the jog loop - poll the joystick at ~250Hz off the step hot-path, drop
the per-iteration sleep, refresh the readout ~1/s instead of 3+/s, and raise the
commanded ceiling to ~1600 steps/s - so the peak reflects the motor's real limit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Me Here 2026-06-05 21:51:34 -05:00
parent 36c7406d71
commit 5f9e9dfad7

View file

@ -1157,19 +1157,19 @@ class App:
show_stats(0, 0, 0)
self.display.refresh()
time.sleep(0.1); center = self.jx.value
last = time.monotonic(); lastdir = None
total = 0; win = 0; peak = 0; tsample = time.monotonic()
while True:
total = 0; win = 0; peak = 0; cw = True; dt = 1.0; lastdir = None
now = time.monotonic(); last = now; tsample = now; tjoy = now
while True: # no per-iteration sleep: tight step timing in this mode
now = time.monotonic()
if now - tjoy >= 0.004: # poll the joystick ~250x/s, OFF the step hot-path
tjoy = now
dx = self.jx.value - center; mag = abs(dx)
if mag > JOY_DEADZONE:
cw = dx > 0
frac = (mag - JOY_DEADZONE) / (32768 - JOY_DEADZONE)
if frac > 1.0: frac = 1.0
dt = 0.02 + (0.001 - 0.02) * frac # full push ~1000 steps/s; just past deadzone = slow
if self.pend is not None and self.pend.ok and now - last >= dt:
self.pend.spin(cw); last = now; total += 1; win += 1
if cw != lastdir: # direction changed -> update LED + needle
dt = 0.02 + (0.0006 - 0.02) * frac # commanded up to ~1600 steps/s (find the motor's real wall)
if cw != lastdir: # direction changed -> LED + needle (rare, so refresh here)
lastdir = cw
if cw: self.led.set(0, 150, 0)
else: self.led.set(0, 0, 255)
@ -1179,18 +1179,19 @@ class App:
arm.points = [(PEND_PX - 4, PEND_PY), (PEND_PX + 4, PEND_PY), (bx, by)]
self.display.refresh()
elif lastdir is not None: # back to center -> stop, release, recentre needle
lastdir = None
lastdir = None; dt = 1.0
if self.pend is not None and self.pend.ok: self.pend.release()
self.led.set(0, 0, 0)
bob.x = PEND_PX; bob.y = PEND_PY - PEND_LEN
arm.points = [(PEND_PX - 4, PEND_PY), (PEND_PX + 4, PEND_PY), (PEND_PX, PEND_PY - PEND_LEN)]
self.display.refresh()
if now - tsample >= 0.3: # ~3x/s: commanded-rate window -> readout (peak = motor ceiling)
if lastdir is not None and self.pend is not None and self.pend.ok and now - last >= dt:
self.pend.spin(lastdir); last = now; total += 1; win += 1
if now - tsample >= 1.0: # readout once/s (one tiny refresh, not 3+ hitches/s)
rate = int(win / (now - tsample))
if rate > peak: peak = rate
show_stats(total, rate, peak); win = 0; tsample = now
self.display.refresh()
time.sleep(0.0005)
# ---------- audio + light ----------
def click(self, level):