Wire ExternalAxis to send LINE blocks (full S-curve mirror to ESP)

Replaces the legacy 'fixed-rate STEPS' path used in Planner.__encode
with a new ExternalAxis.enqueue_line() that hands the ESP the full
7-segment S-curve parameters of every gplan line block (max_accel,
max_jerk, entry_vel, exit_vel, times[7]).

The ESP's new LINE command (auxcnc commit 8acc6f7) integrates the
same SCurve math the AVR uses, so the W axis now physically moves
in lockstep with whatever the planner thinks A is doing. Result:
DRO stays in sync with the actual stepper, no more multi-second lag
between commanded and observed A position.

enqueue_target_mm is kept as a no-frills STEPS path for jog/move UI
endpoints that don't have planner timing context.

AuxAxis._do_line builds the LINE command with mm/min/min^2/min^3
units (matching gplan's internal unit system) and waits for
[line] done|aborted from the ESP. Limit aborts still flag _homed=False.
This commit is contained in:
2026-05-03 12:29:43 +02:00
parent 53b65dc30e
commit 983e06b53d
3 changed files with 126 additions and 23 deletions

View File

@@ -404,11 +404,10 @@ class Planner():
physically a no-op for the steppers, while keeping the
host-side state coherent.
For mixed XYZ + external moves the AVR runs XYZ at the
gplan-computed rate while the ESP runs the external delta
in parallel. Final positions agree; intermediate ap reports
from the AVR may briefly disagree with state.ap until the
block completes."""
We pass the full S-curve parameters to the ESP so its move
duration matches the AVR's exactly. The ESP runs the same
7-segment jerk-limited trajectory the AVR would have run
if A had been a real motor."""
target = block.get('target') or {}
# Read the external target (case-insensitive) without modifying
# the dict so the AVR still sees A.
@@ -416,7 +415,14 @@ class Planner():
if ext_mm is None:
ext_mm = target.get(ext.axis_letter.upper())
try:
ext.enqueue_target_mm(ext_mm)
ext.enqueue_line(
ext_mm,
block.get('max-accel', 0.0),
block.get('max-jerk', 0.0),
block.get('entry-vel', 0.0),
block.get('exit-vel', 0.0),
block.get('times', [0]*7),
)
except Exception as e:
self.log.error('External axis enqueue failed: %s' % e)
raise