What are variables actually for?
In a conventional CNC program everything is fixed. The hole depth is written as Z-20 and it stays 20 mm forever. Machine the same part 25 mm deep and you open the program and edit it by hand.
With variables it works the other way round: you write the depth once at the top and the program uses it. Change one line and everything downstream follows. One program covers ten sizes of the same part.
If you come from Fanuc this is familiar territory — you had macro variables there (#100, #500). SINUMERIK does the same job with a wider system: variables have a type, a name, and a defined scope.
| On Fanuc | On SINUMERIK | Note |
|---|---|---|
#100 (local macro variable) | R10 or a variable you define yourself | R parameters are numbered; your own variables get names |
#500 (permanent common variable) | GUD (global user data) | On SINUMERIK these live in a separate definition file |
#1000 series (system) | System variables starting with $ | Far more detailed on the SINUMERIK side |
| No types — everything is a number | INT, REAL, BOOL, CHAR, STRING, AXIS, FRAME | Use the wrong type and the control alarms |
DEF, the data types and their real limits, the $ prefix system behind system variables, and arithmetic and comparison operations. Everything here is taken from the current Siemens Job Planning programming manual.SINUMERIK has three kinds of variable
The manual splits them cleanly into three. Most of the confusion around variables comes from not knowing this split.
1. System variables
Their meaning is fixed by the control and they are there ready for you: machine data, setting data, tool data, the current axis position and so on. Their names all start with $. You do not define them — you read them, and write them if your access level allows.
2. Predefined user variables
These exist in the system, but how many of them there are is set by machine data. The best known are the R parameters. Link variables belong to this group too.
3. User-defined variables
You decide the name, the type, the size and the visibility. They are created with DEF and come into existence at run time.
R parameters — what you will use most
R parameters are channel-specific predefined user variables. In the manual’s own words they are an array of the REAL data type. So every R parameter can hold a decimal number.
Two ways of writing them, same thing
For historical reasons both forms are allowed:
The indexed form has one big advantage: you can put an expression inside the brackets.
This is called indirect programming and it becomes powerful with loops — put the depths of 20 holes into R20…R39 and walk through them in a loop with a single line.
How many R parameters do you have?
This is where a common claim in older training notes is wrong: “there are 100 of them, R1 to R99”. The correct picture is:
- Numbering starts at R0, not R1.
- The count is not fixed. The upper limit comes from machine data:
MAX_INDEX = (MD28050 $MN_MM_NUM_R_PARAM) − 1
So if you want to know how many R parameters your own machine has, look at MD28050. If 100 are configured the valid range is R0…R99.
Value range
| Notation | Range | Limit |
|---|---|---|
| Normal (non-exponential) | ± (0.0000001 … 9999999) | Maximum 8 decimal places |
| Exponential | ± (1×10−300 … 1×10+300) | Written as 8.2EX-3 · maximum 10 characters including sign and decimal point |
$ prefix.In the part program you write R10. Use the same parameter inside a synchronized action and it has to be $R10. The reason is technical: R10 is read during preprocessing, $R10 during the main run. Mix them up and the value will not be what you expect.Defining your own variables: DEF
A long program written with R10, R11, R12… is unreadable six months later. DEF lets you name a variable so the program explains itself.
The simple form
Naming rules — the manual’s own wording
- Maximum 31 characters. (The “32 characters” figure that circulates in training notes is wrong.)
- The first two characters must be a letter and/or an underscore.
_DEPTHis fine,D1EPTHis fine,1DEPTHis not. - The
$sign is reserved for system variables and must not be used.
Where does the definition go?
The manual’s rules:
- Data must be defined in a dedicated block — you cannot squeeze a definition into a motion line.
- Only one data type per definition line.
- Several variables of the same type may share one line.
Going further: the full DEF syntax
You will not need this day to day, but if you want units and limits the manual gives this structure:
PHU sets the physical unit, LLI the lower limit and ULI the upper limit. For example:
The benefit of limits: if a value outside the range is assigned, the control tells you. The program does not quietly run on with a wrong number.
Data types and their real limits
Choosing the wrong type is one of the most common reasons a program alarms. This is the manual’s own table:
| Type | What it holds | Value range |
|---|---|---|
INT | Integer with sign | −2,147,483,648 … +2,147,483,647 |
REAL | Real number, LONG REAL to IEEE | ±(~2.2×10−308 … ~1.8×10+308) |
BOOL | Truth value | TRUE (1), FALSE (0) |
CHAR | Single ASCII character | ASCII code 0 … 255 |
STRING | Character string of a defined length | Maximum 200 characters (no special characters) |
AXIS | Axis / spindle identifier | Channel axis identifier |
FRAME | Coordinate transformation data (translation, rotation, scaling, mirroring) | — |
The one thing to watch in type conversion
Assign a REAL value to an INT variable and the control rounds: a fractional part of 0.5 or more rounds up, below that rounds down. So with DEF INT A and A=7.6 you end up with 8, not 7. Doing dimensional arithmetic without knowing this will scrap parts.
System variables and the $ prefix system
System variable names are not arbitrary. The letters after the $ tell you what kind of data it is, and the letter after that tells you where it applies.
First letter — what kind of data?
| Prefix | Meaning | Read when? |
|---|---|---|
$M | Machine data | During preprocessing |
$S | Setting data, protection areas | |
$T | Tool management data | |
$P | Programmed values | |
$C | Cycle variables of the ISO envelope cycles | |
$O | Option data | |
R | R parameters | |
$$M / $$S | Machine / setting data | During the main run |
$A | Current main run data | |
$V | Servo data | |
$R | R parameters (in synchronized actions) |
$S is often described as “system data” — it is setting data, which is something else entirely. $V is often described as “service data” — it is servo data. Both errors change the meaning completely.Second letter — where does it apply?
N— NCK-global (the whole control)C— channel-specificA— axis-specific
Example: $AA_IM[X] → $A main run data, the second A axis-specific — the current position of the X axis in the machine coordinate system.
$TC_... the letter C does not mean channel — it means tool carrier. And $P_... denotes channel-specific variables. Descriptions of $TC_DP3[8,2] as “a tool parameter of the current channel” are wrong for this reason.Preprocessing or main run?
In practice this distinction means: preprocessing variables take their value as the control reads and interprets the line, and they do not trigger a preprocessing stop. Main run variables take their value as the motion actually happens. If you want the axis’s real current position, you need a main run variable; a preprocessing variable gives you the value the control calculated in advance.
Where is a variable valid? LUD, PUD, GUD
This topic is missing from most training material, yet it is exactly the answer to “why is my variable empty in the subprogram?”
| Kind | Defined where? | Accessible from? | Deleted when? |
|---|---|---|---|
| LUD Local user data | In a part program that is not the main program — i.e. in a subprogram | Only inside the program it is defined in | At end of program or NC reset |
| PUD Program-global user data | In the part program running as the main program | The main program and all of its subprograms | At end of program or NC reset |
| GUD Global user data | In a definition file (SGUD, MGUD, UGUD, GUD4…GUD9) | All part programs | Never — survives shutdown and restart |
The rule is: a variable defined in a subprogram does not come back to the main program. If you need the value on both sides, define it in the main program (making it a PUD) or make it a GUD.
GUDs are written into a definition file, for example _N_DEF_DIR/_N_MGUD_DEF. They are retained when the machine is switched off and on again — think of them as the equivalent of the Fanuc #500 series.
Doing arithmetic with variables
The manual’s arithmetic function table:
| Command | Meaning | Example / note |
|---|---|---|
+ − * / | Add, subtract, multiply, divide | 3 / 4 = 0.75 |
DIV | Integer division | 7 DIV 4.1 = 1 |
MOD | Modulo — remainder of the integer division | 7 MOD 4.1 = 2.9 |
: | Chain operator for FRAME variables | Frames only |
SIN() COS() TAN() | Sine, cosine, tangent | Angles are in degrees (right angle = 90°) |
ASIN() ACOS() | Arc sine, arc cosine | |
ATAN2(,) | Arc tangent 2 | Angle of the resultant of two perpendicular vectors, result −180° … +180° |
SQRT() | Square root | |
POT() | 2nd power (square) | Squaring is POT() |
ABS() | Absolute value | |
TRUNC() | Integer component | Also used to set comparison accuracy |
ROUND() | Round to integer | |
LN() EXP() | Natural logarithm, exponential function | |
MINVAL() MAXVAL() | Lower / larger of two variables | |
BOUND() | Keeps a value inside a defined range | |
CTRANS() CROT() | Offset, rotation | Frame operations |
CSCALE() CMIRROR() | Change of scale, mirroring | Frame operations |
ROT() → the square function”. That is wrong. In the manual the square function is POT() and rotation is CROT(). ROT is the frame rotation command and has nothing to do with squaring. A calculation written with this mistake produces wrong dimensions.A practical example — hypotenuse
Taper calculations, chamfer calculations, bolt-circle coordinates — all of them come out of these two functions.
Comparison and logic operations
These are the basis of IF statements and loop conditions.
Comparison operators
| Operator | Meaning |
|---|---|
== | Equal to |
<> | Not equal to |
> | Greater than |
< | Less than |
>= | Greater than or equal to |
<= | Less than or equal to |
==, not =.A single equals sign is an assignment: R1=5 means “put 5 into R1”. A comparison needs the double equals: IF R1==5. Examples written as IF X=-50 appear in some material; that form is an assignment, not a condition, and will not behave as you expect.Comparisons work on the CHAR, INT, REAL and BOOL types. For STRING, AXIS and FRAME only == and <> are available. The result of a comparison is always of type BOOL.
Logic operators
AND, OR, NOT (negation), XOR (exclusive OR).
Bit-by-bit versions: B_AND, B_OR, B_NOT, B_XOR. These apply to the individual bits of CHAR and INT types and are what you use to interrogate machine data bits.
In logic operations 0 counts as FALSE and anything other than 0 counts as TRUE.
R10ANDR11; it has to be R10 AND R11. Also, B_NOT refers to a single operand and that operand comes after the operator.Operator priority
From highest to lowest:
NOT,B_NOT*,/,DIV,MOD+,−B_ANDB_XORB_ORANDXOROR<<(string concatenation)==,<>,>,<,>=,<=
Operators of equal priority are evaluated left to right. Parentheses override the order — and the manual recommends using them.
The frame chain operator : is not in this list; it must not be used in the same expression as other operators.
The decimal comparison trap and TRUNC
What happens if you run this?
On paper 61.02 − 61.01 = 0.01, so 0.01 > 0.01 is false and no alarm should be raised. But REAL data is held internally as 64-bit IEEE and decimal numbers cannot be represented exactly. The result may come out as 0.0099999… or 0.0100000…1.
For this reason SINUMERIK checks comparisons for relative equality, not absolute equality. The relative accuracy is of the order of 10−12 and applies to ==, <>, >=, <=, > and <.
If the remaining deviation is still unacceptable, move the comparison onto integers with TRUNC:
Common mistakes
Defining a variable inside a motion line
Definitions belong in their own block. A line like DEF REAL DEPTH G1 X50 will not run.
Defining in a subprogram and looking for it in the main program
A variable defined in a subprogram is an LUD and is deleted when the subprogram ends. To carry the value out, define it in the main program or use a GUD.
Using a single equals sign in a comparison
IF R1==5, not IF R1=5. This is the single most time-consuming typing mistake.
Writing logic expressions without spaces
Write IF (R10<50) AND (R11>20) with spaces around the operator.
Assigning a decimal value to an INT variable
The control rounds and does not tell you. When a dimension is off, look here.
Assuming R parameters get cleared
R parameters are not deleted at the end of a program. To avoid running on a value left over from the previous job, reset the ones you use at the top of your program.
Using high R parameter numbers without checking MD28050
If your machine has 100 parameters configured, R150 alarms immediately. Find the upper limit once and write it down.
Frequently asked questions
What is the practical difference between an R parameter and a DEF variable?
An R parameter is already there, needs no definition, is of type REAL and is not cleared when the program ends. A variable you define with DEF takes the name and type you want, but it has to be defined and its scope is limited. R for quick arithmetic, DEF for readable programs.
What is the equivalent of the Fanuc #500 series?
In terms of surviving a power cycle, the closest equivalent is GUD. Note though that GUDs are defined in a separate definition file — they cannot be created from inside a part program.
Can I change tool offsets from the program using variables?
It is possible through system variables, but it directly changes how the machine cuts, and access level and write timing come into it. We deliberately give no example here; writing offsets is a subject in its own right and should be handled together with the machine builder’s manual.
How do I find out how many R parameters I have?
Look at machine data MD28050 $MN_MM_NUM_R_PARAM. The highest valid number is one less than that value.
Can I use accented or non-English characters in variable names?
Do not. The manual requires letters and underscores; characters outside that set can cause trouble depending on the control version. Write DEPTH, not a localized spelling.
Does all of this apply to an 828D?
The variable structure, the data types, the operators and the priority order are part of the NC language and are defined in the manual shared by 840D sl and 828D. Unlike panel and menu topics they do not change with the version. Only the data class attribute (DCM/DCI/DCU) is specific to the 828D, and machine-data-dependent values such as the number of R parameters differ from machine to machine.
Sources
- Siemens AG — SINUMERIK 840D sl / 828D Job Planning, Programming Manual, 01/2015, document no. 6FC5398-2BP40-5BA2: Section 2.1 Variables (p.19), 2.1.2.1 Channel-specific arithmetic parameters R (p.22), 2.1.4 Definition of user variables DEF (p.27), 2.1.14 Data types (p.55), 2.2 Indirect programming (p.62), 2.3 Arithmetic functions (p.69), 2.4 Comparison and logic operations (p.71), 2.5 Precision correction on comparison errors TRUNC (p.73), 2.7 Priority of the operations (p.76), 2.8 Possible type conversions (p.76)
- Siemens AG — SINUMERIK 840D sl / 828D Fundamentals, Programming Manual (base NC language definitions)