Resolving SINUMERIK 840D Alarm 12550 _C97_NR Not Defined

David Krause15 min read
Other TopicSiemensTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Overview

SINUMERIK 840D controllers emit alarm 12550 ("Channel %1 Block %2 identifier %3 not defined or option not installed") when a defined GUD, macro, LUD, or program name is referenced in an NC block but is not present in the active scope. On a lathe retrofit running Cycle 95 / CYCLE97 thread-cutting, the alarm typically points at the channel-global array _C97_NR[11] declared in GUD7.DEF. The cycle cannot resolve a spindle-to-machine-axis mapping, so downstream calls into _C97_NR[n] fail with 12550 at NC-Start. This reference covers the diagnostic path for that specific failure, the machine-data checks that underpin it, and the recovery sequence for restoring CYCLE95 / CYCLE97 operation without reloading the entire cycle pack.

Siemens documents the general meaning of alarm 12550 in the SINUMERIK MC alarms catalog (SINUMERIK 840D sl / ONE). The catalog entry confirms that the alarm fires when a definable identifier (macro, GUD, LUD, program name, or program block) is referenced before it is defined, or when an option bit required for that identifier is not installed. The remediation logic described below resolves the most common field cases of the _C97_NR variant on 840DE retrofit hardware.

Alarm 12550 Reference

Field Value
Alarm number 12550
Alarm text (literal) Channel %1 Block %2 identifier %3 not defined or option %4 is not installed
Reaction NC-Start inhibit, alarm display, interface signals are not set
Acknowledgement RESET (clear alarm with NCK reset, not just C-Reset)
Cause class Error in the NC program / definition; configuration mismatch
Typical field triggers Missing GUD, missing macro, missing cycle file, unloaded GUD, missing option bit, protection level higher than user authorization
Cancellation block (C) Disables the block containing the undefined identifier so the operator can re-enter a corrected call

Per the Siemens alarms catalog, the 12550 family fires only on identifiers that should exist; it is not an MD validity check. The check is performed by the interpreter against the symbol table populated at NCK power-on and after any explicit GUD reload. If the symbol exists but the value the cycle reads is 0 or the array element is empty (REP of the wrong default), the alarm will still appear, because the cycle passes the empty element back to a higher-level statement that calls it without first verifying validity.

Hardware and Software Environment

Documented from a real 840DE retrofit case (lathe X/Z spindle, threading CYCLE95 / CYCLE97):

Item Article number / version
NCU NCU 571.3 — 6FC5357-0BB10-0AE1
NCK software 05.03.39 (840DE export line)
HMI / PCU PCU 50 — software 06.04.21
Standard cycles 06.04.21
Support cycles 06.04.24
Active cycle CYCLE95 (call) → CYCLE97 (SPF) in _N_CST_DIR
GUD file _N_GUD7_DEF in _N_DEF_DIR
Compatibility constraint: GUD definitions, cycle SPF/DEF versions, and NCK software are bound by the Siemens compatibility matrix. A GUD7.DEF issued with the 06.05.14.00 standard cycle pack (Dec 2004) is not necessarily compatible with NCK 05.03.39. Confirm that the DEF file timestamp (;CHANGE / ;VERSION lines) matches the standard cycle version on the CF card before modifying values.

The cycle file shown in the source contains the standard header banner ;VERSION: 06.05.14.00 Dec 07, 2004 while the loaded standard cycles on the controller are 06.04.21. Mismatched cycle/DEF versions are a frequent retrofit symptom: the user copies a newer CYCLE97.SPF from a development pack onto an older system. The interpreter then calls symbols whose GUD entries are not yet defined on the older NCK, which is the immediate trigger for 12550.

Root Cause Analysis

Three independent root causes converge on the same alarm text. Diagnose in this order:

  1. Empty spindle lookup table. CYCLE97 builds _C97_NR[] dynamically by scanning all configured machine axes and storing $MA_SPIND_ASSIGN_TO_MACHAX[Ax] for each spindle-capable axis. If the lathe has only one main spindle but the spindle-to-axis assignment in MD 30500 / 30550 / 30350 is missing or set to 0, the loop populates only _C97_NR[0] = 0 (the initial REP(0)). Subsequent statements that address _C97_NR[1..5] (e.g. for the counterspindle or the C-axis mapping) read a zero that was never written, and the interpreter raises 12550 on the GUD symbol referenced as the assignment target.
  2. GUD file not actually loaded. The DEF file is present on the CF card in user/_N_DEF_DIR/_N_GUD7_DEF but the active GUD set on the NCK is older. NCK reads the GUD set only at power-on or after an explicit PI service _N_GUD. A file-system update without an NCK reset is the most common field cause of "files are present, no data is visible in the parameter screen".
  3. Protection level. GUD definitions are stored under the current access level. The operator-level (level 4) and setup-level (level 3) parameter displays do not see definitions stored at the manufacturer (level 1) or service (level 2) level unless the password for that level is set. CYCLE97 reads _C97_NR at the protection level of the calling program (typically level 0 or 1), but the values defined in the GUD are written by the cycle at the access level of the active _C97_NR[0] = REP(0) statement. Mismatched levels cause the read to return an undefined symbol.

Diagnostic Procedure

  1. Confirm the alarm block. On the HMI, read the alarm screen and note the channel, block, and identifier. The third parameter of alarm 12550 is the symbol that the interpreter cannot resolve. In the source case it is _C97_NR (or _C97_NR[k] depending on the controller build). Compare the literal symbol against the symbol table.
  2. List GUDs from the HMI. Navigate to Startup > GUD (or Parameters > User Data depending on HMI build). Open GUD7 (channel-specific) and check that _C97_NR, _C97_AXNAM, and _C97 are listed with the expected data type and array size. If the entries are missing entirely, the GUD file is not active.
  3. Inspect the live value. From the same GUD screen, open _C97_NR[0] and read its value. A value of 0 indicates the cycle has just been initialized but has not yet populated the array. A value of 1, 4, or 5 indicates a real spindle number was assigned by $MA_SPIND_ASSIGN_TO_MACHAX.
  4. Check the active file system. Use HMI Startup > File System and confirm the active partition. On a 840DE the partition is normally /card/user/.... The expected path for the GUD definition is /card/user/_N_DEF_DIR/_N_GUD7_DEF and for the cycle /card/user/_N_CST_DIR/_N_CYCLE97_SPF.
  5. Read the cycle version banner. Open CYCLE97.SPF in the HMI editor. The first non-comment line should contain ;VERSION: and ;CHANGE: with a date. If the version date is newer than the loaded standard cycles (Startup > Version → Standard Cycles), you have a mixed version installation and the array layout in the DEF file may no longer match the cycle's expectations.
  6. Cross-check machine data. Verify MD30350 $MA_SPIND_ASSIGN_TO_MACHAX[AX1] and MD30350 $MA_SPIND_ASSIGN_TO_MACHAX[AX2]. Both must be non-zero for a lathe that uses one main spindle and one C-axis. A value of 0 for one of them causes the FOR loop in CYCLE97 to skip the affected index, leaving _C97_NR[1] = 0 and triggering 12550 on a later reference.
  7. Check option bits. Some cycles are option-gated on 840DE export systems. In Startup > Licenses > Options, confirm that the threading option (commonly listed as "Thread cutting") is enabled. A missing option shows up in alarm 12550's fourth parameter ("option %4 is not installed").

Machine Data Verification

The spindle-to-axis assignment is the most common single point of failure. The following MDs must be set in a coordinated way for CYCLE97 to populate _C97_NR correctly:

MD Name Typical value (lathe) Purpose
MD20070 $MC_AXCONF_MACHAX_USED[0..n] Machine axis number used in channel 1, 2, 3, 4 (one per configured axis) Declares which physical machine axes are present in the channel. CYCLE97 loops over this list to find spindles.
MD20080 $MC_AXCONF_CHANAX_NAME_TAB Channel axis name X, Z, SP, C Names the channel axes. CYCLE97 writes these into _C97_AXNAM[] after the spindle is found.
MD30350 $MA_SPIND_ASSIGN_TO_MACHAX[Ax] Spindle number assigned to machine axis 1 (main), 2 (counterspindle), 3 (C-axis) The CYCLE97 read source. If 0, the loop skips the axis.
MD30500 $MA_INDEX_AX_ASSIGN_POS_TAB Indexing axis assignment 0 (off) for non-C axes, 1+ for C axis Establishes whether an axis can act as a spindle when commanded as such.
MD30550 $MA_AXCONF_ASSIGN_MASTER_CHAN Master channel of axis 1 (current channel) Determines the channel ownership for the axis/spindle.
MD35000 $MA_SPIND_ASSIGN_TO_AC_AXIS Spindle assignment to AC axis 0 or 1 On drives with a 1:1 spindle-to-drive mapping, this is the deciding bit for CYCLE97.
MD38010 $MC_MM_NUM_SPINDLES Number of spindles 1 to 4 Allocates runtime memory for spindle structures. Must be ≥ the highest index used in 30350.

Read the live values with MD > Display MD on the HMI. For a retrofit on 840DE export, MD38010 is frequently left at the default 1 even when the mechanical scope includes a counterspindle. CYCLE97 then writes _C97_NR[1] = 0 (because no second spindle is allocated) and downstream blocks that address _C97_NR[1] raise 12550. Increasing MD38010 to 2 (or 3) and re-powering is the fix.

GUD File Verification

The GUD file GUD7.DEF declares the symbol table that the cycle writes into. The relevant block from the source case is:

;$PATH=/_N_DEF_DIR
;VERSION: 06.05.14.00 Dec 07, 2004
;CHANGE : 06.05.11.00 Oct 28, 2003
APR 11 APW 11
N10 DEF CHAN INT _ZSD[10]=0
N20 DEF CHAN REAL _C97[4]
N30 DEF CHAN INT _C97_NR[11]=SET(1,0,0,0,0,4,0,0,0,0,1)
N40 DEF CHAN STRING[8] _C97_AXNAM[5]=SET("C")
N50 DEF CHAN REAL _CONT2[10]
N51 DEF NCK INT _SC_MASK[10]=SET(0,0,0)
N300 REDEF $MC_TOOL_CARRIER_RESET_VALUE APR 7 APW 7

Three structural checks apply to this file:

  1. Attribute match (APR / APW). APR 11 APW 11 sets the read and write access level to 1 (manufacturer). The cycle's write statements are at the level of the running program. If the running program has access level 4 (operator) and the GUDs are at level 1, the cycle fails to write. The standard fix on a retrofit is to change APR/APW to 7 (operator read, operator write) or to match the calling program's level. The REDEF line for the tool carrier reset must also keep the new level (here APR 7 APW 7).
  2. Initial values. The SET(1,0,0,0,0,4,0,0,0,0,1) initializer primes the array with two non-zero entries (index 0 = 1, index 5 = 4) so the cycle has a valid starting point before the FOR loop overwrites the spindle entries. If this initializer is corrupted (e.g. truncated to SET(0,0,0,0,0,0,0,0,0,0,0)), the cycle cannot resolve _C97_NR[0] after the first overwrite pass.
  3. Array sizes. _C97_NR[11] matches an 11-slot layout expected by the CYCLE97 implementation at 06.05.14.00. A copy of an older or newer DEF file (e.g. 10-slot or 12-slot) desynchronizes the cycle's addressing and raises 12550 on slot 10 or 11. Re-extract the file from the matching standard-cycles archive before editing.

Cycle 97 Code Analysis

The interpreter block that drives the 12550 alarm is the spindle-search loop at the head of CYCLE97:

KK=0
_C97_NR[0]=REP(0)
_C97_AXNAM[0]=REP("")
_AXZAHL=$ON_NUM_AXES_IN_SYSTEM-1
SBLOF
FOR II=0 TO _AXZAHL
  JJ=$MC_AXCONF_MACHAX_USED[II]
  IF JJ<>0
    IF $MA_SPIND_ASSIGN_TO_MACHAX[AXNAME("AX"<<JJ)]<>0
      _C97_NR[KK]=$MA_SPIND_ASSIGN_TO_MACHAX[AXNAME("AX"<<JJ)]
      _C97_NR[KK+5]=JJ
      _C97_AXNAM[KK]=$MC_AXCONF_CHANAX_NAME_TAB[II]
      KK=KK+1
    ENDIF
    IF (KK>_SPIZAHL)
      GOTOF _END_SPISUCH
    ENDIF
  ENDIF
ENDFOR
_END_SPISUCH:

