Siemens 840D: Persisting User Variables via R-Parameters and GUD
This technical reference covers how to retain calculated user variables on a SINUMERIK 840D / 840D sl controller after power-off, how to pass values between a main program (MPF) and a subprogram (SPF), and how to avoid the common pitfalls of R-parameter overwrite by built-in cycles. Working code samples and a troubleshooting matrix are included for shop-floor deployment.
1. The Variable Persistence Problem on SINUMERIK 840D
A user-defined variable such as DEF REAL Xmom exists only inside the runtime of the program that declared it. When the controller is switched off, the SRAM/NV-RAM image of LUD (Local User Data) and most volatile workspace is lost. If a calculation such as
DEF REAL Xmom = 50
DEF REAL Xstep = 10
Anfa: G1 X=Xmom
Xmom = Xmom + Xstep
IF Xmom < 500 GOTOB Anfa
ENDIF
is interrupted, the next program start re-initializes Xmom to 50. To bridge the gap you need a storage class whose value survives a power cycle and that the NCK writes back to NV-RAM. Three mechanisms are available on every 840D:
- R-parameters (R0…R99, optionally extended to R0…R299) — volatile, but re-loaded at NCK startup from a configurable NV-RAM area.
- GUD (Global User Data) — globally declared, NV-RAM-backed, persistent across NCK reset and power-off.
- Machine data / Setting data ($MN_, $MC_, $SN_, $SC_) — permanent and protected by access level.
File-based persistence via SAVE / READ is also possible and is described in §6.
2. Variable Classes at a Glance
| Class | Scope | Lifetime | Typical Use |
|---|---|---|---|
| LUD (Local User Data) | Current program only | Until reset / M30 | Loop counters, scratch values |
| GUD (Global User Data) | All programs, all channels | NV-RAM persistent | Setup values, counters, offsets |
| R-parameters | Channel-global (R0…R99) | NV-RAM persistent (with configuration) | Legacy Heidenhain-style math, cycle parameters |
| Setting data $SC_ / $SN_ | Channel / NCK | NV-RAM persistent | Operator-tuned values (e.g. dry-run feed) |
| Machine data $MC_ / $MN_ | Channel / NCK | NV-RAM, password-protected | Commissioning values, fixed configuration |
Source: Siemens Industry Online Support — SINUMERIK 840D sl Programming Manual (Basics), section "Variables and arithmetic parameters".
3. R-Parameters (R0..R99, Extended to R299)
3.1 Why R-Parameters Exist
R-parameters are floating-point arithmetic variables numbered R0 through R99 (the default MD28050 MM_NUM_R_PARAM = 100). Setting MD28050 up to 300 widens the range to R0..R299. They pre-date LUD/GUD and exist mainly to support cycles that need parameters without explicit DEF declarations.
3.2 Scope and Volatility
Although R-parameters live in the channel's working memory, on a SINUMERIK 840D they are part of the persistent NCK data set. Their values survive RESET and power-off, provided MD11250 $MN_PROTOC_FILE_MEM[1] is not configured to log them out. After NCK ramp-up the previous values are available again.
3.3 Risks When Mixing R-Parameters with Cycles
The decisive problem: many standard cycles (CYCLE81 drilling, CYCLE82 drilling/dwell, POCKET3, etc.) use R-parameters internally as transfer parameters. The cycle read routine overwrites R1, R2, ... with whatever the user typed in the cycle mask. If you happen to use R10 as your own running counter, calling CYCLE81(...) silently corrupts it.
Mitigation: never use R-parameters that the cycle definitions reference. The standard mask of cycle defaults targets R0–R25 for argument return values; keep your own math in R30…R99 (or R100…R299 if extended).
3.4 Reading and Writing R-Parameters
R10 = 100.5 ; direct assignment
R11 = R10 * 2 ; arithmetic
IF R11 > 200 GOTOB LABEL1
G1 X=R10 F=R11
R-parameters require no DEF line. This is convenient but also the reason they are easy to misuse — the compiler cannot warn you that a cycle is about to clobber them.
4. GUD — Global User Data for NV-RAM Persistence
GUD is the modern, type-safe equivalent of R-parameters. Define once, use everywhere, persisted in NV-RAM.
4.1 Declaration in a _N_GUD_DEF File
GUD is defined in a dedicated definition file under the NCK's global directory:
; File: _N_GUD_DEF
; Path: /NCK/Definitions/GUD.DEF
DEF NCK INT _GUD_COUNT = 0
DEF NCK REAL _GUD_XMOM = 50.0
DEF NCK REAL _GUD_XSTEP = 10.0
DEF NCK BOOL _GUD_RUN = TRUE
The leading underscore is a Siemens convention marking the variable as system-related and requiring the appropriate access level (typically Manufacturer for NCK scope). Loader via HMI Advanced → Commissioning → User Data, or via CF card / network share.
4.2 Accessing GUD from a Part Program
; File: _N_MPF_DIR/_N_MAIN_MPF
DEF REAL XmomLocal
XmomLocal = _GUD_XMOM
G1 X=XmomLocal F500
_GUD_XMOM = XmomLocal + _GUD_XSTEP
IF _GUD_XMOM < 500 GOTOB LABEL1
_GUD_RUN = FALSE
Because _GUD_XMOM lives in NV-RAM, the next cold-start resumes the program at the correct counter value.
4.3 Scope Prefixes
| Prefix | Scope | Visibility |
|---|---|---|
DEF NCK |
NCK-global | All channels, all modes |
DEF CHAN |
Channel-global | All programs in this channel |
DEF SPD / DEF LOC
|
Spindle / local | Limited |
For the persistence problem on a single channel, DEF CHAN is sufficient and faster to access.
5. Machine Data and Setting Data
For values that must be permanently protected from operator change, use machine data:
$MC_GUD_XMOM = 200.0 ; channel-specific GUD-like setting
$MN_GUD_XSTEP = 10.0 ; NCK-global
Settings data ($SC_, $SN_) is closer to operator-tunable. Both are NV-RAM-backed and survive a power cycle. Access level is enforced: a standard operator may not write $MN_, but read access on $SN_ is normally free.
Reference: SINUMERIK 840D sl Function Manual "Axes and Spindles", sections on machine and setting data layout.
6. SAVE / READ — File-Based Persistence
For larger record sets or machine-tool-builders who want CSV-style logging, the NCK supports binary save/read via SAVE and READ:
DEF REAL Xmom = 200.0
DEF REAL Xstep = 10.0
SAVE(1, "Xmom=", Xmom)
SAVE(1, "Xstep=", Xstep)
At startup in the program header / initialization block:
DEF REAL Xmom
DEF REAL Xstep
IF ISFILE("//NC/MPF.DIR/CNC.DAT")
READ(1, "Xmom=", Xmom)
READ(1, "Xstep=", Xstep)
ENDIF
The file path uses Siemens' logical NC identifier. SAVE/READ write a plain-text line per value, which is easy to inspect and modify on a PC. Memory cost is small but every SAVE touches the file system, so avoid calling it in tight loops.
SAVE opens the file in append mode by default. Use DELETE before SAVE if you want a clean snapshot. Or use SAVE(1,"Xmom=",Xmom,"//NC/MPF.DIR/CNC.DAT") with explicit overwrite.7. Subprogram Parameter Passing
7.1 The Three Methods
-
Call with explicit parameter list — formal parameters declared in the subprogram header (
PROC UP1(REAL Xmom, REAL Xstep)). - Call without parameter list — subprogram reads the channel-global LUD/GUD/R-parameters directly. Side-effect risk: the subprogram's writes are visible in the caller.
-
Local copies via
PROCwith no parameters — declare new LUD inside the SPF. Caller values are not modified.
7.2 PROC Interface Example
Main program:
; _N_MPF_DIR/_N_MAIN_MPF
DEF REAL Xmom = 100.0
DEF REAL Xstep = 10.0
UP1(Xmom, Xstep)
G1 X=Xmom F500
UP1(Xmom, Xstep)
M30
Subprogram:
; _N_SPF_DIR/_N_UP1_SPF
PROC UP1(REAL Xmom, REAL Xstep) SAVE
DEF REAL Result
Result = Xmom + Xstep
Xmom = Result ; returns new value to caller
RET
Because the parameters are pass-by-value-by-default in SINUMERIK with the explicit PROC, the assignment Xmom = Result updates the caller's binding for the duration of UP1. After RET, the caller sees the new Xmom. The SAVE attribute preserves the caller's frame.
7.3 Implicit (No-Parameter) Subprogram
If you do not pass parameters, the subprogram sees only the channel-global state. The subprogram can define its own DEF REAL and not touch the caller's LUD. This is the cleanest isolation pattern:
; _N_SPF_DIR/_N_CALC_SPF
DEF REAL Length = 0.0005 ; local — does NOT touch caller's 'Length'
DEF REAL Angle
Angle = SIN(30) + Length
RET
The caller's Length remains whatever it was. Use this pattern when the subprogram needs only scratch variables.
7.4 How to Avoid Long Parameter Lists
For programs with dozens of shared variables, defining them once as GUD beats a 50-argument PROC header:
; _N_GUD_DEF
DEF NCK REAL _GUD_XMOM
DEF NCK REAL _GUD_XSTEP
DEF NCK REAL _GUD_YMOM
DEF NCK REAL _GUD_ZMOM
Both the main program and any subprogram reference _GUD_XMOM directly. No parameter passing required.
8. Cycle Interaction Risks with R-Parameters
| Cycle | Reads | Writes / Overwrites | Mitigation |
|---|---|---|---|
| CYCLE81 (drilling, centring) | R101 (retract), R102 (reference plane) | R0–R25 (cycle results) | Do not use R0–R25 for user math |
| CYCLE82 (drilling/dwell) | R101, R102, R103 (dwell) | R0–R25 | Same |
| CYCLE83 (deep-hole drilling) | R101–R108 | R0–R25 | Use R30+ for counters |
| CYCLE84 (tapping) | R101–R107 | R0–R25 | Same |
| POCKET3 (rectangular pocket) | R0…R20 | R0…R25 | Use GUD |
| SL cycles (contour tool) | R10…R20 | R0–R30 | Use GUD |
If you must run cycles and your math in the same channel, switch your user math to GUD. R-parameters are then free for the cycle to clobber without harm.
9. Working Code: Counter Persistence with GUD
; _N_GUD_DEF
DEF NCK REAL _GUD_XMOM = 50.0
DEF NCK REAL _GUD_XSTEP = 10.0
DEF NCK BOOL _GUD_ACTIVE = TRUE
; _N_MPF_DIR/_N_MAIN_MPF
DEF REAL Xmom
IF _GUD_ACTIVE == FALSE
_GUD_XMOM = 50.0
_GUD_XSTEP = 10.0
_GUD_ACTIVE = TRUE
ENDIF
Xmom = _GUD_XMOM
LABEL1: G1 X=Xmom F500
Xmom = Xmom + _GUD_XSTEP
_GUD_XMOM = Xmom
IF Xmom < 500 GOTOB LABEL1
_GUD_ACTIVE = FALSE
M30
; _N_SPF_DIR/_N_RESET_SPF
PROC RESET SAVE
_GUD_XMOM = 50.0
_GUD_XSTEP = 10.0
_GUD_ACTIVE = TRUE
RET
This combination persists the counter in NV-RAM, lets the subprogram reset it without parameter passing, and survives every power-off.
10. Troubleshooting Matrix
| Symptom | Likely Cause | Diagnostic | Fix |
|---|---|---|---|
| Counter resets to 50 every cold start | Variable is LUD, not GUD | Check DEF line — must be in _N_GUD_DEF
|
Move declaration to _N_GUD_DEF
|
| Counter resets to 50 every NCK reset | NV-RAM not loaded | Check MD11250 $MN_PROTOC_FILE_MEM
|
Verify NCK file system persistence settings |
| Counter jumps by 30 unexpectedly | Cycle is overwriting R-parameter | Inspect active cycle defaults | Move counter to GUD, not R10 |
| Subprogram sees different value than main | Local LUD shadowing global | Inspect subprogram header for local DEF
|
Remove local DEF, reference global directly |
| Cannot modify _GUD_XMOM from program | Insufficient access level | Check current access level in HMI | Switch to Service or Manufacturer |
| SAVE writes to wrong path | No file system path or wrong drive | Check NCK log for SAVE errors | Use full NC path //NC/MPF.DIR/
|
| Variable undefined error after M30 | LUD scope lost between programs | Verify LUD SAVE attribute on PROC |
Add SAVE to PROC header |
| GUD file not picked up at NCK start | Activation bit in MD | Check MD11260 $MN_GUD_FILE_MEM
|
Set bit for _N_GUD_DEF
|
| Subprogram call fails with 12080 | Path not in SPF search list | Check MD11610 $MN_PROG_FILE_MEM
|
Add SPF.DIR to search list |
| R-parameter range too small | Default R0..R99 | Check MD28050 MM_NUM_R_PARAM
|
Increase to 300 if licensed |
11. Verification Procedure
-
Declare GUD in
_N_GUD_DEFwith explicit initial value. - Activate file: HMI Advanced / SINUMERIK Operate → Commissioning → User Data → Activate. Confirm NCK reports no alarm 7552 (file activation errors).
-
Write a probe program: assign
_GUD_XMOM = 123.456and exit. - Power-cycle: NCK off for at least 10 s, then back on.
-
Read the variable: in MDI mode,
R0 = _GUD_XMOM, then inspect R0 on the HMI. Expected: 123.456. -
Run a cycle (e.g.
CYCLE81(0,0,2,-30,0)) and confirm R0..R25 are wiped but_GUD_XMOMretains 123.456. -
Log access level: attempt to write
_GUD_XMOMfrom a standard operator password; should be rejected.
12. Best Practices Checklist
- Default to GUD for any persistent counter or state value.
- Use R-parameters only for legacy cycle interop or short-lived scratch math.
- Never name a user R-parameter in the R0..R25 range if your part program calls cycles.
- When passing data between MPF and SPF, prefer GUD lookups over long PROC parameter lists.
- Always initialize GUD with explicit default values in
_N_GUD_DEF; never assume zero. - Document every GUD name in a project-level header so new programmers know
_GUD_XMOMis the X counter. - Use
SAVE/READfor audit-trail-grade persistence (CSV-style logs). - Keep LUD strictly local to one program; never assume LUD survives M30.
- For multi-channel setups, choose the correct GUD scope (
NCKvsCHAN). - Test after every GUD file activation: a syntax error in
_N_GUD_DEFblocks NCK start.
Which variable class survives a power cycle on a Siemens 840D?
GUD (Global User Data) and machine/setting data survive a power cycle because they live in NV-RAM. R-parameters also persist if their count is part of the NV-RAM image; LUD does not persist — it is reset to defaults at NCK ramp-up.
Why does my R-parameter counter jump unexpectedly after a drilling cycle?
CYCLE81, CYCLE82, CYCLE83, CYCLE84, and the SL pocket cycles use R0..R25 as temporary arguments. If your counter sits in that range, the cycle silently overwrites it. Move your user math to R30+ or, preferably, to a GUD variable.
How do I pass 50 variables between a main program and a subprogram without writing 50 PROC parameters?
Declare the values once in _N_GUD_DEF (e.g. DEF NCK REAL _GUD_VAL01 … _GUD_VAL50). Both the MPF and the SPF reference the global name directly; no parameter list is required. The trade-off is shared state, so use unique names per logical value.
Can I write GUD from a standard operator password?
No. DEF NCK and DEF CHAN GUD typically require at least Service access level. Operators can read but not modify. For values operators may tune, expose them through setting data ($SC_) instead.
How do I reset a persisted GUD counter to its initial value at program start?
Add a small initialization block at the top of the main program that detects a flag (e.g. IF NOT _GUD_ACTIVE) and resets the counter plus flag. Alternatively call a dedicated reset subprogram that overwrites _GUD_XMOM with the default value.