Resolving SINUMERIK 840D _OVR Variable Reset After CYCLE977

David Krause10 min read
Motion ControlSiemensTroubleshooting
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

Problem Overview

On a SINUMERIK 840D / 840D sl controller, after invoking the CYCLE977 probe calibration cycle, the result array _OVR[] appears to populate correctly while the cycle is executing but is cleared to zero on the very next NC block. Programs that read R222 = _OVR[2] or use _OVR[5] downstream of the cycle therefore always see 0, even though the probe physically measured a value during the cycle.

This symptom is a scope issue, not a hardware fault. _OVR is a Siemens-supplied Global User Data (GUD) array that is intended to persist across program blocks. If the controller resolves the symbol to a Local User Data (LUD) or to a program-local definition, the storage lifetime is bounded by the current program level, and the values are released the moment the cycle returns. The fix is to force the proper GUD definition set to be loaded, and if the cycle itself zeroes the element, to write the value back from a non-volatile result variable.

Affected Systems and Software Versions

Component Versions / Identifiers
Controller SINUMERIK 840D, 840D sl, 828D
HMI HMI Advanced (PCU50), HMI Operate (TCU/PCU50.5)
Measuring cycle package meas_cycles.com / meas_cust.com / DEFINES.ARC
Cycle CYCLE977 – Calibrate probe in ring/groove
Variable in question _OVR[0..7] – GUD result array (measuring cycle output)
Result array used by CYCLE977 _M_MSPE[] – internal measuring result
Related cycle state _MA, _KNUM, _MVAR, _SETVAL, _CVAL, _TP, _WP, _ZSD

The official Siemens reference for these cycles is the SINUMERIK 840D sl / 828D Measuring Cycles programming manual. All variable names, indices, and cycle calls in this article match the conventions in that document.

Root Cause: LUD vs GUD Variable Scope

User-defined variables in SINUMERIK exist in three storage classes:

  1. GUD – Global User Data. Defined once in a *.DEF / SGUD / MGUD / UGUD / GUD5..7 file, valid across all programs in the channel. Persistent until the controller is powered off (or until explicitly overwritten).
  2. LUD – Local User Data. Defined implicitly by the programmer in the current program (or loaded by a cycle that does not have GUD access). Valid only for the current program execution. Released as soon as the program / cycle returns to the calling level.
  3. PUD – Program-global User Data. Valid for the current program only, but visible across all subprograms of that program.

The _OVR[] array is shipped with the measuring-cycle package as a GUD. If a different *.DEF set is loaded in the channel – for example, a project-specific definition file that was generated before the measuring cycles were installed – the controller may interpret _OVR as LUD. In that case, the value is alive only for the duration of the CYCLE977 call. The instruction STOPRE in the next block does not save it, because LUDs are not retained when the subprogram level pops.

Key diagnostic: Open the Parameters area of HMI Advanced or HMI Operate and look for the variable list under Channel-specific user data. If _OVR appears with non-zero values only while CYCLE977 is in the block display, the symbol is bound to a non-global scope.

Diagnosing the Scope

Use the HMI to check where the definition lives:

  1. Switch to the Services area and open the Definitions folder.
  2. Locate the SGUD, MGUD, UGUD, GUD5, GUD6, GUD7, and PGUD files.
  3. Open each and search for _OVR, _MA, _KNUM, _MVAR, _SETVAL, _CVAL, _TP, _WP, and _ZSD.

On a stock 840D sl with measuring cycles installed, you will normally see:

  • SGUD.DEF – base Siemens definitions (always loaded)
  • GUD5.DEF or MGUD.DEF – measuring-cycle result array _OVR[]
  • GUD6.DEF – probe calibration values _CVAL, _TP, _WP
  • GUD7_MC.DEF – measurement-specific state _ZSD

If none of the files contain _OVR, the measuring-cycle DEFINES.ARC has not been unpacked, or the file is referenced but not active. If _OVR exists only in PGUD or is created at runtime by a program, scope is wrong.

Solution Path A – Load the Proper GUD Definitions

This is the recommended, non-invasive fix. The cycle source is untouched, and the variable retains its intended semantics.

  1. Locate the definitions archive. On a PCU50 running HMI Advanced, the measuring cycles and their definitions ship in:
    F:\HMI Advanced\Archive\Cycle-Archives\Meas.-cycles\DEFINES.ARC
    On HMI Operate, the equivalent is in the installed cycle archive under card\user\cycle\meas or oem\sinumerik\hmisrl\meas.
  2. Extract the archive to a temporary directory and confirm the presence of GUD5.DEF, GUD6.DEF, and GUD7_MC.DEF.
  3. Copy the *.DEF files into the active definitions directory:
    /_N_DEF_DIR/ (or F:\HMI Advanced\DEF for legacy systems).
  4. Activate the files in the channel via the HMI (Services → Definitions → Activate) or in the channel configuration under Channel-specific user data.
  5. Verify with a power-on reset (or RESET + Reload definitions) so the new GUD set is parsed at NCK startup.
  6. Re-run the calibration program and read R222 = _OVR[2] on the block after STOPRE.