Two key observations from this block:

  • REP(0) and REP("") are valid initializers but the entries they write are *not* real spindle numbers. The block is intended to clear the array before the search. If the FOR loop never finds a valid $MA_SPIND_ASSIGN_TO_MACHAX value (because all the MD entries are 0), the array stays at REP(0). CYCLE97 then tries to assign _C97_NR[0] = 0 to a local variable of type INT, and the interpreter (depending on build) raises 12550 on the symbol because the runtime binding is "defined as zero, not undefined at this point".
  • SBLOF suppresses single-block stop inside the loop, so the alarm is reported against the calling program block (the CYCLE95 call), not against line SBLOF. The operator sees the alarm at the CYCLE95 call site, which is why the alarm message is reported as "_C97_NR not defined" even though the cycle 95 source is correct.

Resolution Procedure

  1. Back up the active GUD and the cycle file. In HMI Startup > GUD > Save to export the current GUD set. Use File System > Copy to copy CYCLE97.SPF and CYCLE95.SPF to a USB stick before any change.
  2. Verify machine data for the spindle assignment. Set MD30350 $MA_SPIND_ASSIGN_TO_MACHAX for the main spindle axis to 1, and for the C-axis (or counterspindle axis, if used) to 2 or 3 as applicable. If a second spindle is mechanically present, raise MD38010 $MC_MM_NUM_SPINDLES from 1 to 2 (or 3) so the runtime can address the extra index.
  3. Reload the matching DEF file. Copy the GUD7.DEF from the standard-cycles archive that matches the running cycle version (06.04.21). Do not edit the array initializers or the array sizes by hand unless the cycle is also updated. The file must reside at /card/user/_N_DEF_DIR/_N_GUD7_DEF.
  4. Adjust the access levels. In the DEF file header, change APR 11 APW 11 to APR 7 APW 7 (or to the access level of the calling program). The REDEF line for the tool carrier reset must be updated to the same level. Save the file on the HMI.
  5. Trigger an NCK reload. Either power-cycle the NCU (proper way) or use the HMI Startup > GUD > Activate to force a reload. The PI service _N_GUD executes the same effect without a power cycle but requires service-level access.
  6. Clear the alarm and test. Press NC-Reset to clear 12550, then run a dry motion in JOG on the spindle (no thread). Run a single CYCLE95 call with a short thread (e.g. 1 mm pitch, 1 mm thread length) to confirm _C97_NR[0] and _C97_NR[1] populate correctly. Read them back from Parameters > GUD > GUD7 — the values should now show 1 and 2 (or whatever the MD assignment is), not 0.

Verification and Commissioning

After the fix, run a verification matrix to confirm the cycle behaves across the lathe's operating envelope:

Check Expected behavior Pass criterion
NC-Start of CYCLE95 with valid thread parameters Cycle runs, 12550 does not appear No 12550 in the alarm history
Read _C97_NR[0..10] after CYCLE95 Index 0..n-1 populated with spindle numbers, rest zero Indices match the configured spindles
Read _C97_AXNAM[0..4] after CYCLE95 Names of the channel axes that carry a spindle Names match MD20080 entries
Thread pitch and depth from CYCLE95 parameters Output geometry matches the part program Thread profile measured to drawing tolerance
Override ramp on the spindle during threading Spindle speed is held, feed override inactive Override has no effect inside the thread (per Siemens thread-cutting rules)
Dry run with rapid retract Cycle returns to start without alarm Return position matches start; no 12550
Repeat the same CYCLE95 with multi-start threading NUMTH parameter honored Number of thread starts equals NUMTH
Safety: Threading is a spindle-synchronous operation. Before the verification run, set the spindle to a safe reference position and confirm the encoder reference point is set. A missing reference mark causes the cycle to read a wrong Z position for the thread entry and can crash the tool. After any GUD reload, re-reference all axes.

Related Cycles and Common Variants

Cycle Function Relation to _C97_NR
CYCLE95 (_N_CST_DIR/_N_CYCLE95_SPF) Contour turning with thread element support Calls CYCLE97 internally for the thread passes; the 12550 on "cycle 95" is often actually raised inside CYCLE97.
CYCLE97 (_N_CST_DIR/_N_CYCLE97_SPF) Thread cutting (single / multi-start, taper, run-in, run-out) Owns the _C97_NR array and the FOR loop that builds it.
CYCLE98 (_N_CST_DIR/_N_CYCLE98_SPF) Thread chaining (string of thread segments) Reads _C97_NR as a continuation; same dependency on spindle MDs.
CYCLE99 (_N_CST_DIR/_N_CYCLE99_SPF) Thread undercut / relief Reads _C97_AXNAM for tool-side geometry.
802D variant (_ktl_ alarm 12550) Similar CYCLE95 implementation on 802D / 802D sl Same root cause (GUD not loaded, MD not set, option bit missing) but the symbol is _ktl_ instead of _C97_NR.

