From 39718e646ba521f53abddbd45efb786e0b3bd594 Mon Sep 17 00:00:00 2001 From: RoccoFL <41308012+RoccoFL@users.noreply.github.com> Date: Sun, 26 Apr 2026 11:55:09 -0500 Subject: [PATCH] Add toolprobe_v3 macros for RRF Introduce a complete toolprobe_v3 macro suite for RepRapFirmware: new top-level macros (LocateToolProbe.g, CalibrateActiveTool.g, CalibrateToolRange.g, RefreshProbeZPlane.g), a user-editable UserConfig.g, persistent globals/state files, and a set of helper library macros under _lib/ (BracketAxis, DiscoverProbeZ, EnsureSafeStart, MoveToProbeXY, Probe_IsTriggered, RestoreEndstops, ScanEdgeNative, Status, TouchZNative, UseProbeAsEndstop). The implementation uses native G1 H4 probing, per-axis M574 endstop swapping, validation of span/center repeatability, safety checks (homing, tool selection, probe-trigger sanity), and M118/M118+echo status messages for DWC visibility. Designed to preserve/restore endstops on all exit paths and provide configurable tuning via UserConfig.g. This commit note as well as the code were written heavily with chatgpt and claude code. This works on my jubilee rrf printer, modified with klicky probe. --- RRF Implementation/CalibrateActiveTool.g | 146 ++++++++++++++++ RRF Implementation/CalibrateToolRange.g | 45 +++++ RRF Implementation/LocateToolProbe.g | 118 +++++++++++++ RRF Implementation/RefreshProbeZPlane.g | 55 ++++++ RRF Implementation/UserConfig.g | 164 ++++++++++++++++++ RRF Implementation/_lib/BracketAxis.g | 37 ++++ RRF Implementation/_lib/DiscoverProbeZ.g | 54 ++++++ RRF Implementation/_lib/EnsureSafeStart.g | 14 ++ RRF Implementation/_lib/MoveToProbeXY.g | 28 +++ RRF Implementation/_lib/Probe_IsTriggered.g | 12 ++ RRF Implementation/_lib/RestoreEndstops.g | 8 + RRF Implementation/_lib/ScanEdgeNative.g | 95 +++++++++++ RRF Implementation/_lib/Status.g | 11 ++ RRF Implementation/_lib/TouchZNative.g | 68 ++++++++ RRF Implementation/_lib/UseProbeAsEndstop.g | 39 +++++ RRF Implementation/globals.g | 178 ++++++++++++++++++++ RRF Implementation/state.g | 35 ++++ 17 files changed, 1107 insertions(+) create mode 100644 RRF Implementation/CalibrateActiveTool.g create mode 100644 RRF Implementation/CalibrateToolRange.g create mode 100644 RRF Implementation/LocateToolProbe.g create mode 100644 RRF Implementation/RefreshProbeZPlane.g create mode 100644 RRF Implementation/UserConfig.g create mode 100644 RRF Implementation/_lib/BracketAxis.g create mode 100644 RRF Implementation/_lib/DiscoverProbeZ.g create mode 100644 RRF Implementation/_lib/EnsureSafeStart.g create mode 100644 RRF Implementation/_lib/MoveToProbeXY.g create mode 100644 RRF Implementation/_lib/Probe_IsTriggered.g create mode 100644 RRF Implementation/_lib/RestoreEndstops.g create mode 100644 RRF Implementation/_lib/ScanEdgeNative.g create mode 100644 RRF Implementation/_lib/Status.g create mode 100644 RRF Implementation/_lib/TouchZNative.g create mode 100644 RRF Implementation/_lib/UseProbeAsEndstop.g create mode 100644 RRF Implementation/globals.g create mode 100644 RRF Implementation/state.g diff --git a/RRF Implementation/CalibrateActiveTool.g b/RRF Implementation/CalibrateActiveTool.g new file mode 100644 index 0000000..661907f --- /dev/null +++ b/RRF Implementation/CalibrateActiveTool.g @@ -0,0 +1,146 @@ +; /macros/toolprobe_v3/CalibrateActiveTool.g +; +; Calibrate the currently selected tool's G10 offsets against the located HRP +; tool probe. Uses native G1 H4 throughout. +; +; Preconditions: +; - LocateToolProbe.g has run (tp3_located == true) +; - A tool is selected (state.currentTool != -1) +; +; Result: writes new G10 X/Y/Z offsets for the active tool. +; Endstops are restored on every exit path. + +M98 P"/macros/toolprobe_v3/globals.g" +M98 P"/macros/toolprobe_v3/state.g" + +; Defensive cleanup: in case a previous abort left endstops swapped +M98 P"/macros/toolprobe_v3/_lib/RestoreEndstops.g" + +if !move.axes[0].homed || !move.axes[1].homed || !move.axes[2].homed + abort "CalibrateActiveTool: home all axes first." + +if state.currentTool == -1 + abort "CalibrateActiveTool: select a tool first." + +if !global.tp3_located + abort "CalibrateActiveTool: run LocateToolProbe.g first." + +; Reset babystepping so the staleness check and the calibration both see a +; clean Z reference (and so the per-print Z hand-tuning doesn't bias offsets). +M290 R0 S0 + +M98 P"/macros/toolprobe_v3/_lib/Status.g" S{"toolprobe_v3: calibrating T" ^ state.currentTool} + +; Snapshot current offsets so we apply a CORRECTION (not absolute) +var baseX = tools[state.currentTool].offsets[0] +var baseY = tools[state.currentTool].offsets[1] +var baseZ = tools[state.currentTool].offsets[2] + +; --- Travel near the probe at safe Z --- +; Done BEFORE the staleness check so the Z-frame reading happens at the same +; XY where RefreshProbeZPlane / LocateToolProbe captured it. Otherwise mesh +; height variation between the macro entry XY and the probe XY shows up as a +; false-positive workspace shift. +M98 P"/macros/toolprobe_v3/_lib/MoveToProbeXY.g" + +; --- Staleness check (advisory only) --- +; Approximate workspace Z offset from observable values. Different RRF versions +; report userPosition slightly differently when a tool is selected, so this +; comparison is informational and DOES NOT abort. If you ran autoz/G92 Z/G30 +; since LocateToolProbe and DIDN'T refresh, the calibration will be off by the +; frame delta — the warning below tells you when this is likely. +var currentZFrame = move.axes[2].machinePosition - move.axes[2].userPosition + tools[state.currentTool].offsets[2] +if global.tp3_probeZPlaneFrame > -9998 + if abs(var.currentZFrame - global.tp3_probeZPlaneFrame) > 0.5 + echo "WARNING: workspace Z reference may have shifted since probeZPlane was measured." + echo " Captured frame: " ^ global.tp3_probeZPlaneFrame ^ " Current frame: " ^ var.currentZFrame + echo " If you ran autoz/G92 Z/G30 since LocateToolProbe, T-1 and run RefreshProbeZPlane.g first." + echo " Otherwise this may be benign (RRF version reports userPosition differently with tool active)." + echo " Proceeding with calibration — verify Z offset afterward." + +; --- Discover where the tool tip actually touches the probe --- +; The H4 trigger is physical, so this stops at first contact regardless of how +; far off the existing G10 Z is. Used to set the XY engagement depth so the +; subsequent X/Y scans always engage the dome correctly, even when the tool +; starts well above (or below) the probe due to a rough initial G10 Z. +M98 P"/macros/toolprobe_v3/_lib/Status.g" S"toolprobe_v3: discovering tool tip Z" + +M98 P"/macros/toolprobe_v3/_lib/Probe_IsTriggered.g" +if global.tp3_probeTriggered + M98 P"/macros/toolprobe_v3/_lib/RestoreEndstops.g" + abort "CalibrateActiveTool: probe already triggered at travel Z. Lift tp3_travelZ or check probe." + +M98 P"/macros/toolprobe_v3/_lib/UseProbeAsEndstop.g" A2 + +G91 +G1 H4 Z{-global.tp3_toolDiscoveryPlunge} F{global.tp3_fZFast} +G90 +M400 + +M98 P"/macros/toolprobe_v3/_lib/Probe_IsTriggered.g" +if !global.tp3_probeTriggered + M98 P"/macros/toolprobe_v3/_lib/UseProbeAsEndstop.g" A2 R1 + G1 Z{global.tp3_travelZ} F{global.tp3_fZFast} + echo "CalibrateActiveTool: tool tip plunge of " ^ global.tp3_toolDiscoveryPlunge ^ "mm did not contact probe." + echo "Tool may be much shorter than expected, seed XY may be off, or probe is offline." + echo "Increase tp3_toolDiscoveryPlunge if the tool is very short." + abort "CalibrateActiveTool: tool tip plunge did not contact probe" + +var roughTipZ = move.axes[2].userPosition + +M98 P"/macros/toolprobe_v3/_lib/UseProbeAsEndstop.g" A2 R1 + +; Lift back to safe travel +G1 Z{global.tp3_travelZ} F{global.tp3_fZFast} + +M98 P"/macros/toolprobe_v3/_lib/Status.g" S{"tool tip touched probe at userZ=" ^ var.roughTipZ ^ "; XY engagement Z=" ^ (var.roughTipZ + global.tp3_toolNudgeZOffset)} + +; XY engagement Z relative to the discovered tip touch position. +; toolNudgeZOffset is intentionally shallow (small negative) — tool tips are +; smaller and more fragile than the bare carriage feature used in LocateToolProbe. +var zEngage = var.roughTipZ + global.tp3_toolNudgeZOffset + +; --- Bracket X around expected center --- +M98 P"/macros/toolprobe_v3/_lib/BracketAxis.g" A0 C{global.tp3_probeX} R{global.tp3_edgeStart} Z{var.zEngage} +var cx = global.tp3_lastCenter +var xSpan = global.tp3_lastSpan + +; Move to refined X over expected Y before bracketing Y +G1 Z{global.tp3_travelZ} F{global.tp3_fZFast} +G1 X{var.cx} Y{global.tp3_probeY} F{global.tp3_fXYTravel} + +; --- Bracket Y around expected center --- +M98 P"/macros/toolprobe_v3/_lib/BracketAxis.g" A1 C{global.tp3_probeY} R{global.tp3_edgeStart} Z{var.zEngage} +var cy = global.tp3_lastCenter +var ySpan = global.tp3_lastSpan + +; Span sanity (looser than LocateToolProbe; we already trust the located center) +if abs(var.xSpan - var.ySpan) > global.tp3_spanMatchTol + M98 P"/macros/toolprobe_v3/_lib/RestoreEndstops.g" + abort "CalibrateActiveTool: span asymmetry. X=" ^ var.xSpan ^ " Y=" ^ var.ySpan + +; --- Z touch at refined center --- +G1 Z{global.tp3_travelZ} F{global.tp3_fZFast} +G1 X{var.cx} Y{var.cy} F{global.tp3_fXYTravel} +G1 Z{global.tp3_workcellZ} F{global.tp3_fZFast} + +M98 P"/macros/toolprobe_v3/_lib/TouchZNative.g" +var cz = global.tp3_lastZ + +; --- Apply correction to existing offsets --- +var corrX = global.tp3_probeX - var.cx +var corrY = global.tp3_probeY - var.cy +var corrZ = global.tp3_probeZPlane - var.cz + +var newX = var.baseX + var.corrX +var newY = var.baseY + var.corrY +var newZ = var.baseZ + var.corrZ + +G10 P{state.currentTool} X{var.newX} Y{var.newY} Z{var.newZ} + +; --- Lift, restore, report --- +G1 Z{global.tp3_travelZ} F{global.tp3_fZFast} +M98 P"/macros/toolprobe_v3/_lib/RestoreEndstops.g" + +M98 P"/macros/toolprobe_v3/_lib/Status.g" S{"T" ^ state.currentTool ^ " offsets X=" ^ var.newX ^ " Y=" ^ var.newY ^ " Z=" ^ var.newZ} +M98 P"/macros/toolprobe_v3/_lib/Status.g" S{"T" ^ state.currentTool ^ " delta X=" ^ var.corrX ^ " Y=" ^ var.corrY ^ " Z=" ^ var.corrZ} diff --git a/RRF Implementation/CalibrateToolRange.g b/RRF Implementation/CalibrateToolRange.g new file mode 100644 index 0000000..b4170a6 --- /dev/null +++ b/RRF Implementation/CalibrateToolRange.g @@ -0,0 +1,45 @@ +; /macros/toolprobe_v3/CalibrateToolRange.g +; +; Iterate a range of tools and calibrate each via CalibrateActiveTool.g. +; +; Params: +; start = first tool index (default 0) +; end = last tool index (default 0) +; +; Preconditions: +; - LocateToolProbe.g has run (tp3_located == true) +; +; Endstops are restored after each tool and at the end (and CalibrateActiveTool +; itself restores on every exit, so a failure on one tool does not leave the +; machine in a bad state). + +M98 P"/macros/toolprobe_v3/globals.g" +M98 P"/macros/toolprobe_v3/state.g" +M98 P"/macros/toolprobe_v3/_lib/RestoreEndstops.g" + +if !global.tp3_located + abort "CalibrateToolRange: run LocateToolProbe.g first." + +var start = exists(param.start) ? floor(param.start) : 0 +var end = exists(param.end) ? floor(param.end) : 0 + +if var.start > var.end + abort "CalibrateToolRange: start (" ^ var.start ^ ") > end (" ^ var.end ^ ")" + +M98 P"/macros/toolprobe_v3/_lib/Status.g" S{"toolprobe_v3: calibrating tools T" ^ var.start ^ ".." ^ var.end} + +while var.start <= var.end + if var.start >= #tools + M98 P"/macros/toolprobe_v3/_lib/Status.g" S{"T" ^ var.start ^ " not defined, skipping"} + else + T{var.start} + if state.currentTool != var.start + M98 P"/macros/toolprobe_v3/_lib/Status.g" S{"T" ^ var.start ^ " select failed, skipping"} + else + M98 P"/macros/toolprobe_v3/CalibrateActiveTool.g" + + set var.start = var.start + 1 + +T-1 +M98 P"/macros/toolprobe_v3/_lib/RestoreEndstops.g" +M98 P"/macros/toolprobe_v3/_lib/Status.g" S"toolprobe_v3: tool range calibration complete" diff --git a/RRF Implementation/LocateToolProbe.g b/RRF Implementation/LocateToolProbe.g new file mode 100644 index 0000000..731a79c --- /dev/null +++ b/RRF Implementation/LocateToolProbe.g @@ -0,0 +1,118 @@ +; /macros/toolprobe_v3/LocateToolProbe.g +; +; Locate the fixed (HRP) tool probe XY center and Z plane in the machine frame. +; Uses native G1 H4 probing throughout, with deterministic span / repeatability +; validation borrowed from the v2 design. +; +; Preconditions: +; - All axes homed +; - T-1 (no tool selected) +; +; Result globals (machine frame, T-1): +; global.tp3_probeX, global.tp3_probeY, global.tp3_probeZPlane, global.tp3_located = true +; +; Endstops are restored on every exit path (success or abort). + +M98 P"/macros/toolprobe_v3/globals.g" +M98 P"/macros/toolprobe_v3/state.g" +M98 P"/macros/toolprobe_v3/_lib/EnsureSafeStart.g" + +; Reset babystepping so the captured Z frame is on the unbiased reference +M290 R0 S0 + +M98 P"/macros/toolprobe_v3/_lib/Status.g" S"toolprobe_v3: locating fixed probe" + +; --- Travel to seed XY --- +M98 P"/macros/toolprobe_v3/_lib/MoveToProbeXY.g" + +; --- Discover the probe top via Z plunge --- +M98 P"/macros/toolprobe_v3/_lib/DiscoverProbeZ.g" +; Engage tp3_locateEngagementDepth mm BELOW the discovered touch (carriage +; geometry knob — see UserConfig.g 'CARRIAGE GEOMETRY' section). +var zEngage = global.tp3_discoveredEngageZ - global.tp3_locateEngagementDepth + +; ============================================================================ +; PASS 1: bracket around the seed +; ============================================================================ +M98 P"/macros/toolprobe_v3/_lib/Status.g" S"toolprobe_v3: pass 1 (coarse)" + +M98 P"/macros/toolprobe_v3/_lib/BracketAxis.g" A0 C{global.tp3_probeX} R{global.tp3_edgeStart} Z{var.zEngage} +var cx1 = global.tp3_lastCenter +var xSpan = global.tp3_lastSpan + +; Move to refined X over seed Y before Y bracket +G1 Z{global.tp3_travelZ} F{global.tp3_fZFast} +G1 X{var.cx1} Y{global.tp3_probeY} F{global.tp3_fXYTravel} + +M98 P"/macros/toolprobe_v3/_lib/BracketAxis.g" A1 C{global.tp3_probeY} R{global.tp3_edgeStart} Z{var.zEngage} +var cy1 = global.tp3_lastCenter +var ySpan = global.tp3_lastSpan + +; --- Span validation --- +if var.xSpan < global.tp3_spanMin || var.xSpan > global.tp3_spanMax + M98 P"/macros/toolprobe_v3/_lib/RestoreEndstops.g" + abort "LocateToolProbe: X span out of range: " ^ var.xSpan + +if var.ySpan < global.tp3_spanMin || var.ySpan > global.tp3_spanMax + M98 P"/macros/toolprobe_v3/_lib/RestoreEndstops.g" + abort "LocateToolProbe: Y span out of range: " ^ var.ySpan + +if abs(var.xSpan - var.ySpan) > global.tp3_spanMatchTol + M98 P"/macros/toolprobe_v3/_lib/RestoreEndstops.g" + abort "LocateToolProbe: span asymmetry. X=" ^ var.xSpan ^ " Y=" ^ var.ySpan + +; ============================================================================ +; PASS 2: refine around the discovered center +; ============================================================================ +M98 P"/macros/toolprobe_v3/_lib/Status.g" S"toolprobe_v3: pass 2 (refine)" + +var rx = (var.xSpan / 2) + global.tp3_refineMargin +var ry = (var.ySpan / 2) + global.tp3_refineMargin + +G1 Z{global.tp3_travelZ} F{global.tp3_fZFast} +G1 X{var.cx1} Y{var.cy1} F{global.tp3_fXYTravel} + +M98 P"/macros/toolprobe_v3/_lib/BracketAxis.g" A0 C{var.cx1} R{var.rx} Z{var.zEngage} +var cx2 = global.tp3_lastCenter + +G1 Z{global.tp3_travelZ} F{global.tp3_fZFast} +G1 X{var.cx2} Y{var.cy1} F{global.tp3_fXYTravel} + +M98 P"/macros/toolprobe_v3/_lib/BracketAxis.g" A1 C{var.cy1} R{var.ry} Z{var.zEngage} +var cy2 = global.tp3_lastCenter + +; --- Center repeatability check --- +var dxc = abs(var.cx2 - var.cx1) +var dyc = abs(var.cy2 - var.cy1) +if var.dxc > global.tp3_centerRepeatTol || var.dyc > global.tp3_centerRepeatTol + M98 P"/macros/toolprobe_v3/_lib/RestoreEndstops.g" + abort "LocateToolProbe: center not repeatable. Δx=" ^ var.dxc ^ " Δy=" ^ var.dyc + +; ============================================================================ +; FINAL Z TOUCH at refined center +; ============================================================================ +M98 P"/macros/toolprobe_v3/_lib/Status.g" S"toolprobe_v3: final Z touch" + +G1 Z{global.tp3_travelZ} F{global.tp3_fZFast} +G1 X{var.cx2} Y{var.cy2} F{global.tp3_fXYTravel} +G1 Z{global.tp3_workcellZ} F{global.tp3_fZFast} + +M98 P"/macros/toolprobe_v3/_lib/TouchZNative.g" +var cz = global.tp3_lastZ + +; --- Save located probe --- +; Capture the workspace Z offset that was active when probeZPlane was measured. +; CalibrateActiveTool uses this to detect "autoz happened since locate" and +; demand a RefreshProbeZPlane.g run before producing wrong Z calibrations. +; With T-1 active, workplace Z offset = machinePosition - userPosition. +set global.tp3_probeX = var.cx2 +set global.tp3_probeY = var.cy2 +set global.tp3_probeZPlane = var.cz +set global.tp3_probeZPlaneFrame = move.axes[2].machinePosition - move.axes[2].userPosition +set global.tp3_located = true + +; --- Lift, restore, report --- +G1 Z{global.tp3_travelZ} F{global.tp3_fZFast} +M98 P"/macros/toolprobe_v3/_lib/RestoreEndstops.g" + +M98 P"/macros/toolprobe_v3/_lib/Status.g" S{"toolprobe_v3: located X=" ^ global.tp3_probeX ^ " Y=" ^ global.tp3_probeY ^ " Z=" ^ global.tp3_probeZPlane} diff --git a/RRF Implementation/RefreshProbeZPlane.g b/RRF Implementation/RefreshProbeZPlane.g new file mode 100644 index 0000000..c277b60 --- /dev/null +++ b/RRF Implementation/RefreshProbeZPlane.g @@ -0,0 +1,55 @@ +; /macros/toolprobe_v3/RefreshProbeZPlane.g +; +; Re-measure the located probe's Z plane in the CURRENT user frame. Run this +; after any operation that changes the workplace Z offset (autoz, manual G92 Z, +; G30 to set Z, etc.) so subsequent CalibrateActiveTool runs have a Z reference +; in the new frame. +; +; XY are unaffected by autoz (autoz only does G92 Z), so tp3_probeX/probeY are +; preserved. +; +; Preconditions: +; - All axes homed +; - T-1 (no tool selected) +; - LocateToolProbe.g has been run (tp3_located == true) +; +; Recommended order of operations: +; 1. T-1 +; 2. M98 P"/macros/toolprobe_v3/LocateToolProbe.g" +; 3. (autoz / klicky calibration here) +; 4. T-1 +; 5. M98 P"/macros/toolprobe_v3/RefreshProbeZPlane.g" +; 6. T0 (or any tool) +; 7. M98 P"/macros/toolprobe_v3/CalibrateActiveTool.g" + +M98 P"/macros/toolprobe_v3/globals.g" +M98 P"/macros/toolprobe_v3/state.g" +M98 P"/macros/toolprobe_v3/_lib/EnsureSafeStart.g" + +if !global.tp3_located + abort "RefreshProbeZPlane: run LocateToolProbe.g first." + +; Reset babystepping so the captured Z frame is on the unbiased reference +M290 R0 S0 + +M98 P"/macros/toolprobe_v3/_lib/Status.g" S"toolprobe_v3: refreshing probe Z plane in current user frame" + +; --- Travel to the located XY at safe Z, then drop near probe --- +G90 +G1 Z{global.tp3_travelZ} F{global.tp3_fZFast} +G1 X{global.tp3_probeX} Y{global.tp3_probeY} F{global.tp3_fXYTravel} +G1 Z{global.tp3_workcellZ} F{global.tp3_fZFast} + +; --- Precision Z touch (slow plunge with backoff) --- +M98 P"/macros/toolprobe_v3/_lib/TouchZNative.g" + +; --- Update probeZPlane and the captured workspace frame --- +; With T-1 active, workplace Z offset = machinePosition - userPosition. +set global.tp3_probeZPlane = global.tp3_lastZ +set global.tp3_probeZPlaneFrame = move.axes[2].machinePosition - move.axes[2].userPosition + +; --- Lift, restore, report --- +G1 Z{global.tp3_travelZ} F{global.tp3_fZFast} +M98 P"/macros/toolprobe_v3/_lib/RestoreEndstops.g" + +M98 P"/macros/toolprobe_v3/_lib/Status.g" S{"toolprobe_v3: probeZPlane=" ^ global.tp3_probeZPlane ^ " (workspace Z offset=" ^ global.tp3_probeZPlaneFrame ^ ")"} diff --git a/RRF Implementation/UserConfig.g b/RRF Implementation/UserConfig.g new file mode 100644 index 0000000..7264b9e --- /dev/null +++ b/RRF Implementation/UserConfig.g @@ -0,0 +1,164 @@ +; /macros/toolprobe_v3/UserConfig.g +; +; Operator-editable tuning for toolprobe_v3. +; Edit the values below, then run this file to apply. It updates tunables and +; SEED guesses but never overwrites the located probe XY/Z unless you flip +; the resetEstimateToSeed switch. + +; ============================================================================= +; OPTIONAL: reset runtime estimate to seed +; ============================================================================= +; Set true once when you want LocateToolProbe to start from a fresh seed. +; After a successful run, set back to false. +var resetEstimateToSeed = false + + +; ============================================================================= +; *** CARRIAGE GEOMETRY — read this first *** +; ============================================================================= +; LocateToolProbe (T-1) uses your BARE CARRIAGE to bracket the probe dome. +; After the first downward touch, the carriage drops this many mm further so +; the carriage's contact feature can engage the dome's SIDE for the X/Y scans. +; Pick the value that matches your hardware: +; +; - Nudge / probe peg sticking 5+mm below the carriage: 1.0 - 1.5 +; - Small contact pin (1-2mm below the carriage body): 0.3 - 0.7 +; - Flat carriage bottom, no dedicated probe feature: 0.0 - 0.1 +; +; Symptom -> too large: LocateToolProbe aborts with +; "ScanEdgeNative: probe already triggered at scan start" +; (the carriage is being pushed past where it can physically go). +; Symptom -> too small: LocateToolProbe aborts with +; "probe did not trigger within 12mm scan" +; (the contact feature isn't engaged with the dome's side). +var locateEngagementDepth = 0.5 + +; CalibrateActiveTool engagement (tool tip touches dome's side at this depth) +; Negative = below the discovered tip-touch point. Keep shallow for tool tips. +var toolNudgeZOffset = -0.20 + + +; ============================================================================= +; SEED VALUES (rough estimates, machine frame, T-1) +; ============================================================================= +var seedX = 263.8675 +var seedY = 309.9875 +var seedZGuess = 4.140 +var domeZ = 0.5 + + +; ============================================================================= +; PROBE SELECTION +; ============================================================================= +var probeIndex = 3 +var trigMin = 900 +var trigMax = 1100 + + +; ============================================================================= +; ENDSTOP PINS (must match config.g) +; ============================================================================= +var endstopPinX = "^io2" +var endstopPinY = "^io1" + + +; ============================================================================= +; Z POLICY +; ============================================================================= +var travelZ = 15 +var workcellZ = 8 +var betweenTouchZLift = 0.5 +; locateEngagementDepth and toolNudgeZOffset live in the CARRIAGE GEOMETRY +; section near the top of this file. + + +; ============================================================================= +; XY GEOMETRY / VALIDATION +; ============================================================================= +var edgeStart = 6.0 +var refineMargin = 0.5 + +var spanMin = 1.0 +var spanMax = 12.0 +var spanMatchTol = 1.0 +var centerRepeatTol = 0.05 + + +; ============================================================================= +; Z TOUCH +; ============================================================================= +var zFastPlunge = 10.0 +var zSlowPlunge = 2.0 +var zBackoff = 1.0 + + +; ============================================================================= +; FEEDRATES +; ============================================================================= +var fZFast = 600 +var fZSlow = 50 +var fXYTravel = 6000 +var fXYScan = 50 + + +; ============================================================================= +; DOCK BAND +; ============================================================================= +var dockYMin = 9999 ; set <= dockYMax to enable +var dockYMax = -9999 +var corridorY = 150 + + +; ============================================================================= +; APPLY (create-if-missing, else set) +; ============================================================================= +M98 P"/macros/toolprobe_v3/globals.g" +M98 P"/macros/toolprobe_v3/state.g" + +set global.tp3_probeSeedX = var.seedX +set global.tp3_probeSeedY = var.seedY +set global.tp3_probeSeedZGuess = var.seedZGuess +set global.tp3_probeDomeZ = var.domeZ + +set global.tp3_probeIndex = var.probeIndex +set global.tp3_probeTrigMin = var.trigMin +set global.tp3_probeTrigMax = var.trigMax + +set global.tp3_endstopPinX = var.endstopPinX +set global.tp3_endstopPinY = var.endstopPinY + +set global.tp3_travelZ = var.travelZ +set global.tp3_workcellZ = var.workcellZ +set global.tp3_betweenTouchZLift = var.betweenTouchZLift +set global.tp3_locateEngagementDepth = var.locateEngagementDepth +set global.tp3_toolNudgeZOffset = var.toolNudgeZOffset + +set global.tp3_edgeStart = var.edgeStart +set global.tp3_refineMargin = var.refineMargin + +set global.tp3_spanMin = var.spanMin +set global.tp3_spanMax = var.spanMax +set global.tp3_spanMatchTol = var.spanMatchTol +set global.tp3_centerRepeatTol = var.centerRepeatTol + +set global.tp3_zFastPlunge = var.zFastPlunge +set global.tp3_zSlowPlunge = var.zSlowPlunge +set global.tp3_zBackoff = var.zBackoff + +set global.tp3_fZFast = var.fZFast +set global.tp3_fZSlow = var.fZSlow +set global.tp3_fXYTravel = var.fXYTravel +set global.tp3_fXYScan = var.fXYScan + +set global.tp3_dockYMin = var.dockYMin +set global.tp3_dockYMax = var.dockYMax +set global.tp3_corridorY = var.corridorY + +if var.resetEstimateToSeed + set global.tp3_probeX = var.seedX + set global.tp3_probeY = var.seedY + set global.tp3_probeZPlane = var.seedZGuess + set global.tp3_located = false + M118 P0 S"toolprobe_v3: estimate reset to seed (tp3_located=false)" +else + M118 P0 S"toolprobe_v3: tunables applied (estimate preserved)" diff --git a/RRF Implementation/_lib/BracketAxis.g b/RRF Implementation/_lib/BracketAxis.g new file mode 100644 index 0000000..de38ee4 --- /dev/null +++ b/RRF Implementation/_lib/BracketAxis.g @@ -0,0 +1,37 @@ +; /macros/toolprobe_v3/_lib/BracketAxis.g +; +; Bracket the dome on one axis: scan from -R to find the minus-side edge, +; then scan from +R to find the plus-side edge. Returns center and span. +; +; Params: +; A = axis (0 = X, 1 = Y) +; C = center estimate (machine frame) +; R = half-window: start scans this far from C +; Z = engagement Z (machine frame) +; +; Outputs: +; global.tp3_lastCenter +; global.tp3_lastSpan + +M98 P"/macros/toolprobe_v3/globals.g" +M98 P"/macros/toolprobe_v3/state.g" + +if !exists(param.A) || !exists(param.C) || !exists(param.R) || !exists(param.Z) + abort "BracketAxis: requires A, C, R, Z" + +; Minus-side scan: start at C - R, scan in +1 direction +M98 P"/macros/toolprobe_v3/_lib/ScanEdgeNative.g" A{param.A} D1 S{param.C - param.R} Z{param.Z} +var minus = global.tp3_lastEdge + +; Plus-side scan: start at C + R, scan in -1 direction +M98 P"/macros/toolprobe_v3/_lib/ScanEdgeNative.g" A{param.A} D-1 S{param.C + param.R} Z{param.Z} +var plus = global.tp3_lastEdge + +set global.tp3_lastSpan = var.plus - var.minus +set global.tp3_lastCenter = (var.plus + var.minus) / 2 + +if global.tp3_lastSpan <= 0 + abort "BracketAxis: invalid span. minus=" ^ var.minus ^ " plus=" ^ var.plus + +var axisName = (param.A == 0) ? "X" : "Y" +M98 P"/macros/toolprobe_v3/_lib/Status.g" S{"bracket " ^ var.axisName ^ ": center=" ^ global.tp3_lastCenter ^ ", span=" ^ global.tp3_lastSpan} diff --git a/RRF Implementation/_lib/DiscoverProbeZ.g b/RRF Implementation/_lib/DiscoverProbeZ.g new file mode 100644 index 0000000..7ccf8e3 --- /dev/null +++ b/RRF Implementation/_lib/DiscoverProbeZ.g @@ -0,0 +1,54 @@ +; /macros/toolprobe_v3/_lib/DiscoverProbeZ.g +; +; Find the probe top via a single native G1 H4 plunge from travelZ. +; Output: +; global.tp3_discoveredEngageZ = userPosition at first contact (tip frame) +; +; The caller (LocateToolProbe.g) is responsible for adding any further +; engagement depth via tp3_locateEngagementDepth. +; +; Assumes you are already positioned at (tp3_probeX, tp3_probeY). + +M98 P"/macros/toolprobe_v3/globals.g" +M98 P"/macros/toolprobe_v3/state.g" + +M98 P"/macros/toolprobe_v3/_lib/Status.g" S"toolprobe_v3: discovering probe Z plane" + +; Verify we are not already triggered before plunging +M98 P"/macros/toolprobe_v3/_lib/Probe_IsTriggered.g" +if global.tp3_probeTriggered + abort "DiscoverProbeZ: probe already triggered at travel Z (raise tp3_travelZ or check probe state)" + +; Lift to safe Z first. No G53 — with T-1 it makes no difference, and dropping +; G53 keeps this leaf consistent with the T-active context. +G90 +G1 Z{global.tp3_travelZ} F{global.tp3_fZFast} +M400 + +; Assign probe as Z endstop, native H4 plunge, then restore Z endstop +M98 P"/macros/toolprobe_v3/_lib/UseProbeAsEndstop.g" A2 + +; Plunge from travelZ down toward 0 — H4 stops on trigger +G1 H4 Z0 F{global.tp3_fZFast} +M400 + +; Capture in tool-tip frame (userPosition). With T-1 this equals +; machinePosition; with T-active (not the normal call site) it would be tip Z. +var touchZ = move.axes[2].userPosition + +M98 P"/macros/toolprobe_v3/_lib/UseProbeAsEndstop.g" A2 R1 + +; Sanity: we should not have run all the way to Z0 +if var.touchZ <= 0.05 + abort "DiscoverProbeZ: plunge ran to Z0 without trigger. Seed XY likely off, or probe failed." + +; Lift back to safe Z +G1 Z{global.tp3_travelZ} F{global.tp3_fZFast} +M400 + +; Store the discovered touch Z. The caller adds tp3_locateEngagementDepth. +; Note: tp3_probeZPlane is deliberately NOT set here — LocateToolProbe's final +; TouchZNative is the single source of truth for that value. +set global.tp3_discoveredEngageZ = var.touchZ + +M98 P"/macros/toolprobe_v3/_lib/Status.g" S{"toolprobe_v3: probe top Z=" ^ var.touchZ} diff --git a/RRF Implementation/_lib/EnsureSafeStart.g b/RRF Implementation/_lib/EnsureSafeStart.g new file mode 100644 index 0000000..f67ac45 --- /dev/null +++ b/RRF Implementation/_lib/EnsureSafeStart.g @@ -0,0 +1,14 @@ +; /macros/toolprobe_v3/_lib/EnsureSafeStart.g +; Common pre-flight for top-level toolprobe_v3 entries. +; +; - Restores any stale endstop swap from a previous aborted run +; - Verifies XYZ are homed +; - Verifies T-1 (no tool selected) + +M98 P"/macros/toolprobe_v3/_lib/RestoreEndstops.g" + +if !move.axes[0].homed || !move.axes[1].homed || !move.axes[2].homed + abort "toolprobe_v3: home all axes first." + +if state.currentTool != -1 + abort "toolprobe_v3: deselect tool first (T-1)." diff --git a/RRF Implementation/_lib/MoveToProbeXY.g b/RRF Implementation/_lib/MoveToProbeXY.g new file mode 100644 index 0000000..cf0148d --- /dev/null +++ b/RRF Implementation/_lib/MoveToProbeXY.g @@ -0,0 +1,28 @@ +; /macros/toolprobe_v3/_lib/MoveToProbeXY.g +; Safe travel to (tp3_probeX, tp3_probeY) at travelZ, with optional dock-band +; avoidance routing. Caller drops Z afterward. + +M98 P"/macros/toolprobe_v3/globals.g" +M98 P"/macros/toolprobe_v3/state.g" + +; Note: no G53 — with workplace offsets at 0 and a tool selected, user-frame +; moves correctly position the TOOL TIP (not the carriage) at the probe XY. +; G53 would crash a tool extending below the carriage at travelZ. +; +; Dock-band routing assumption: with T-active, the tool's Y offset is small +; relative to (corridorY - dockYMin/Max). Typical Jubilee setups satisfy this. +G90 +G1 Z{global.tp3_travelZ} F{global.tp3_fZFast} + +var routed = false +if global.tp3_dockYMin <= global.tp3_dockYMax + var nowInBand = (move.axes[1].userPosition >= global.tp3_dockYMin) && (move.axes[1].userPosition <= global.tp3_dockYMax) + var tgtInBand = (global.tp3_probeY >= global.tp3_dockYMin) && (global.tp3_probeY <= global.tp3_dockYMax) + if var.nowInBand || var.tgtInBand + G1 Y{global.tp3_corridorY} F{global.tp3_fXYTravel} + G1 X{global.tp3_probeX} F{global.tp3_fXYTravel} + G1 Y{global.tp3_probeY} F{global.tp3_fXYTravel} + set var.routed = true + +if !var.routed + G1 X{global.tp3_probeX} Y{global.tp3_probeY} F{global.tp3_fXYTravel} diff --git a/RRF Implementation/_lib/Probe_IsTriggered.g b/RRF Implementation/_lib/Probe_IsTriggered.g new file mode 100644 index 0000000..2e980dc --- /dev/null +++ b/RRF Implementation/_lib/Probe_IsTriggered.g @@ -0,0 +1,12 @@ +; /macros/toolprobe_v3/_lib/Probe_IsTriggered.g +; Status query (no motion). Sets global.tp3_probeTriggered based on the probe +; reading. Used to verify untriggered start state, NOT as a probing primitive. +; All actual probing is done with native G1 H4 moves. + +M98 P"/macros/toolprobe_v3/globals.g" + +if !exists(global.tp3_probeTriggered) + global tp3_probeTriggered = false + +var v = sensors.probes[global.tp3_probeIndex].value[0] +set global.tp3_probeTriggered = (var.v >= global.tp3_probeTrigMin) && (var.v <= global.tp3_probeTrigMax) diff --git a/RRF Implementation/_lib/RestoreEndstops.g b/RRF Implementation/_lib/RestoreEndstops.g new file mode 100644 index 0000000..4623454 --- /dev/null +++ b/RRF Implementation/_lib/RestoreEndstops.g @@ -0,0 +1,8 @@ +; /macros/toolprobe_v3/_lib/RestoreEndstops.g +; Defensive full restore of XYZ endstop configuration. Called at the start of +; top-level macros (in case a previous run aborted with endstops swapped) and +; at the end of every top-level macro. + +M98 P"/macros/toolprobe_v3/_lib/UseProbeAsEndstop.g" A0 R1 +M98 P"/macros/toolprobe_v3/_lib/UseProbeAsEndstop.g" A1 R1 +M98 P"/macros/toolprobe_v3/_lib/UseProbeAsEndstop.g" A2 R1 diff --git a/RRF Implementation/_lib/ScanEdgeNative.g b/RRF Implementation/_lib/ScanEdgeNative.g new file mode 100644 index 0000000..070eae6 --- /dev/null +++ b/RRF Implementation/_lib/ScanEdgeNative.g @@ -0,0 +1,95 @@ +; /macros/toolprobe_v3/_lib/ScanEdgeNative.g +; +; Single-axis edge scan using native G1 H4 probing. The probe is assigned as +; the endstop for ONLY this axis for the duration of the scan, then restored +; immediately after the move completes. +; +; Params: +; A = axis (0 = X, 1 = Y) +; D = direction of scan motion (+1 or -1) +; S = absolute START coordinate on that axis (machine frame; should be +; offset AWAY from the expected edge so the move starts untriggered) +; Z = engagement Z (machine frame) +; +; Output: +; global.tp3_lastEdge = machine-frame coordinate where the probe tripped + +M98 P"/macros/toolprobe_v3/globals.g" +M98 P"/macros/toolprobe_v3/state.g" + +if !exists(param.A) || !exists(param.D) || !exists(param.S) || !exists(param.Z) + abort "ScanEdgeNative: requires A, D, S, Z" + +var axisIsX = (param.A == 0) +var dir = (param.D > 0) ? 1 : -1 +var startCoord = param.S +var zEngage = param.Z + +; Total scan window: from start, scan up to 2 * edgeStart through center +var maxScan = 2 * global.tp3_edgeStart + +; --- Move to start at safe Z --- +; Note: no G53 — with workplace offsets at 0, user-frame moves give the same +; machine positions when T-1 AND correctly target the tool tip when T-active. +; G53 here would crash a tool extending below the carriage, and would ignore +; tool offsets when bracketing the dome. +G90 +G1 Z{global.tp3_travelZ} F{global.tp3_fZFast} +if var.axisIsX + G1 X{var.startCoord} F{global.tp3_fXYTravel} +else + G1 Y{var.startCoord} F{global.tp3_fXYTravel} + +; --- Drop to engagement Z --- +G1 Z{var.zEngage} F{global.tp3_fZFast} +M400 +G4 P100 ; settle + +; --- Verify untriggered start --- +M98 P"/macros/toolprobe_v3/_lib/Probe_IsTriggered.g" +if global.tp3_probeTriggered + ; Lift before erroring so retry is safer + G1 Z{global.tp3_travelZ} F{global.tp3_fZFast} + echo "ScanEdgeNative: probe already triggered at scan start. zEngage=" ^ var.zEngage + echo "Contact feature cannot dive to engagement depth." + echo "T-1 (LocateToolProbe): reduce tp3_locateEngagementDepth in UserConfig.g." + echo "T-active (CalibrateActiveTool): raise tp3_toolNudgeZOffset toward 0." + abort "ScanEdgeNative: contact feature cannot reach engagement depth" + +; --- Native H4 scan --- +M98 P"/macros/toolprobe_v3/_lib/UseProbeAsEndstop.g" A{param.A} + +G91 +if var.axisIsX + G1 H4 X{var.dir * var.maxScan} F{global.tp3_fXYScan} +else + G1 H4 Y{var.dir * var.maxScan} F{global.tp3_fXYScan} +G90 +M400 ; ensure motion finished and OM updated + +; --- Capture stop position --- +; userPosition reflects the TOOL TIP position (when a tool is selected) and +; equals machinePosition when T-1. Using userPosition makes the offset formula +; in CalibrateActiveTool come out correct in both contexts. +var hitPos = var.axisIsX ? move.axes[0].userPosition : move.axes[1].userPosition + +; --- Restore endstop for this axis immediately --- +M98 P"/macros/toolprobe_v3/_lib/UseProbeAsEndstop.g" A{param.A} R1 + +; --- Did the move actually trigger, or did it run to full travel? --- +var traveled = (var.hitPos - var.startCoord) * var.dir +if var.traveled >= (var.maxScan - 0.005) + ; Lift before erroring + G1 Z{global.tp3_travelZ} F{global.tp3_fZFast} + abort "ScanEdgeNative: probe did not trigger within " ^ var.maxScan ^ "mm scan." + +set global.tp3_lastEdge = var.hitPos + +; --- Lift after touch so cross moves don't drag --- +G91 +G1 Z{global.tp3_betweenTouchZLift} F{global.tp3_fZFast} +G90 + +var axisName = var.axisIsX ? "X" : "Y" +var dirName = (var.dir > 0) ? "+" : "-" +M98 P"/macros/toolprobe_v3/_lib/Status.g" S{"edge " ^ var.axisName ^ var.dirName ^ " = " ^ var.hitPos} diff --git a/RRF Implementation/_lib/Status.g b/RRF Implementation/_lib/Status.g new file mode 100644 index 0000000..17c43a6 --- /dev/null +++ b/RRF Implementation/_lib/Status.g @@ -0,0 +1,11 @@ +; /macros/toolprobe_v3/_lib/Status.g +; Push a status line to all DWC clients AND the firmware console. +; +; Usage: +; M98 P"/macros/toolprobe_v3/_lib/Status.g" S"toolprobe_v3: locating fixed probe" + +if !exists(param.S) + abort "Status.g: requires S" + +M118 P0 S{param.S} +echo {param.S} diff --git a/RRF Implementation/_lib/TouchZNative.g b/RRF Implementation/_lib/TouchZNative.g new file mode 100644 index 0000000..c2fd1a6 --- /dev/null +++ b/RRF Implementation/_lib/TouchZNative.g @@ -0,0 +1,68 @@ +; /macros/toolprobe_v3/_lib/TouchZNative.g +; +; Native G1 H4 Z touch: untriggered-check -> fast plunge -> backoff -> +; slow plunge. Records the slow trigger position. +; +; Caller must already have positioned the head at (probeX, probeY, workcellZ) +; with the probe untriggered. +; +; Output: +; global.tp3_lastZ = machine-frame Z coord at slow trigger + +M98 P"/macros/toolprobe_v3/globals.g" +M98 P"/macros/toolprobe_v3/state.g" + +; --- Verify untriggered start --- +M98 P"/macros/toolprobe_v3/_lib/Probe_IsTriggered.g" +if global.tp3_probeTriggered + abort "TouchZNative: probe already triggered. Raise tp3_workcellZ." + +; --- Assign Z probe --- +M98 P"/macros/toolprobe_v3/_lib/UseProbeAsEndstop.g" A2 + +; --- Fast plunge --- +G91 +G1 H4 Z{-global.tp3_zFastPlunge} F{global.tp3_fZFast} +G90 +M400 + +; H4 stops on trigger; sanity check +M98 P"/macros/toolprobe_v3/_lib/Probe_IsTriggered.g" +if !global.tp3_probeTriggered + M98 P"/macros/toolprobe_v3/_lib/UseProbeAsEndstop.g" A2 R1 + abort "TouchZNative: fast plunge ran out without trigger. Lower tp3_workcellZ or raise tp3_zFastPlunge." + +; --- Backoff to release contact --- +G91 +G1 Z{global.tp3_zBackoff} F{global.tp3_fZFast} +G90 +M400 + +M98 P"/macros/toolprobe_v3/_lib/Probe_IsTriggered.g" +if global.tp3_probeTriggered + M98 P"/macros/toolprobe_v3/_lib/UseProbeAsEndstop.g" A2 R1 + abort "TouchZNative: probe did not release after backoff. Increase tp3_zBackoff." + +; --- Slow plunge --- +G91 +G1 H4 Z{-global.tp3_zSlowPlunge} F{global.tp3_fZSlow} +G90 +M400 + +M98 P"/macros/toolprobe_v3/_lib/Probe_IsTriggered.g" +if !global.tp3_probeTriggered + M98 P"/macros/toolprobe_v3/_lib/UseProbeAsEndstop.g" A2 R1 + abort "TouchZNative: slow plunge ran out without trigger. Increase tp3_zSlowPlunge." + +; userPosition gives tip Z (T-active) or carriage Z (T-1 — they're equal). The +; CalibrateActiveTool offset math relies on this being the tool-tip frame. +set global.tp3_lastZ = move.axes[2].userPosition + +; --- Restore Z endstop and lift --- +M98 P"/macros/toolprobe_v3/_lib/UseProbeAsEndstop.g" A2 R1 + +G91 +G1 Z{global.tp3_zBackoff + global.tp3_betweenTouchZLift} F{global.tp3_fZFast} +G90 + +M98 P"/macros/toolprobe_v3/_lib/Status.g" S{"Z touch = " ^ global.tp3_lastZ} diff --git a/RRF Implementation/_lib/UseProbeAsEndstop.g b/RRF Implementation/_lib/UseProbeAsEndstop.g new file mode 100644 index 0000000..5c15da9 --- /dev/null +++ b/RRF Implementation/_lib/UseProbeAsEndstop.g @@ -0,0 +1,39 @@ +; /macros/toolprobe_v3/_lib/UseProbeAsEndstop.g +; +; Assign or restore the endstop for one axis. Per-axis swap keeps the other +; axes on their real endstops during a scan, so an inadvertent G28 X (etc.) +; can't trigger off the tool probe. +; +; Params: +; A = 0 (X) | 1 (Y) | 2 (Z) +; R = 1 to RESTORE the default endstop for that axis (otherwise: assign probe) +; +; Defaults restored: +; X -> S1 P{tp3_endstopPinX} +; Y -> S1 P{tp3_endstopPinY} +; Z -> M574 Z0 (no physical Z endstop; matches your config.g) + +if !exists(param.A) + abort "UseProbeAsEndstop: requires A (0,1,2)" + +var axis = param.A +var restore = exists(param.R) && (param.R == 1) + +if var.restore + if var.axis == 0 + M574 X1 S1 P{global.tp3_endstopPinX} + elif var.axis == 1 + M574 Y1 S1 P{global.tp3_endstopPinY} + elif var.axis == 2 + M574 Z0 + else + abort "UseProbeAsEndstop: bad axis " ^ var.axis +else + if var.axis == 0 + M574 X1 S2 K{global.tp3_probeIndex} + elif var.axis == 1 + M574 Y1 S2 K{global.tp3_probeIndex} + elif var.axis == 2 + M574 Z1 S2 K{global.tp3_probeIndex} + else + abort "UseProbeAsEndstop: bad axis " ^ var.axis diff --git a/RRF Implementation/globals.g b/RRF Implementation/globals.g new file mode 100644 index 0000000..9f86d00 --- /dev/null +++ b/RRF Implementation/globals.g @@ -0,0 +1,178 @@ +; /macros/toolprobe_v3/globals.g +; +; toolprobe_v3 — best of both worlds: +; - Native G1 H4 probing (firmware-level, fast, accurate) -- from original toolprobe/ +; - Config / state / user-config separation -- from toolprobe_v2/ +; - Span + center-repeatability validation -- from toolprobe_v2/ +; - Dome geometry awareness -- from toolprobe_v2/ +; - Per-axis M574 swap, scoped at the top-level macro -- new +; - M118 status for DWC visibility -- new +; +; Naming: all globals live under the `tp3_` namespace so v3 coexists with v2 +; during the transition. Edit values via UserConfig.g, not here. + +; ============================================================================= +; PROBE SELECTION +; ============================================================================= + +; Tool probe index in your M558/G31 setup (your config has K3 = tool probe) +if !exists(global.tp3_probeIndex) + global tp3_probeIndex = 3 + +; Trigger band for digital probes (P8 reports 0 / 1000) +if !exists(global.tp3_probeTrigMin) + global tp3_probeTrigMin = 900 +if !exists(global.tp3_probeTrigMax) + global tp3_probeTrigMax = 1100 + + +; ============================================================================= +; ENDSTOP RESTORE PINS +; v3 owns its own pin globals so it does not depend on the older +; SetProbeConfig.g globals. Keep these in sync with config.g. +; ============================================================================= + +if !exists(global.tp3_endstopPinX) + global tp3_endstopPinX = "^io2" +if !exists(global.tp3_endstopPinY) + global tp3_endstopPinY = "^io1" + + +; ============================================================================= +; SEED VALUES (rough manual estimates, machine frame, T-1 active) +; After homing these should put the carriage within the probe footprint. +; Refined values are written to state.g at runtime. +; ============================================================================= + +if !exists(global.tp3_probeSeedX) + global tp3_probeSeedX = 263.8675 +if !exists(global.tp3_probeSeedY) + global tp3_probeSeedY = 309.9875 + +; Rough estimate of the probe-top Z (machine frame). +; Used only to place XY edge scans into the engagement band; true plane is +; measured by DiscoverProbeZ + TouchZNative. +if !exists(global.tp3_probeSeedZGuess) + global tp3_probeSeedZGuess = 4.140 + +; Vertical correction from contact plane to dome centerline. +; Used by tool-tip probing, not by LocateToolProbe itself. +if !exists(global.tp3_probeDomeZ) + global tp3_probeDomeZ = 0.5 + + +; ============================================================================= +; Z POLICY +; ============================================================================= + +; Global travel Z (machine frame) used between regions +if !exists(global.tp3_travelZ) + global tp3_travelZ = 15 + +; Local "above the probe" Z used as start point for Z touches +if !exists(global.tp3_workcellZ) + global tp3_workcellZ = 8 + +; Lift after each XY edge touch so cross moves don't drag the dome +if !exists(global.tp3_betweenTouchZLift) + global tp3_betweenTouchZLift = 0.5 + +; ===== CARRIAGE GEOMETRY — engagement depth for LocateToolProbe (T-1) ===== +; LocateToolProbe brackets the probe dome with the BARE CARRIAGE (T-1). After +; the first downward touch, the carriage drops THIS many mm further so the +; carriage's contact feature engages the dome's SIDE for the X/Y scans. +; +; - Has a Nudge / probe peg sticking 5+mm below the carriage: 1.0 - 1.5 +; - Has a small contact pin (1-2mm below carriage body): 0.3 - 0.7 +; - Just a flat carriage bottom (no dedicated probe feature): 0.0 - 0.1 +; +; If you see "ScanEdgeNative: probe already triggered at scan start" during +; LocateToolProbe, this value is too large for your contact feature — reduce +; it. If you see "probe did not trigger within 12mm scan", increase it. +if !exists(global.tp3_locateEngagementDepth) + global tp3_locateEngagementDepth = 0.5 + +; ===== TOOL TIP GEOMETRY — engagement depth for CalibrateActiveTool ===== +; After the tip-discovery touch, the tip drops THIS many mm further for the +; XY tip scans. Tool tips are usually small and fragile, so keep this shallow. +; Negative number = below the discovered touch point. +if !exists(global.tp3_toolNudgeZOffset) + global tp3_toolNudgeZOffset = -0.20 + + +; ============================================================================= +; XY GEOMETRY +; ============================================================================= + +; Half-window used to start an edge scan: probe is expected to be within +; tp3_edgeStart of the seed/refined center along each axis. +if !exists(global.tp3_edgeStart) + global tp3_edgeStart = 6.0 + +; Refine pass margin added beyond half-span before the second edge scan +if !exists(global.tp3_refineMargin) + global tp3_refineMargin = 0.5 + + +; ============================================================================= +; VALIDATION +; ============================================================================= + +; Acceptable measured span across the dome at engagement Z +if !exists(global.tp3_spanMin) + global tp3_spanMin = 1.0 +if !exists(global.tp3_spanMax) + global tp3_spanMax = 12.0 + +; Allowed mismatch between X and Y spans (symmetry sanity check) +if !exists(global.tp3_spanMatchTol) + global tp3_spanMatchTol = 1.0 + +; Allowed center movement between coarse and refine passes +if !exists(global.tp3_centerRepeatTol) + global tp3_centerRepeatTol = 0.05 + + +; ============================================================================= +; Z TOUCH PARAMETERS +; ============================================================================= + +if !exists(global.tp3_zFastPlunge) + global tp3_zFastPlunge = 10.0 +if !exists(global.tp3_zSlowPlunge) + global tp3_zSlowPlunge = 2.0 +if !exists(global.tp3_zBackoff) + global tp3_zBackoff = 1.0 + +; Plunge distance used by CalibrateActiveTool to discover where the actual +; tool tip touches the probe (handles existing G10 Z offset error). Must be +; larger than the gap from travelZ to the probe top in the worst-case tool +; offset error you expect. +if !exists(global.tp3_toolDiscoveryPlunge) + global tp3_toolDiscoveryPlunge = 20 + + +; ============================================================================= +; FEEDRATES (mm/min) +; ============================================================================= + +if !exists(global.tp3_fZFast) + global tp3_fZFast = 600 +if !exists(global.tp3_fZSlow) + global tp3_fZSlow = 50 +if !exists(global.tp3_fXYTravel) + global tp3_fXYTravel = 6000 +if !exists(global.tp3_fXYScan) + global tp3_fXYScan = 50 + + +; ============================================================================= +; DOCK BAND (Y range to avoid for cross-bed travel) +; ============================================================================= + +if !exists(global.tp3_dockYMin) + global tp3_dockYMin = 9999 ; disabled if min > max +if !exists(global.tp3_dockYMax) + global tp3_dockYMax = -9999 +if !exists(global.tp3_corridorY) + global tp3_corridorY = 150 ; safe Y outside the dock band diff --git a/RRF Implementation/state.g b/RRF Implementation/state.g new file mode 100644 index 0000000..9d22fbc --- /dev/null +++ b/RRF Implementation/state.g @@ -0,0 +1,35 @@ +; /macros/toolprobe_v3/state.g +; Runtime cache populated by LocateToolProbe.g and the leaf macros. +; Loads globals.g first so this file is safe to run standalone. + +M98 P"/macros/toolprobe_v3/globals.g" + +; --- Located probe (machine frame, T-1) --- +if !exists(global.tp3_located) + global tp3_located = false +if !exists(global.tp3_probeX) + global tp3_probeX = global.tp3_probeSeedX +if !exists(global.tp3_probeY) + global tp3_probeY = global.tp3_probeSeedY +if !exists(global.tp3_probeZPlane) + global tp3_probeZPlane = global.tp3_probeSeedZGuess + +; Workspace Z offset that was active when probeZPlane was captured. Used by +; CalibrateActiveTool to detect "autoz happened since LocateToolProbe" and +; demand a RefreshProbeZPlane.g run. Sentinel value -9999 means never set. +if !exists(global.tp3_probeZPlaneFrame) + global tp3_probeZPlaneFrame = -9999 + +; --- Last-touch scratch globals (written by leaf macros) --- +if !exists(global.tp3_lastEdge) + global tp3_lastEdge = 0 +if !exists(global.tp3_lastCenter) + global tp3_lastCenter = 0 +if !exists(global.tp3_lastSpan) + global tp3_lastSpan = 0 +if !exists(global.tp3_lastZ) + global tp3_lastZ = 0 +if !exists(global.tp3_discoveredEngageZ) + global tp3_discoveredEngageZ = 0 +if !exists(global.tp3_probeTriggered) + global tp3_probeTriggered = false