Files
linuxcnc/nc_files/TOOLS.md
Thaddeus Hughes ad1f8719d6 big overhaul
2026-04-05 20:51:43 -05:00

15 KiB
Raw Permalink Blame History

Tool Changes, Offsets & Work Coordinates in LinuxCNC

Reference for the Lagun mill config (non-random manual toolchanger, GMOCCAPY GUI, inch mode).


Tool Table (tool.tbl)

Each line defines a tool:

T3   P3   D+0.187500            ;3/16in flat
T1   P1   D+0.187500 I+7.000000 ;0.201in DrillBit
T5   P5   D+0.250000            ;1/4
Column Meaning
T Tool number (what programs reference with T1, T5, etc.)
P Pocket number (our setup just uses P = T)
Z Tool length offset (distance from spindle reference to tool tip)
D Tool diameter (full width, not radius)
; Comment

Important: The D column stores diameter, but G10 L1 sets it using radius (R word). This is a common source of confusion.


Tool Change Sequence

T1          ; select tool 1 (prepares it, does NOT load it)
M6          ; execute the change — pops up the manual tool change dialog
G43         ; activate that tool's length offset
  • T alone only selects (prepares) a tool. Nothing physical happens.
  • M6 performs the actual change. On our machine this pops up a dialog prompting the operator to insert the tool and click OK.
  • G43 applies the tool's Z offset from the tool table. Without this line, the machine has no idea how long the tool is.
  • T1 M6 on one line is fine (and common).

After M6, the built-in parameter #<_current_tool> holds the loaded tool number, and #5410 holds its diameter.


Tool Length Offset (G43 / G49)

Activating

