From 748f092795e246d21d3b13941a8db77a7ea8581a Mon Sep 17 00:00:00 2001 From: muehe Date: Fri, 1 May 2026 16:18:23 +0200 Subject: [PATCH] control: properly wait for gantry homing before W api.put('home') returns immediately when queued, not when homing finishes, so the previous polling loop saw cycle=='idle' (homing hadn't started yet) and fired W right away. Now we first wait up to 5s for the cycle to *leave* idle, then up to 2min for it to return, before kicking off the auxcnc W home. --- src/js/control-view.js | 43 ++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/src/js/control-view.js b/src/js/control-view.js index c9b53b8..a418ba6 100644 --- a/src/js/control-view.js +++ b/src/js/control-view.js @@ -258,9 +258,12 @@ module.exports = { // Home every enabled axis (legacy Onefinity "Home All"). Sequence: // 1. Z, X, Y (and A/B/C if enabled) via /api/home on the AVR // 2. W axis via /api/aux/home on the ESP - // The two cycles are dispatched serially: we wait for the main - // homing cycle to drop back to idle before kicking off W so the - // gantry never moves while the W spindle is also homing. + // /api/home returns as soon as the request is queued, not when + // homing completes, so we have to watch state.cycle: + // - first wait for it to *leave* 'idle' (cycle began), + // - then wait for it to come *back* to 'idle' (cycle ended). + // Only then do we fire the W home, so the gantry and the auxcnc + // ESP never move at the same time. home_all: async function () { this.ask_home = false; try { @@ -270,14 +273,34 @@ module.exports = { return; } if (!this.w || !this.w.enabled) return; - // Poll state.cycle until the main homing cycle finishes. The - // homing cycle leaves state.cycle as 'homing' until done, then - // returns to 'idle'. - const start = Date.now(); - while (Date.now() - start < 120000) { - if (this.state && this.state.cycle == "idle") break; - await new Promise(r => setTimeout(r, 200)); + + const wait = (ms) => new Promise(r => setTimeout(r, ms)); + const cycleNow = () => (this.state && this.state.cycle) || "idle"; + + // Phase 1: wait up to 5s for the homing cycle to actually start. + // If the request was rejected upstream (e.g. estopped) cycle + // never leaves idle and we bail rather than home W in isolation. + const startedAt = Date.now(); + while (Date.now() - startedAt < 5000) { + if (cycleNow() != "idle") break; + await wait(100); } + if (cycleNow() == "idle") { + console.warn("home_all: main homing cycle never started; skipping W"); + return; + } + + // Phase 2: wait up to 2 minutes for the gantry to finish. + const settledAt = Date.now(); + while (Date.now() - settledAt < 120000) { + if (cycleNow() == "idle") break; + await wait(200); + } + if (cycleNow() != "idle") { + console.warn("home_all: gantry homing did not complete in time"); + return; + } + api.put("aux/home").catch(function (err) { console.error("W home failed:", err); });