Access rights. Some controllers report "GUD5 data does not exist or you do not have access permission" when the user class (NCK read/write protection) is set above Manufacturer. Log in with at least Service credentials before loading the definition.

Solution Path B – Patch CYCLE977 to Write the Real Result

Where the GUD definitions cannot be re-installed (e.g., production-locked OEM image, certification restrictions), the workaround is to edit the cycle so that _OVR[2] is written from a non-volatile result variable that survives the cycle return. The internal measuring result is exposed in the array _M_MSPE[].

  1. Open CYCLE977.SPF in the cycle directory:
    /_N_CST_DIR/_N_CUS_DIR/_N_CMA_DIR/ (manufacturer cycles) or _N_CUS_DIR / _N_CMA_DIR for user cycles.
  2. Locate the line that zeroes the result element. In stock measuring-cycle releases this is typically the assignment near the cycle end:
    _OVR[2] = 0
  3. Replace it with the result captured during the measurement:
    _OVR[2] = _M_MSPE[6]
  4. Save the cycle, archive it, and reset the NCK so the modified cycle is reloaded into the active working memory.

Index 6 in _M_MSPE[] is the X-axis deviation measured during the ring/groove calibration; the exact index depends on the SW version of the cycle package. Confirm by single-stepping CYCLE977 with the Block display showing the result array, then reading _M_MSPE[0..7] at each measurement and picking the index whose value matches the live measured deviation.

Maintainability warning. Editing a Siemens cycle is a last resort. Any SW update that re-installs CYCLE977.SPF will overwrite your patch. Move the modified cycle into a user cycle directory (_N_CUS_DIR) and call it explicitly, or wrap it in a higher-level cycle, so future service updates do not silently restore the original line.

Solution Path C – Substitute with $P_UIFR for the Translation

For the work-offset part of the result, you do not need _OVR[5] at all. The X translation written by the cycle is available through the settable frame system. Replace the read with:

R211 = $P_UIFR[1, X, TR]

The system variable $P_UIFR[n, axis, element] gives the programmed value of the n-th settable frame. Index 1 corresponds to G54, X is the axis token, and TR is the translation component. Because the frame lives in the channel's persistent frame memory, this value survives the cycle return and is available to subsequent blocks without any GUD loading. The same pattern works for G55..G599 by stepping the first index.

Complete Working Program Skeleton

; --- Probe calibration in a ring or groove, CYCLE977 ---
_MA    = 1                          ; 1 = calibrate in ring, 2 = calibrate in groove
_KNUM  = 1                          ; kinematics number for the probe
_MVAR  = 103                        ; measuring variant (ring/groove geometry)
_SETVAL = 75                        ; nominal reference (e.g. ring diameter)
_FA    = _SETVAL/2 + 2              ; approach feed
_VMS   = 0                          ; no multi-measurement
_EVNUM = 0                          ; no external Vo measurement
_TSA   = 20                         ; tolerance band for plausibility
_PRNUM = 101                        ; probe number
_NMSP  = 1                          ; number of measurements per point

CYCLE977                            ; execute calibration

STOPRE                              ; synchronize preprocessing/main run

R222 = _OVR[2]                      ; X deviation (requires GUD scope or Path B patch)
R211 = $P_UIFR[1, X, TR]            ; X translation of G54 (always persistent)

G75  Z0                             ; retract to Z0 before next op

Verification Procedure

  1. Set a known ring or groove reference on the table.
  2. Run the calibration cycle with the values above.
  3. Immediately after STOPRE, inspect _OVR[0..7] in the Parameters area. All values must be visible after the cycle returns, not only during its execution.
  4. Confirm R222 and R211 in the block display – both must be non-zero for a successful calibration.
  5. Move the part, run the same cycle a second time, and verify that the values are repeatable within _TSA.
  6. If the values disappear, check the GUD file activation status in Services → Definitions and re-apply Path A.

Troubleshooting Matrix

Symptom Likely Cause Corrective Action
_OVR[*] = 0 immediately after CYCLE977 returns _OVR bound to LUD scope Load GUD5.DEF / GUD6.DEF from DEFINES.ARC (Path A)
_OVR[2] stays at 0 even with GUD loaded Cycle itself writes _OVR[2]=0 at end of cycle Patch cycle to read _M_MSPE[6] (Path B)
"GUD5 data does not exist or you do not have access permission" Insufficient access level for current user Log in at Service or higher, or set NCK write protection to Customer
Translation still wrong after using $P_UIFR[1,X,TR] Wrong frame index (not G54) or wrong axis token Confirm which G5x is active; read $P_UIFRN[n] for the channel
Modified CYCLE977 silently reverts Service update overwrote the cycle Move patched cycle to _N_CUS_DIR; re-archive with ARC.COM
_OVR not in any *.DEF file Measuring-cycle archive not unpacked Unpack DEFINES.ARC from F:\HMI Advanced\Archive\Cycle-Archives\Meas.-cycles
Values present in chan-spec user data 5 but only in cycle display LUD interpretation by NCK Force GUD5 reload with NCK reset after definition activation

Worked Example – Substituting _M_MSPE

Suppose a 3-axis mill with a rotary table is probing a slot, and you need the X offset and the table rotation angle to align the part. The probe calibration cycle produces both, but _OVR[5] vanishes because of the LUD scope issue. Confirm the correct index of _M_MSPE[] by single-stepping the calibration with a known fixture:

; Manual mapping of _M_MSPE index to physical quantity
DEF _M_MSPE[10] = SET(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)

; Run CYCLE977 with a calibrated reference ring of 75.000 mm
_MA=1 _KNUM=1 _MVAR=103 _SETVAL=75
CYCLE977
STOPRE

; Inspect each index with a fixed R variable
R100 = _M_MSPE[0]   ; nominal reference echo
R101 = _M_MSPE[1]   ; measured center, X
R102 = _M_MSPE[2]   ; measured center, Y
R103 = _M_MSPE[3]   ; measured center, Z
R104 = _M_MSPE[4]   ; deviation, X
R105 = _M_MSPE[5]   ; deviation, Y
R106 = _M_MSPE[6]   ; deviation, Z or angle, depending on MVAR

Once the index that holds the deviation of interest is identified, patch the cycle so that _OVR[2] = _M_MSPE[6] (or whichever index was confirmed). The same pattern lets you populate other elements of _OVR for downstream R-parameter logic.

Additional Field Notes

  • Always follow CYCLE977 with STOPRE. The measuring cycle is processed at block-preparation time; without STOPRE, the next block reads the preprocessed (and stale) value of R222.
  • Do not use SET(expression) on _OVR[] outside of GUD scope – the NCK will accept the syntax in some SW versions and silently treat it as LUD.
  • If you copy a measuring cycle from one machine to another, the GUD definitions must travel with it. DEFINES.ARC contains the *.DEF files; meas_cycles.com / meas_cust.com contain the cycles themselves.
  • For probing on a 4th / 5th-axis configuration, the index of _M_MSPE for the angular deviation is different. Always confirm empirically with a known fixture before committing a patch to CYCLE977.
  • The reference document is the SINUMERIK 840D sl / 828D Measuring Cycles manual, which lists every _OVR index, the _M_MSPE layout, and the calling conventions for CYCLE977, CYCLE978, and CYCLE979.

FAQ

Why does _OVR[2] read zero on the block right after CYCLE977?

The symbol _OVR is being resolved to a Local User Data (LUD) instead of a Global User Data (GUD). LUDs are released the moment the cycle returns, so the value is alive only inside CYCLE977. Load the GUD5/GUD6 definitions from DEFINES.ARC, or patch CYCLE977 to copy the value from _M_MSPE[6] into _OVR[2] before the cycle returns.

Where are the measuring-cycle GUD definitions stored on a 840D sl with HMI Advanced?

They are in F:\HMI Advanced\Archive\Cycle-Archives\Meas.-cycles\DEFINES.ARC. Extract the archive, copy the *.DEF files into the active definitions directory, then activate them in Services → Definitions and perform an NCK reset.

Can I read the X translation that CYCLE977 writes without using _OVR[5]?

Yes. Use the system variable $P_UIFR[1, X, TR] to read the X translation of G54, or $P_UIFR[n, X, TR] for G55..G599. The settable frame memory is persistent and does not depend on GUD scope.

Is editing CYCLE977.SPF a safe long-term fix?

It works, but any service update that re-installs the cycle will overwrite your patch. Move the modified cycle into _N_CUS_DIR, call it explicitly, and archive it locally. The preferred long-term fix is to load the proper GUD definitions and leave the cycle untouched.

How do I find the correct index of _M_MSPE for the value I need?

Run CYCLE977 against a known reference and copy each _M_MSPE[0..9] element into a different R variable on the next block, after STOPRE. Identify the index whose value tracks the physical deviation you expect, then patch the cycle to assign that index to _OVR[2] (or whichever slot the calling program expects).

Back to blog