Command Effect
G43 Apply TLO of the currently loaded tool (from last M6)
G43 H1 Apply TLO of tool 1 from the table (doesn't have to match spindle tool)
G43.1 Z0.5 Dynamic TLO: set Z offset to 0.5 directly (doesn't write to table)
G43.2 H1 Cumulative: add tool 1's offset on top of the current offset

G43 shifts all subsequent Z moves by the tool's Z offset. No motion occurs on the G43 line itself — the offset applies on the next move.

Canceling

G49     ; cancel tool length offset

Typical multi-tool workflow

T1 M6               ; load tool 1
G43                  ; activate its TLO
; ... do work ...
G49                  ; cancel TLO before next change
T2 M6               ; load tool 2
G43                  ; activate tool 2's TLO

Setting Tool Offsets with G10

G10 L1 — Write directly to the tool table

G10 L1 P<tool#> Z<length> R<radius>
  • P: tool number to update
  • Z: tool length offset (direct value)
  • R: tool radius (half the diameter). LinuxCNC stores this as D = 2 * R in the tool table.

Examples:

G10 L1 P1 Z-2.500 R0.125   ; tool 1: length=-2.5", radius=0.125" (1/4" endmill, D=0.250)
G10 L1 P1 R[3/16/2]        ; just update radius: 3/16" tool -> R=0.09375 -> D=0.1875

After G10 L1, re-issue G43 to pick up the new offset if that tool is already loaded.

G10 L10 — Set offset by touching off (work coords as reference)

G10 L10 P<tool#> Z<desired_coord>

Calculates what Z offset the tool table needs so that, with the current work coordinate system active and the machine at its current position, the Z display would read the specified value.

Touch-off workflow:

  1. Load tool, jog Z down until it touches the workpiece surface
  2. G10 L10 P1 Z0 — "the tip is at Z=0, calculate the offset"

G10 L11 — Touch off using G59.3 as reference

Same as L10 but uses G59.3 (with no G52/G92) as the reference frame. Useful if you have a fixed tool-length probe at a known machine position stored in G59.3.


Cutter Radius Compensation (G41 / G42 / G40)

Cutter comp shifts the toolpath left or right of the programmed path by the tool's radius. This lets you program to the part geometry (the actual edge you want) and let LinuxCNC offset the toolpath by the tool radius automatically.

Basics

G41         ; compensate LEFT of the programmed path (climb milling on outside profiles)
G42         ; compensate RIGHT of the programmed path (conventional milling on outside profiles)
G40         ; cancel compensation — return to programming on centerline

"Left" and "right" are from the perspective of looking down the tool axis in the direction of travel.

The D word

G41 D1      ; use tool 1's diameter from the table for the offset amount
G42         ; no D = use the currently loaded tool's diameter

The D word in G41/G42 is a tool number, not a diameter value. LinuxCNC looks up that tool's D column (diameter), halves it, and uses that as the offset distance.

Rules and gotchas

  • The lead-in move (first move after G41/G42) must be at least as long as the tool radius. A rapid (G0) is fine.
  • The lead-out move (move on the same line as G40) must also be linear and at least as long as the tool radius.
  • Inside corners: the path is shortened to prevent gouging.
  • Outside corners: the path is extended (the tool wraps around the corner).
  • U-turns and tight inside corners where the tool can't physically fit will cause an error.
  • Cutter comp only works in G17 (XY plane). For G18/G19 it compensates in the respective plane.
  • You cannot start cutter comp while already in cutter comp — must G40 first.

Example: cutting an outside profile

G10 L1 P1 R[1/4/2]          ; tool 1 = 1/4" endmill (R=0.125, D=0.250)
T1 M6
G43

G0 X-1 Y-1                  ; position away from the part
G41                          ; turn on left comp (uses current tool's D)
G1 X0 Y0 F10                ; lead-in move to first corner (must be >= tool radius)
G1 X0 Y2                    ; cut along left edge
G1 X3 Y2                    ; cut along top edge
G1 X3 Y0                    ; cut along right edge
G1 X0 Y0                    ; cut along bottom edge, back to start
G40                          ; cancel comp
G0 X-1 Y-1                  ; lead-out / retract

The programmed path (X0 Y0 to X3 Y2) is the actual part edge. The tool centerline runs 0.125" outside of it.

Dynamic variant

G41.1 D0.250    ; compensate left by 0.250" diameter (= 0.125" offset) directly
G42.1 D0.250    ; compensate right

Here the D word IS a diameter value (not a tool number). Useful when you want to specify the offset directly without looking it up from the table.

Cutter comp vs. our macros

Our macros (pocket_circ, frame_rect, etc.) do their own tool-diameter compensation internally using #<_td>. They do not use G41/G42. So:

  • Use G41/G42 when you're writing raw G-code profiles (manually programmed contours).
  • Use #<_td> when calling our subroutines — they handle the offset math themselves.
  • Don't use both at the same time on the same toolpath.

Work Offsets (G54G59.3)

Work offsets define where "zero" is on your workpiece relative to the machine's home position.

Available coordinate systems

G-code Name P number (for G10)
G54 Work offset 1 (default) P1
G55 Work offset 2 P2
G56 Work offset 3 P3
G57 Work offset 4 P4
G58 Work offset 5 P5
G59 Work offset 6 P6
G59.1 Work offset 7 P7
G59.2 Work offset 8 P8
G59.3 Work offset 9 P9

These persist across power cycles — they're stored in linuxcnc.var.

Setting work offsets

Touch-off method (most common): jog to where you want zero, then:

G10 L20 P1 X0 Y0    ; "right here is G54 X0 Y0"
G10 L20 P0 Z0        ; "right here is Z0 in the currently active system"
  • P0 = whichever G5x is currently active
  • You only need to specify the axes you want to set

Direct method: if you know the machine-coordinate position of your fixture:

G10 L2 P1 X-12.500 Y-6.000 Z0.000    ; G54 origin is at machine X-12.5 Y-6.0 Z0.0

Switching between coordinate systems:

G55    ; now all coords are relative to work offset 2

Practical use

  • One fixture, one part: Just use G54. Touch off XYZ zero on your stock.
  • Multiple fixtures / vises: G54 for vise 1, G55 for vise 2. Touch off each.
  • Multiple setups on one part: Flip the part, touch off new Z in G54.

G52 and G92 (temporary offsets)

G52 X1 Y1 adds a temporary offset on top of the active G5x. Useful for pattern repeats.

G92 X0 Y0 says "my current position IS X0 Y0" (like G10 L20 but temporary). Caution: G92 offsets persist across program runs until cleared with G92.1. This is a common gotcha. Prefer G52 over G92.

Your pendant buttons

Button MDI Command What it does
Macro 5 G10 L20 P0 X0 Zero X in current work offset
Macro 6 G10 L20 P0 Y0 Zero Y in current work offset
Macro 7 G10 L20 P0 Z0 Zero Z in current work offset
Macro 1 G10 L20 P0 X[#<_x>/2.0] Halve X (center-finding)
Macro 2 G10 L20 P0 Y[#<_y>/2.0] Halve Y (center-finding)

The halve trick: touch one edge of the stock and zero it, jog to the other edge, press the halve button — now you're at the center.


Coordinate System Hierarchy

Displayed position = Machine position
                   + G5x work offset (G54, G55, ... set by G10 L2/L20)
                   + G52/G92 offset
                   + G43 tool length offset

G53 bypasses all offsets and moves in raw machine coordinates (useful for "go to tool change position" moves).


GMOCCAPY Interface

DRO (Digital Readout)

The DRO has three display modes, toggled by clicking any axis value:

Mode Background Shows
Relative Black Position in current work coordinate system (G5x + tool offset + G92). This is what your G-code program sees.
Absolute Blue Machine coordinates (G53). Position relative to machine home.
DTG Yellow Distance To Go — remaining distance to the programmed endpoint during motion.

DRO digit colors indicate homing status:

  • Green = homed (reference established)
  • Red = unhomed (position is not trustworthy)

Touch-Off via the DRO

Click the axis letter (the "X", "Y", or "Z" label, not the number) to open a popup dialog. Enter the coordinate value you want the current position to represent (usually 0). This issues G10 L20 P0 <axis> <value> internally.

Offset Page

The Offset page (accessible from the notebook tabs) shows a table of all work coordinate systems (G54G59.3) plus G92 and tool offsets. The currently active system is highlighted.

  • Double-click a cell to edit a value directly. This issues G10 L2 P<n> <axis> <value> (sets the offset to the value you typed, NOT touch-off style).
  • "Zero G92" button: sends G92.1 to cancel G92 offsets.
  • "Set Active" button: switches the active coordinate system (e.g., click the G55 row, then "Set Active" to switch to G55).

Key distinction: Editing the offset page sets offsets with G10 L2 (absolute). Touching off via the DRO uses G10 L20 (calculated from current position). These are different operations.

Tool Page

Shows the tool table with columns for tool number, pocket, diameter, and Z offset.

  • Click a cell to edit. Changes are NOT live until you click "Apply Changes".
  • After applying, you must re-issue G43 (in MDI) if the active tool's offset changed. GMOCCAPY does not do this automatically.
  • The top of the page shows the currently loaded tool's active offsets (fed by the gmoccapy.tooloffset-x and gmoccapy.tooloffset-z HAL pins).

Tool Change Dialog

When a program executes M6, GMOCCAPY pops up a dialog showing the tool number and its description from the tool table comment. The operator physically changes the tool and clicks OK (or presses a physical confirm button wired to gmoccapy.toolchange-confirm).

Our config currently uses hal_manualtoolchange instead of GMOCCAPY's built-in dialog (wired in lagun.hal). The behavior is similar — a popup appears, operator confirms.

Auto Tool Measurement (not currently configured)

GMOCCAPY supports automatic tool length measurement using a fixed probe on the machine table. This requires:

  1. A [TOOLSENSOR] INI section with the probe's machine coordinates
  2. A [CHANGE_POSITION] INI section for safe tool-change position
  3. Remapping M6 to a change.ngc script that probes after each tool swap
  4. The probe input wired to motion.probe-input

When enabled, every M6 automatically: moves to the change position, swaps the tool, drives to the probe, measures the tool, stores the offset with G10 L1, and activates it with G43. This eliminates manual tool touch-off.

We don't have this set up yet, but it's a natural next step if a tool setter is installed on the machine.


Named Parameters for Tool Info

Parameter Value
#<_current_tool> Tool number in the spindle
#<_selected_tool> Tool number from last T word (before M6)
#5400 Same as #<_current_tool>
#5401#5409 Active TLO values (X through W)
#5410 Tool diameter of current tool (D column value)

About #<_td> in our macros

#<_td> is not a built-in LinuxCNC parameter. It is a user-defined global that our macros read for tool diameter. Programs must set it manually:

#<_td> = [3/16]   ; 3/16" endmill

A future improvement would be to replace #<_td> with #5410 (the built-in diameter parameter), but this requires proper tool table setup with correct D values and a T M6 G43 sequence before cutting.


Quick Reference

Full setup with tool change and cutter comp

G10 L1 P1 Z-2.5 R[1/4/2]   ; tool 1: Z offset and 1/4" endmill radius
T1 M6                        ; load tool 1
G43                           ; activate TLO
G41                           ; cutter comp left (uses tool 1's D from table)
F10
G1 X0 Y0                     ; lead-in (>= tool radius long)
G1 X2 Y0                     ; cut along edge
G40                           ; cancel comp (with lead-out move)
G0 X-1 Y-1

Touch off tool length

T1 M6                        ; load tool
; jog Z down until tool touches top of workpiece
G10 L10 P1 Z0                ; store: "this position = Z0"
G43                           ; activate the new offset

Touch off work zero

; jog to front-left corner of stock
G10 L20 P1 X0 Y0             ; set G54 origin here
; jog Z to top of stock
G10 L20 P1 Z0                ; set G54 Z origin here

Our current macro workflow

#<_td> = [1/4]                ; tell macros the tool is 1/4"
#<_z_top> = 0.05
#<_z_bot> = -0.25
#<_z_clearance> = 0.2

G10 L1 P1 Z0.0 R[1/4/2]      ; also set it in the table for cutter comp
T1 M6
G43
M03
F5

o<pocket_circ> call [0][0] [1.0] [0] [0]