For the 802D variant of the same failure, the symbol reported in alarm 12550 is _ktl_not (or _ktl_ followed by an index). The recovery sequence is the same: verify the GUD file is active, verify the spindle MD assignment, and verify the threading option bit. The 802D controller does not use the same DEF file naming, so do not copy a 840D GUD7.DEF across to an 802D platform — the GUD layout is different.

Troubleshooting Matrix

Symptom Likely root cause First check Fix
12550 on CYCLE95 call, symbol _C97_NR GUD not loaded HMI > GUD > GUD7 Re-copy GUD7.DEF, activate, NCK reset
12550 on CYCLE95 call, symbol _C97_NR[1] specifically MD38010 = 1, second spindle not allocated MD38010 value Raise MD38010, power-cycle
12550 on CYCLE95 call, symbol _C97_NR, array all-zero MD30350 = 0 for all axes MD30350 for AX1..AXn Set MD30350 to the spindle number for the spindle-capable axes
12550 with fourth parameter non-zero ("option not installed") Thread cutting option missing Startup > Licenses > Options Enable the threading option (license required)
12550 on 802D controller, symbol _ktl_not 802D-specific GUD _ktl_ not loaded 802D GUD editor Re-copy the 802D DEF, activate
12550 appears at the line after CYCLE95, not inside it SBLOF in CYCLE97 hides the source CYCLE97.SPF source Diagnostic only — fix the underlying MD / GUD issue, alarm site will follow
12550 clears on Reset but returns on every CYCLE95 call DEF access level too high for operator program APR/APW in DEF header Change APR/APW to 7 (operator) in GUD7.DEF
12550 only on multi-start thread (NUMTH > 1) Array size insufficient, or _C97_NR initial SET missing slots CYCLE97 / GUD7 version match Restore matching standard cycle and DEF pair

FAQ

What does SINUMERIK alarm 12550 with identifier _C97_NR mean on a lathe retrofit?

Alarm 12550 fires when CYCLE97 (called internally by CYCLE95 for thread passes) cannot resolve the channel-global array _C97_NR[11] declared in GUD7.DEF. The most common cause is that the GUD file is not active on the NCK, or that MD30350 $MA_SPIND_ASSIGN_TO_MACHAX is 0, so the FOR loop inside CYCLE97 leaves the array empty.

How do I confirm that GUD7 is active on the NCK?

Open HMI > Startup > GUD, select the channel, and look for _C97_NR, _C97_AXNAM, and _C97. If the entries are missing, copy GUD7.DEF from the matching standard-cycles archive into /card/user/_N_DEF_DIR/ and trigger an NCK reset (or use the GUD Activate PI service with service-level access).

What machine data controls the spindle-to-axis mapping that CYCLE97 needs?

MD30350 $MA_SPIND_ASSIGN_TO_MACHAX is the decisive entry. It must be set to 1, 2, 3, or 4 for each machine axis that carries a spindle. MD20070 $MC_AXCONF_MACHAX_USED, MD20080 $MC_AXCONF_CHANAX_NAME_TAB, and MD38010 $MC_MM_NUM_SPINDLES are the supporting entries; raise MD38010 to at least the number of spindles the lathe actually has.

Why does alarm 12550 point at CYCLE95 even though the error is in CYCLE97?

CYCLE97 starts with the SBLOF (suppress single-block) command and the alarm is raised at the next interpreter check, which is the calling block in the part program (the CYCLE95 call). The alarm site therefore always reads as "cycle 95 block _C97_NR" even though the offending line is inside cycle 97.

Can a missing option bit cause alarm 12550 with identifier _C97_NR?

Yes. The fourth parameter of alarm 12550 reports the option bit number when the referenced identifier is option-gated. Thread cutting is an option on some 840DE export configurations. Enable the threading option in Startup > Licenses > Options and re-test. The 12550 catalog entry in the Siemens SINUMERIK MC alarms documentation confirms this is a valid trigger for the alarm.

Back to blog