Skip to content

INDX_DOCK_MEASURE: dock X is corrupted by the other axis's homing on CoreXY with sensorless homing #946

Description

@kilene001-bit

INDX support was added in #904. This concerns IndxDockMeasurement.measure()
in klippy/extras/indx/toolboard.py.

Environment

  • Kalico v2026.08.00-1-gae261624f
  • BTT Octopus Pro v1.1 (STM32H723), Voron Trident 350, CoreXY
  • X: physical endstop. Y: sensorless (TMC2240, StallGuard2 via driver_SGT)
  • 6-tool INDX, docks mounted at the front of the machine

Problem

Repeating CALIBRATE_DOCK_X / INDX_DOCK_MEASURE on the same dock, without
moving anything, returned X values scattered over 0.4–1.0 mm:

344.994  345.000  345.195  345.366  345.412  345.591
345.768  345.780  345.865  345.975  345.981  345.999

The INDX docks need roughly 0.2 mm, so this is not usable.

Cause

measure() homes every requested axis first and computes the start position
once, at the end, from the final kinematic state:

kin.home(homing_state)                                   # all requested axes
final_position = toolhead.get_position()
kinematic_position_after = self._get_kinematic_position(kin)
start_position = [final + before - after for ...]

_get_kinematic_position() is derived from stepper.get_mcu_position(), i.e.
commanded steps. Sensorless homing ends by driving the gantry into a hard
stop, so some steps are physically lost. On CoreXY a loss on one motor shifts
X, because X = (a + b) / 2. The Y homing therefore corrupts the measured X.

X_FIRST=1 does not help. It only reorders the homing moves; the single
calculation still happens after every axis has homed.

Suggested fix

Home one axis at a time and settle that axis's start position immediately,
before the next axis moves:

start_position = [0.0, 0.0]
for axis in axes:
    homing_state = Homing(self.printer)
    homing_state.set_axes([axis])
    kin.home(homing_state)
    final_position = toolhead.get_position()
    kinematic_position_after = self._get_kinematic_position(kin)
    start_position[axis] = (
        final_position[axis]
        + kinematic_position_before[axis]
        - kinematic_position_after[axis]
    )

With this change plus X_FIRST=1, the X result is settled while the machine
has only ever homed X against its physical switch.

Result

Same dock, same procedure, after the change:

345.195  345.195  345.195  345.195      (identical to 3 decimals)

Measuring the five other docks gave spreads of 0.02–0.23 mm.

Sanity check: deliberately parking 20–30 mm away from the dock returns
306.963, so the command is reading the real position and not a cached one.

Related, lower priority

On a machine where the toolhead is hand-placed into the dock, the dock-holding
axis cannot be homed first without dragging the tool sideways out of the dock.
A parameter to retreat along +Y under motor control before homing would make
X_FIRST=1 usable on such setups — moving the gantry by hand instead does not
work, because it disturbs X. I added a local RETREAT=<mm> for this, but I
suspect you would want to implement it differently: passing
homing_axes=(0, 1) to toolhead.set_position() failed here with
"Must home axis first", so I ended up calling Klipper's own
SET_KINEMATIC_POSITION via run_script_from_command().

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions