SINUMERIK 840D Tool Offset Check: Pre-Machining Limit Setup
SINUMERIK 840D controllers can validate tool length and tool diameter against user-defined upper and lower limits before a machining cycle executes. Three implementation paths exist on the platform: built-in Siemens measuring cycles (CYCLE971 / CYCLE977 / CYCLE982), the SINUMERIK Tool Management wear and life monitor, or a custom subprogram (SPF) wired to a free M function through machine data MD10715 and MD10716. This reference covers the third path end to end, the syntax errors that surface when the M call carries parameters, and the "level of nesting exceeded" alarm that appears when the SPF file structure is wrong.
Why a Pre-Machining Tool Offset Check Matters
Tool length offset (TLZO) and tool radius offset (TRC) are the two geometry components the controller applies to every linear and circular move. The geometry length is the difference between the spindle nose reference and the tool tip measured along the spindle axis at a calibrated reference; the radius compensates for the diameter written into the cutting edge geometry. If the offset drifts due to a missing offset number, a wrong D word, a manual edit error, or an operator entering the wrong value after a regrind, every G1 / G2 / G3 move on the part will be off by the same delta — and the controller will not raise a warning unless an explicit check is added. The Autodesk Machining Fundamentals: Tool Length Offset reference covers the mechanical definition in detail. The Siemens application note How to Measure Tool Offset in Milling walks through the HMI "Measure Tool" softkey sequence (Cycle Start after the work offset and CW spindle direction are set).
A pre-machining check is especially important on 5-axis machines where length compensation along the tool vector is non-trivial, on production lines that run unattended for hours, and on shop floors where operators manually enter offsets between cycles. The check returns the controller to a safe state with a defined alarm if the offset falls outside the tolerance band, instead of cutting a scrapped part.
Three Methods to Compare
| Method | Hardware needed | Setup effort | Limit granularity | Auto-rejects | Best fit |
|---|---|---|---|---|---|
| Siemens measuring cycles (CYCLE971/977/982) | Touch probe or reference block | Low (HMI-driven) | Measured vs. expected | No (writes new value) | Mills with calibrated probe |
| Tool Management (wear / life) | None (uses $TC_MOPx) | Medium (MD18080+) | Per-tool wear and life | Yes (alarm 6450 / 6451) | Magazine-equipped cells |
| Custom M-call SPF | None | Medium (MD10715+10716+10717, SPF) | Any user-defined window | Yes (SETAL 61000+) | Custom limit logic, no probe |
Prerequisites
- SINUMERIK 840D sl with HMI Oper or HMI Advanced; SW 4.4 or later for the MD10715 / MD10716 / MD10717 substitution block to be valid.
- Access level "Manufacturer" or higher to write MD10715 / MD10716 / MD10717.
- A free M function (e.g., M7, M70, M99) not already assigned by the machine builder or PLC.
- NCK file system access to write into the path declared in MD10718 (default /_N_CUS_DIR/).
- Active tool offset memory with valid $TC_DP1..$TC_DP25 entries for the spindle tool ($AC_TOOL_ACT).
- Available user alarms in the 61000–61999 range (reserved for user cycles).
Method 1: Siemens Measuring Cycles
The fastest route for shops that have a calibrated touch probe or a fixed reference block is to use Siemens measuring cycles from the standard cycle directory:
- CYCLE982 – calibrate the reference tool to a known reference block; writes $TC_DP3 / $TC_DP4 / $TC_DP5.
- CYCLE971 – measure tool length with a workpiece probe touching the tool.
- CYCLE977 – measure tool radius / diameter and write $TC_DP6 / $TC_DP7.
The "Measure Tool" softkey in the HMI offsets menu drives these cycles and writes the measured value back into the active geometry length. See the Siemens application note How to Measure Tool Offset in Milling for the softkey sequence. Tool length offset basics are described in the Autodesk Tool Length Offset reference.
The measuring cycles overwrite the offset, they do not reject the tool if it falls outside a tolerance. To add a tolerance reject, wrap the cycle call in an IF block that compares the previous value with the new value, or chain to the custom SPF described in Method 3.
Method 2: SINUMERIK Tool Management
If a tool magazine is configured ($TC_MAP1..$TC_MAP64, $TC_MPP1..$TC_MPP6), Tool Management already monitors wear limits and life. Set per-tool:
- $TC_MOP5[t] – wear setpoint (cumulative allowable wear in mm or minutes, depending on the time / count switch).
- $TC_MOP6[t] – wear limit (alarm raised when wear reaches this value).
- $TC_MOP11[t] – tool life in minutes.
- $TC_MOP13[t] – tool life counter.
Tool Management is enabled through the MD18080 to MD18099 block (the exact MD count varies by SW version; check the BOM for your SW). When the accumulated wear crosses $TC_MOP6 or the life crosses $TC_MOP11, the controller raises alarm 6450 "Tool wear limit reached" or 6451 "Tool life reached" before the next tool use. The alarm appears during tool change prep, not during the cutting move, which is the expected place to intercept a bad tool. The user can wire PLC logic to acknowledge and continue, swap the tool, or stop the program.
Method 3: Custom M-Code Subprogram — Implementation
For shops that want a single M-call inside the machining program (e.g., M99(nominal, offset, limit)) to validate length or radius against limits without invoking a measuring cycle, write a parametric SPF and tie it to an M function through machine data. This is the path that produces the syntax and nesting alarms discussed in the rest of the article.
Step 1 — Select a Free M Function
Confirm the M function is unused by the PLC and not already mapped to a cycle by MD10715. The substitution table supports 10 M functions (indices 0 through 9):
MD10715 $MN_M_NO_FCT_CYCLE[0..9] ; M number that triggers the cycle call
MD10716 $MN_M_NO_FCT_CYCLE_NAME[0..9] ; program name without _N_ prefix and without .SPF
MD10717 $MN_M_NO_FCT_CYCLE_PAR[0..9] ; parameter count expected on the M call (0..10)
MD10718 $MN_M_NO_FCT_CYCLE_FILE ; default "_N_CUS_DIR" — search path
MD10719 $MN_M_NO_FCT_CYCLE_FILE_EXT ; default "SPF" — file extension
Pick an index whose M value is free (often M7 if the controller does not use it for coolant, or any user range M70–M99). MD10717[n] must match the number of parameters in the SPF's PROC block; set it to 0 for a parameter-free check.
Step 2 — Write the Check Subprogram
Save the file on the NCK file system at the path declared in MD10718 (default /_N_CUS_DIR/_N_CHECK_OFFSET_SPF). The mandatory header line uses the exact name declared in MD10716 (without the _N_ prefix and without the .SPF extension).
%_N_CHECK_OFFSET_SPF
;$PATH=/_N_CUS_DIR
; SPARAM: NOM, OFFS, LIM
DEF REAL _NOM = NOM
DEF REAL _OFFS = OFFS
DEF REAL _LIM = LIM
IF ABS(_OFFS - _NOM) > _LIM
; out of tolerance — raise user alarm 61000
SETAL(61000, _OFFS)
ENDIF
RET
The geometry length reads from $TC_DP3 (length 1), $TC_DP4 (length 2), or $TC_DP5 (length 3) depending on the active cutting edge type. The radius reads from $TC_DP6. Wear accumulates in $TC_DP12..$TC_DP15. The tool number is $TC_TPN (or $AC_TOOL_ACT for the active spindle tool) and the active D-word is $TC_DPCE.
Step 3 — Assign the M Function
Write the machine data on the controller:
MD10715[0] = 99 ; M function number
MD10716[0] = "CHECK_OFFSET" ; subprogram name (without _N_ prefix, without .SPF)
MD10717[0] = 3 ; number of call parameters expected (0..10)
MD10717 specifies how many call parameters the controller passes into the SPF's PROC block. With MD10717[0] = 3 the call M99(nom, offs, lim) is supported.
Step 4 — Call from the Machining Program
N10 T="DRILL_8" D1
N20 M6
N30 M99(125.000, $TC_DP3[$TC_TPN,$TC_DPCE], 0.050) ; nominal 125 mm, length, ±0.05 mm
N40 G0 X0 Y0 Z100
N50 G1 Z-5 F200
...
If the offset is outside the ±0.05 mm band, alarm 61000 fires before the G1 move. The alarm halts the program, leaves the spindle at the last safe position, and is cleared only by an operator acknowledge.
Variant — Diameter Check (Radius)
%_N_CHECK_RADIUS_SPF
;$PATH=/_N_CUS_DIR
; SPARAM: NOM_R, LIM_R
DEF REAL _NOM_R = NOM_R
DEF REAL _ACT_R = $TC_DP6[$TC_TPN,$TC_DPCE]
DEF REAL _LIM_R = LIM_R
IF ABS(_ACT_R - _NOM_R) > _LIM_R
SETAL(61001, _ACT_R)
ENDIF
RET
MD10715[1] = 98
MD10716[1] = "CHECK_RADIUS"
MD10717[1] = 2
Reserve a different alarm number per check type so the operator message shows which offset class failed.
Inline Workflow Diagram
Common Faults and Fixes
Syntax Fault on M99(nom, offs, lim)
The first error class is a syntax alarm when the M call carries a parameter list. MD10715 / MD10716 substitute the M number with the cycle name; the substitution parser does not allow expression parameters on the M line. The M function will be called with the listed parameters only if MD10717 declares the count and the parameters are scalar identifiers, not expressions.
Symptoms: Alarm 14011 "Statement not recognized" or alarm 12550 "Name not defined".
Fix — Option A (rename to a cycle): Rename the SPF to a free CYCLE### number and call it via the cycle call parser, which does accept expressions:
%_N_CYCLE995_SPF
...
RET
N30 CYCLE995(125.000, $TC_DP3[$TC_TPN,$TC_DPCE], 0.050)
Fix — Option B (GUD parameters): Store the parameters in global user data variables before the M call and read them inside the SPF:
DEF NCK REAL _AC_CHECK_NOM, _AC_CHECK_OFFS, _AC_CHECK_LIM
...
N25 _AC_CHECK_NOM=125.000 _AC_CHECK_OFFS=$TC_DP3[$TC_TPN,$TC_DPCE] _AC_CHECK_LIM=0.050
N30 M99
This decouples the M-line syntax from the parameter passing.
Nesting Depth Exceeded (Alarm 6510 / 65100)
The second error class is "level of nesting exceeded" appearing immediately after the syntax fix. Causes:
- The .SPF file header does not match the name declared in MD10716.
- The ;$PATH= directive is missing or wrong (controller cannot resolve the cycle and falls back to recursive lookup).
- The SPF body calls macros, ASUBs, or other subroutines in a chain deeper than the NCK limits.
- The file ends with M17 or M30 instead of RET (the substitution treats M17 as a fresh subroutine entry and re-enters the lookup).
Fix: Confirm the header line is exactly:
%_N_CHECK_OFFSET_SPF
;$PATH=/_N_CUS_DIR
Even one byte difference between the filename, the program name in MD10716, and the header line "%_N_..._SPF" causes the substitution mechanism to fail and the controller falls back to recursive call logic, which then hits the depth limit.
The exact alarm number depends on SW version: 840D SW 4.x raised alarm 6510; 840D sl SW 2.6+ raises alarm 65100 "Channel %1 nesting depth for macro calls exceeded".
Tool Offset Variable Not Populated
If $TC_DP3 evaluates to zero inside the SPF, the active cutting edge and tool are not yet valid when the check runs. The substitution runs immediately at the M line, which is before any subsequent positioning move but after the M6 in the same block. Read the offsets only after a T selection and before any positioning move that would change $AC_TOOL_ACT:
N5 T="DRILL_8" D1
N6 M6
N7 M99(125.000, $TC_DP3[$TC_TPN,$TC_DPCE], 0.050)
N8 G0 Z100
If the T and M6 are in different blocks from the M99, add a STOPRE between them to ensure synchronous decoding.
Permission Error on File Write
Alarm 10060 "Permission error" appears when the protection level on the cycle directory forbids the write. Confirm the CUS_DIR access level is set to the level matching the logged-in user (configured through the Oper setup menu under Files > Custom Cycles > Properties). The default is level 4 (Service), which requires the service password.
PLC Decodes the M First
If the PLC has a high-priority M-decoder that reacts to the chosen M number (M99 is commonly used as "subprogram end" by many post-processors), the M function never reaches the substitution table. Cross-check the PLC program (FB1 / FB2 in the standard PLC) for an M-decoder and either change the M number, or set the substitution priority in MD10715[0] to a higher value than the PLC priority.
Wrong MD10717 Parameter Count
If MD10717[0] is set to 0 but the SPF signature uses three parameters, the substitution passes zero parameters and the SPF reads garbage from the stack. Conversely, if MD10717[0] = 3 but the call line only has two parameters, the substitution fails silently and the cycle does not run. Always match MD10717[n] to the SPF's PROC parameter count and to every call site.
Verification
- Switch the controller to MDA, type the M99 call with the offset inside tolerance, press NC Start. The line must execute without alarm.
- Edit $TC_DP3 to a value 5 mm outside the tolerance window in the offset list, re-issue the M99 call — alarm 61000 must appear before any subsequent G1 motion. Clear the alarm and restore the value.
- In the HMI diagnostics (Diagnosis → Service Displays), read $TC_DP3, $TC_DP6, $TC_MOP5, $TC_MOP6 to confirm the values the SPF compared against.
- Enable a trace in /_N_MPF_DIR/_N_CHECK_LOG_SPF to log _NOM, _OFFS, _LIM on each call. Look at the trace after a full part program run.
- Reset MD10715 / MD10716 / MD10717 to defaults and verify the original M function behavior is restored before production release.
- Power-cycle the NCK to confirm the substitution persists (it must, as MD10715 is a general machine data, not a reset-dependent setting).
- Run a complete dry-run part program with all expected tools loaded; confirm each tool passes the check on first use.
Parameter Reference Table
| Machine Data | Name | Default | Meaning |
|---|---|---|---|
| MD10715 $MN_M_NO_FCT_CYCLE[0..9] | M function for cycle | −1 | M number that triggers the cycle call |
| MD10716 $MN_M_NO_FCT_CYCLE_NAME[0..9] | Cycle program name | "" | Program name without _N_ prefix and without .SPF |
| MD10717 $MN_M_NO_FCT_CYCLE_PAR[0..9] | Parameter count | 0 | Number of parameters expected on the M call (0..10) |
| MD10718 $MN_M_NO_FCT_CYCLE_FILE | Cycle file path | "_N_CUS_DIR" | Search path for the cycle subprogram |
| MD10719 $MN_M_NO_FCT_CYCLE_FILE_EXT | Cycle file extension | "SPF" | File extension appended to the program name |
| MD20090 / MD20095 | Reserved M / G numbers | site-specific | M and G functions reserved by the machine builder |
| MD18080 (block) | Tool management MDs | – | Enables Tool Management and wear/life monitoring |
| MD20150 $MC_GCODE_RESET_VALUES[2] | G49 / G43 reset state | 49 | Set to 43 if ALC should remain active after reset |
Tool Offset Variable Reference
| System Variable | Meaning | Typical Unit |
|---|---|---|
| $TC_DP1[t,d] | Tool type (drill, mill, tap, ...) | – |
| $TC_DP2[t,d] | Cutter position | – |
| $TC_DP3[t,d] | Length 1 (geometry) | mm |
| $TC_DP4[t,d] | Length 2 (geometry) | mm |
| $TC_DP5[t,d] | Length 3 (geometry) | mm |
| $TC_DP6[t,d] | Radius (geometry) | mm |
| $TC_DP7[t,d] | Corner radius (geometry) | mm |
| $TC_DP12[t,d] | Wear length 1 | mm |
| $TC_DP13[t,d] | Wear length 2 | mm |
| $TC_DP15[t,d] | Wear radius | mm |
| $TC_MOP5[t] | Wear setpoint | mm or min |
| $TC_MOP6[t] | Wear limit (alarm threshold) | mm or min |
| $TC_MOP11[t] | Tool life setpoint | min |
| $TC_MOP13[t] | Tool life counter | min |
| $TC_TPN | Active T number | – |
| $TC_DPCE | Active D (cutting edge) number | – |
| $AC_TOOL_ACT | Active spindle tool number | – |
Alarm Code Reference
| Alarm | Text (typical) | Cause | Action |
|---|---|---|---|
| 14011 | Statement not recognized | Parser cannot resolve M-call expression | Use cycle call or GUD-passed parameters |
| 12550 | Name not defined | Subprogram name mismatch | Confirm MD10716 matches header |
| 6510 / 65100 | Nesting depth exceeded | Recursive cycle substitution | Fix header / RET; reduce nesting |
| 10060 | Permission error | Write access level too low | Raise access to CUS_DIR |
| 61000 (user) | Tool offset out of limits | |Δ| > lim | Operator decision — replace or override |
| 61001 (user) | Tool radius out of limits | |Δ| > lim | Operator decision — replace or override |
| 6450 | Tool wear limit reached | $TC_MOP6 exceeded | Swap tool, reset $TC_MOP5 |
| 6451 | Tool life reached | $TC_MOP11 exceeded | Swap tool, reset $TC_MOP13 |
Field-Commissioning Checklist
- Confirm the M function is unused by the PLC; cross-check FB1/FB2 in the standard PLC program (M-decoders).
- Confirm the file lives on the CF card or NCU local FS at the path set in MD10718 (default /_N_CUS_DIR/).
- Confirm protection level: SINUMERIK Oper set to read-only on _N_CUS_DIR silently fails the substitution with alarm 10060.
- Confirm ALC (Automatic Length Compensation) is enabled if you compare measured vs nominal length (MD20150 $MC_GCODE_RESET_VALUES[2] = 1).
- Confirm SETAL numbering is unique. 61000–61999 are reserved for user cycles; do not clash with standard alarms 6000–7999.
- Confirm file permissions on the .SPF allow overwriting. The factory default _N_CUS_DIR is writable at access level 4 (Service).
- Verify the SW version with the HMI version screen; confirm the MD names match the installed SW (some legacy 840D variants use different MD numbers).
- Back up the original MD values to /_N_CST_DIR/ before changes so a single Reset can restore.
- Run a full-tool dry-run before the first part; confirm every tool either passes the check or generates a controlled alarm.
- Document the M-number-to-check mapping in the operator-facing work instructions so the alarm message is unambiguous on the shop floor.
Static vs Parametric Substitution
| Feature | Static (MD10717 = 0) | Parametric (MD10717 > 0) |
|---|---|---|
| Call form | M70 | M99(p1, p2, …) |
| Parameter parsing | None | Scalar identifiers only |
| Use case | Always-on monitoring | Per-tool / per-feature limits |
| Common failure | PLC decoder conflict | Syntax alarm on expression in call |
| SPF signature | Empty PROC | PROC(N1, N2, …) |
| Best fit | Generic safety check | Tight tolerance machining |
Safety and PLC Integration
Pre-machining offset checks should be wired to the PLC in two additional places beyond the NCK alarm: a feed-hold output that pauses the spindle if the alarm is acknowledged-and-continued, and a parts-counter gate that increments only after a successful check. The PLC inputs to monitor are:
- DB21.DBX6.0 — feed hold request from NCK alarm path.
- DB21.DBD26 — active alarm number, low byte.
- DB21.DBB4 — channel status word (NCK → PLC).
Add the user alarm 61000 to the PLC alarm mask so the operator HMI displays the tool number, current offset, and tolerance limit. The standard Siemens PLC library includes FB2 for M-decoder and FB7 for axis monitoring; both are accessible to the integrator through the standard machine PLC.
FAQ
Why does my M99(nom, offs, lim) call raise a syntax alarm on SINUMERIK 840D?
The M-function substitution configured in MD10715/MD10716 replaces the M word with the cycle program name but does not allow a parameter list with expressions on the M line. Use a CYCLE### name called via CYCLE###(a,b,c) or move the parameters into GUD variables before the M call.
How do I get MD10715 and MD10716 to actually load my check subprogram?
Set MD10715[n]=99, MD10716[n]="CHECK_OFFSET", MD10717[n]=3, and save the file as /_N_CUS_DIR/_N_CHECK_OFFSET_SPF. The header line "%_N_CHECK_OFFSET_SPF" plus ";$PATH=/_N_CUS_DIR" must match exactly, and the file must end with RET.
What causes "level of nesting exceeded" after the subprogram name is corrected?
It is almost always a mismatch between the .SPF file header and the name in MD10716, or a chain of macro/cycle calls deeper than the NCK limit. Confirm the header, the path directive, and the RET close, then reduce nested calls.
Can the controller check tool wear limits without writing a subprogram?
Yes. With Tool Management active (MD18080 block), set $TC_MOP5 (setpoint) and $TC_MOP6 (limit) per tool and the controller raises alarm 6450/6451 automatically when the accumulated wear or life crosses the limit.
Which Siemens cycles measure tool length and diameter?
CYCLE982 calibrates the reference tool, CYCLE971 measures tool length with a workpiece probe, and CYCLE977 measures tool radius/diameter. They are invoked from the HMI "Measure Tool" softkey or directly in the part program.