SINUMERIK 840D: Calling Subprograms from Programmed Alarms

David Krause12 min read
Other TopicSiemensTechnical Reference
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

SINUMERIK 840D: Calling Subprograms from Programmed Alarms

Programmed alarms in SINUMERIK 840D sl (triggered by SETAL in the NC program or by a PLC request) cannot directly invoke a subprogram. The NCK scheduler rejects the nested program call because a part program or synchronous action is already active on the channel. This reference documents the workarounds that are field-proven on 840D sl with SINUMERIK Operate: persistent flag handling, SETINT/ASUB asynchronous subprogram triggering, and file-based state retention. The same patterns apply to SINUMERIK 828D and ONE controllers because the NC kernel and the SETAL/sync-action runtime are shared.

1. The Constraint: Why SETAL Will Not Call a Subprogram

The SETAL command raises a configured alarm number in the alarm buffer. The alarm handler runs in the alarm runtime context, not in the context of an NC part program. From the alarm handler the system is not permitted to start a separate subprogram because:

  • The channel interpreter is already executing the part program, a synchronous action, or an ASUB. Nested CALL instructions require the interpreter to be free to load a new program context, and the alarm path does not provide that.
  • The PLC is the only path that can request a program change asynchronously, and only through the FC9 / ASUP request interface, not through the alarm text processing.
  • Sync actions (WHEN ... DO) are evaluated in the IPO cycle. They can set flags, write R parameters, or trigger SETINT, but the DO block of a sync action cannot contain CALL, CALLPATH, or CALLBLOCK on a stock 840D sl build.

The user's symptom — "the sync action refuses to start a subprogram" — is therefore correct behaviour, not a misconfiguration.

2. What the NCK Allows from a Sync Action

Construct Allowed in Sync Action Notes
Assignment to R parameter Yes Local to the program unless declared GUD
Assignment to GUD Yes Persists across reset only if AP_INIT / AP_MEM attributes are set
SETAL Yes Triggers programmed alarm
SETINT Yes Arms an interrupt-driven ASUB
WRITE to file Yes Persistent across reset/NCK startup
CALL / CALLPATH No Rejected by interpreter
M function output Yes Can request PLC to start an ASUB via FC9

Source: SINUMERIK 840D sl Programming Manual (Fundamentals), 06/2019 Edition, Section 10 "Synchronized Actions" and SINUMERIK 840D sl Programming Manual (Job Planning), Section K1 "Flexible NC Programming".

3. The SETINT / ASUB Pattern

The accepted method to start a subprogram from an event detected in a sync action is the asynchronous subprogram (ASUB) path:

  1. Declare the ASUB routine in a separate program file (for example _N_ASUP_MPF or a manufacturer part program directory).
  2. Register the routine in machine data so the NCK knows which file is the interrupt handler. MD11620 $MN_ASUP_TEMPL_OB / MD11610 $MN_ASUP_EDITABLE are not required for the standard pattern; the SETINT(n) instruction names the interrupt number that is hard-wired to a default ASUB at compile time.
  3. From the sync action, raise SETINT(1) when the alarm condition is true. The NCK takes the IPO-to-IPO interrupt, saves the current program context, and starts the ASUB at the next IPO cycle.
  4. The ASUB runs to completion, then control returns to the interrupted part program.

3.1 Sync Action That Arms the Interrupt

DEF NCK INT _alarm_flag = 0

IDS = 1 EVERY $AC_PATH[0] == 0 AND $A_DBB[0] == 1 DO _alarm_flag = 1 SETINT(1)

The condition checks the actual axis position and a digital input byte from the PLC. When the alarm is to be raised, the sync action sets the local flag and primes the interrupt.

3.2 ASUB Program _N_ASUP_MPF

PROC ASUP SAVE
  ; Runs in interrupt context
  IF _alarm_flag == 1
    _alarm_flag = 0
    SETAL(65000, 1)   ; raise programmed alarm 65000 with channel 1
    ; perform the operator-defined response here
    ; (axis stop, spindle stop, custom M-code to PLC)
    M00                ; programmed stop; equivalent to halt request
  ENDIF
  RET

Notes on the SAVE attribute: the interrupt handler must save all R parameters, frames, and G codes that it modifies. The SAVE declaration in the PROC line forces the ASUB to allocate its own R parameter context, preventing leakage back into the calling part program.

4. Persistent State: R Parameters vs GUD vs File

The field report notes that "system variables are set to 0 when the machine is reset." This is correct for stock R parameters. The cure depends on how long the value must survive.

Storage Survives Reset Survives NCK Power Off Survives HMI Restart Scope
Local R parameter (R0..R99) No No No Program / ASUB
Global R parameter (R100+ via GUD) Yes (if AP_MEM) Yes (if AP_MEM) Yes Channel or NCK-wide
GUD file (/_N_DEF_DIR/_N_GUD_DEF) Yes Yes Yes NCK-wide
Local LUD / P variables No No No Program only
File via WRITE Yes Yes Yes Any file system path
NV variable ($A_*) No (mostly) No No Per-cycle

4.1 Defining a GUD That Persists

Open the GUD definition file in the NCK (path: /_N_DEF_DIR/_N_GUD_DEF) and add:

DEF NCK INT _alarm_state = 0    ;AP_MEM=1 implicitly via NCK scope
DEF NCK REAL _alarm_value = 0.0

Scope keywords (per the Programming Manual Fundamentals, Section 2.4):

  • DEF NCK — accessible from every channel, persists because the definition is in the NCK file system.
  • DEF CHAN — accessible from the declaring channel only.
  • DEF GLOB — same as NCK in modern builds.
Note: GUD persistence across NCK reset requires that the GUD file be backed up via the standard commissioning archive. The AP_MEM attribute applies to the value of a settable frame, not to the GUD definition file. Use the standard HMI archive path /card/sinumerik/nck to ensure values survive a control restart.

5. File-Based Persistence with WRITE and READ

When a value must survive even a control rebuild, write it to a file on the CFast card. The WRITE and READ instructions in the part program are part of the standard NC language and require no option (in contrast to EXECSTRING, which requires compile cycles).

DEF STRING[32] _path = "/_N_MPF_DIR/_N_ALARM_LOG_MPF"
DEF INT _rc

; --- write side (in the ASUB after SETAL) ---
WRITE(_error, _path, _rc)
  ; _error is the alarm number

; --- read side (in the next program start) ---
READ(_error, _path, _rc)
  IF _rc == 0
    ; apply _error
  ENDIF

File handling is documented in the Programming Manual Fundamentals, Section 12 "File Programming". The WRITE instruction requires a string expression and writes it as a single line; structured logging requires explicit formatting (for example, SPRINT to compose the line).

6. Why "Global Variables" in a Sync Action Can Fail

The field report states that the user could not get global variables working in a sync action. The most common cause is the location of the assignment. Sync actions execute under a slightly different symbol resolution path than the part program. If the global variable is defined as a DEF CHAN GUD, the channel context is implicit. If the GUD is declared in a definition file that is not loaded into the channel (missing access rights in the definition file), the sync action cannot see it.

Verify with the HMI menu Commissioning > NCK > GUD: the variable must appear with a non-red icon. If it shows red, the access level is wrong. Modify the ACCESS / REDDEF attributes in the GUD definition file:

DEF NCK INT _alarm_state = 0
ACCESS = RW   ; read-write from the part program
REDDEF = AS_ACCESSED   ; not reduced when read

For the sync action, the variable must be declared at the start of the part program file that contains the IDS block, or referenced fully qualified. See Programming Manual Fundamentals, Section 2.4 "User-Defined Variables (GUD)".

7. Complete End-to-End Example

The following builds a working pattern: the part program watches for an external alarm request, persists the alarm code to a GUD, raises the alarm, and on the next start the part program reads the file and clears the condition.

7.1 GUD Definition (/_N_DEF_DIR/_N_GUD_DEF)

DEF NCK INT _last_alarm = 0
DEF NCK REAL _last_alarm_time = 0.0
ACCESS = RW
REDDEF = AS_ACCESSED

7.2 Sync Action Block (top of the part program)

IDS = 1 WHENEVER $A_DBB[0] == 1 DO _last_alarm = 65000 SETINT(1)
IDS = 2 WHENEVER $A_DBB[0] == 0 DO _last_alarm = 0

7.3 ASUB Handler (/_N_CMA_DIR/_N_ALARM_ASUP_MPF)

PROC ALARM_ASUP SAVE
  DEF INT _rc = 0
  DEF STRING[64] _line
  IF _last_alarm <> 0
    _line = SPRINT("ALARM %d @ %f", _last_alarm, $AC_TIMER[1])
    WRITE(_line, "/_N_MPF_DIR/_N_ALARM_LOG_MPF", _rc)
    SETAL(_last_alarm, 1)
  ENDIF
  RET

7.4 Operator Acknowledgement Part Program

PROC ACK_ALARM
  DEF INT _rc = 0
  DEF INT _alarm = 0
  READ(_alarm, "/_N_MPF_DIR/_N_ALARM_LOG_MPF", _rc)
  IF _rc == 0 AND _alarm <> 0
    MSG("Last alarm: " << _alarm)
    _last_alarm = 0
    ; erase log file by writing empty line
    WRITE("", "/_N_MPF_DIR/_N_ALARM_LOG_MPF", _rc)
  ENDIF
  RET

Each step is fully supported on the stock 840D sl and 828D builds. The SPRINT formatter is documented in Programming Manual Job Planning, Section K5 "String Operations".

8. Alternative: PLC-Triggered ASUB via FC9

If the alarm is raised by a PLC condition rather than by NC code, the PLC can request an ASUB directly through the standard interface:

  • FC9 "ASUB" in the SINUMERIK PLC basic program: the PLC sets the request byte and the NCK starts the ASUB. The default ASUB is _N_ASUP_MPF in the manufacturer directory.
  • The PLC also writes the alarm number to a configured DB byte; the ASUB reads it and raises the alarm with SETAL.

This path is preferable when the alarm originates from a sensor the PLC already monitors, because it avoids polling the PLC in a sync action.

Reference: SINUMERIK 840D sl PLC Programming Manual, Section 3.6 "Asynchronous Subprograms (ASUBs)".

9. Verification Procedure

  1. Load the GUD file via HMI > Commissioning > NCK > GUD > Activate. The system reports "GUD file loaded".
  2. Set a write access password or accept the default access level for testing.
  3. In MDA mode, run IDS=1 alone (no part program) and check that the sync action does not raise an alarm — only sets the flag.
  4. Manually run SETINT(1) and verify that the ASUB is loaded and the alarm text appears on the HMI.
  5. Cycle NCK power; the GUD value must survive. Read with R_RVAR(1, _last_alarm) in the part program.
  6. Force an NCK reset (Commissioning > NCK > Reset (NCK)). Confirm that the file-based log still contains the alarm entry.

10. Troubleshooting Matrix

Symptom Likely Root Cause Fix
Alarm not raised on event Sync action not active because the part program is in a block without motion Move IDS definition to a globally active file (for example _N_GUD_DEF) or use DO with a non-zero condition
Alarm raised but no ASUB runs SETINT not armed; MD20150 G-code defaults block SETINT Set MD20150 $MC_GCODE_RESET_VALUES[0] = 0 or move SETINT outside the block where it is being reset
GUD value resets on NCK startup Definition file not archived; REDDEF blocks persistence Adjust GUD access attributes and run a full commissioning archive
Subprogram call still rejected from sync action Wrong interpreter path; CALL is fundamentally blocked in sync actions on the build in use Move the call into the ASUB; keep the sync action as the trigger only
WRITE to file returns error 18 Path does not exist or file is locked by HMI Check that the file directory is mounted; use the HMI to inspect the file
Alarm appears but the operator cannot clear it Alarm configured as "Clear by Reset only" in MD11415 Configure MD11415 $MN_ALARM_CLEAR_BEFORE_START to allow clear on program start

11. Field-Commissioning Tips

  • Keep the sync action side as small as possible — one assignment and one SETINT. All complex logic belongs in the ASUB.
  • Always declare SAVE on the ASUB's PROC line. Without it, the ASUB shares R parameters with the interrupted program and can corrupt the parent context.
  • Do not call CANCEL(1) from inside the ASUB; that would terminate the interrupted part program rather than return to it.
  • For test rigs that lack PLC, drive the sync action with a write to a system variable that you can change from the HMI: $A_DBB[0] is wired to the PLC by default but can be used as a test flag with care.
  • When the alarm must be cleared at NCK reset, combine the GUD value with the file-based log; the file is the only path that survives the most aggressive resets (for example, NCK general reset, part 5 of the Commissioning > Reset menu).

12. Summary of Constraints

  • SETAL cannot start a subprogram. It can only set the alarm number and text.
  • Sync actions can set state, write R parameters, and prime interrupts, but cannot call subprograms.
  • The supported path from a sync action to a subprogram is SETINT(n) → NCK interrupt → ASUB. The ASUB is a normal NC part program running in interrupt context.
  • For state that must survive reset, use GUD variables with the correct ACCESS and REDDEF attributes, or write to a file via the WRITE instruction.
  • For alarms originating in the PLC, use the FC9 ASUB request path rather than a sync action.

13. Frequently Asked Questions

Why does my sync action refuse to call a subprogram on SINUMERIK 840D?

Sync actions are evaluated in the IPO cycle and the language subset excludes CALL, CALLPATH, and CALLBLOCK. The interpreter rejects the instruction on every 840D sl and 828D build. Use SETINT(n) to trigger an asynchronous subprogram (ASUB) instead.

Which variable scope survives an NCK reset on a SINUMERIK 840D?

Local R parameters (R0–R99) reset to 0. Variables defined as DEF NCK in the GUD file (path /_N_DEF_DIR/_N_GUD_DEF) persist across reset and across NCK restart when the file is part of the standard commissioning archive.

How do I raise a programmed alarm from a sync action?

Use SETAL(alarm_number, channel) inside the DO block of the sync action. The alarm appears in the HMI alarm bar and the alarm log. The alarm number must be configured in the alarm text file /_N_CMA_DIR/_N_ALARM_TXT_MPF or in the manufacturer-specific configuration.

Can the PLC start an ASUB directly when an alarm condition is detected?

Yes. Use the standard PLC basic program block FC9 "ASUB". The PLC writes the request byte and the NCK starts the ASUB at the next IPO cycle. The ASUB can then call SETAL with the alarm number supplied by the PLC.

What is the difference between SETINT and a regular CALL in an ASUB?

SETINT(n) arms an interrupt and tells the NCK to start the ASUB associated with interrupt number n when the condition becomes true. A regular CALL requires the interpreter to be idle; SETINT works while the part program is running, making it the only valid way to branch from a sync action.

How do I make a value written from an ASUB visible to the next part program run?

Store the value in a GUD declared DEF NCK for channel-wide visibility, or use WRITE to a file under /_N_MPF_DIR or /_N_CMA_DIR for persistence across NCK reset. Read the value back with READ at the start of the next program.

Back to blog