Subprograms
Function: Call of a subprogram
Frequently recurring tasks, such as pocket milling, hole drilling, and tool changing, can be swapped out to G code subprograms and called from there. During a call, parameters can be passed to the subprogram. The data types BOOL
, LREAL
, and STRING
are permitted for this purpose.
Tip
If you use subprograms, then you need to use the function blocks SMC_ReadNCFile2
and SMC_NCInterpreter
instead of SMC_ReadNCFile
and SMC_NCDecoder
.
Tip
Subprograms work in the online decoder only (not in the CNC editor).
Each subprogram is stored in a separate file. These files are saved in one or more subdirectories on the controller. The file names have to be written in lowercase, have the file extension .cnc
, and correspond to the name of the subprogram. Example: Subprogram name "Drill" -> file name drill.cnc
.
Important
Note that the file name of the subprogram has to be written in lowercase.
The SMC_ReadNCFile2
POU has an input aSubProgramDirs : ARRAY[0..4] OF STRING(174)
. Up to five subdirectories can be specified beyond this. They are scanned in the given order. If there are subprograms with the same name in multiple directories, then the subprogram is found that has the directory with the lowest index in the array. The subprogram name is converted to lowercase.
aSubProgramDirs = ['subprograms/user', 'subprograms/system', '']
The subprogram DrillA1
is scanned first in the file subprograms/user/drilla1.cnc
. If this file does not exist, then the search continues in subprograms/system/drilla1.cnc
.
It is possible to call subprograms indirectly by means of a variable (more precisely, by means of an expression of type STRING
). The expression (and therefore also any lookup of variables) is evaluated – generally in the case when using variables in the G code – at the time of the preprocessing when the interpreter reaches the line. In this case, the type checking of the arguments is done only when the interpreter has reached the line and not already during parsing, as is the case with static calls.
Tip
Subprograms cannot be created offline in the CNC editor.
Maximum nesting depth of subprogram calls
Before version 4.18.0.0: The maximum nesting depth of subprogram calls is limited to 14.
Version 4.18.0.0 and higher: The nesting depth is now limited only by the memory. The maximum value can be changed using the library parameter SMC_CNC_LibParams.MAX_SUBPROGRAM_NESTING_DEPTH.
Syntax for the call
Subprogram calls are special blocks in the G code that consist of a block number and a call only. No additional words are permitted. Moreover, there is a dynamic call in which the name of the subprogram is still unknown when parsing and is prepared (for example, by an IEC variable).
N<SentenceNo> <Name> <BracketOpen> <ActualParamList> <BracketClosed> N<SentenceNo> DYNCALL <BracketOpen> <SubNameExp> [, <ActualParamListNotEmpty] <BracketClosed> <SubNameExp> : An expression with exactly one value of type STRING <ActualParamList> ::= Empty | <ActualParamListNotEmpty> <ActualParamListNotEmpty> ::= <ActualParamValue> | <ActualParamValue>, <ActualParamListNotEmpty>
| Valid IEC identifier with minimum 3 and maximum 80 characters. It has to correspond to the file name (without extension) where the subprogram is defined. Uppercase or lowercase does not matter for subprogram names. The characters The following keywords are invalid as names: |
| There has to be exactly the same number of parameter values specified as the subprogram defines (see "Syntax for the declaration"). The type of each parameter value has to agree with the declaration. |
| For reasons of compatibility, braces are used instead of parentheses in default settings for The function block |
| Variable, literal, or any expressions |
Example
N10 SUB1() N20 DRILL(10.0) N30 SUB2(5, "Text", 2.5) N40 G36 O#SUBNAME D'DRILL' % Indirect call via local variable N40 DYNCALL(#SUBNAME, 2) % equivalent to N40 DRILL(2) N50 DYNCALL($SUBNAME$, 2, 4) % Indirect call via IEC variable
Syntax for the declaration
A subprogram has to be saved in a separate file. The first line (neither empty nor a comment line) has to contain the declaration of the subprogram. The following syntax applies:
SUBPROGRAM <Name> <BracketOpen> <FormalParamList> <BracketClosed> <RESTORE_OPT> <Inhalt Unterprogramm> END_SUBPROGRAM <FormalParamList> ::= Empty | <FormalParamListNotEmpty> <FormalParamListNoEmpty> ::= <FormalParam> | <FormalParam> , <FormalParamListNotEmpty> <FormalParam> ::= <ParamName> : <ParamType> <ParamName> ::= #[a-zA-Z0-9_]+ <ParamType> ::= LREAL | BOOL | STRING ; String with a maximum length of 255 bytes <RESTORE_OPT> ::= RESTORE_MODES
| The length of the name may be a maximum of 80 characters (not including the prefix |
| If this keyword is specified, then the following modal states are restored when returning to the calling program (set to the value that it had at the call):
The following modal states are not restored:
Note: Regardless of this keyword, the implicit counter variables (G36, G37) are restored when returning from the subprogram to the calling program. |
Examples
SUBPROGRAM SUB1() ; no formal parameters SUBPROGRAM DRILL(#depth : LREAL) SUBPROGRAM SUB2(#a : LREAL, #b : STRING, #c : LREAL) SUBPROGRAM SRM1() RESTORE_MODES
Syntax for the return
The return is done either at the end of the subprogram text (before the END_SUBPROGRAM
) or explicitly with the following syntax: N<block number> RETURN
.
Using the formal parameters in the subprogram
The values of the formal parameters can be accessed in the subprogram by #<ParamName>
.
The number of formal parameters is limited to 21.
SUBPROGRAM SUB(#Param1 : LREAL) N10 G01 X#Param1
Display of the call stack
The interpreter (SMC_NCInterpreter
) has an output that contains the 10 top active programs/subprograms: aActivePrograms : ARRAY[0..9] OF STRING
. The first entry (aActivePrograms[0]
) is the currently interpreted program/subprogram. The second entry (aActivePrograms[1]
) is the calling program/subprogram and so on. If there is no calling program, then the corresponding string is empty.
The call stack can also be displayed at interpolation time. The SMC_DisplayNCCallstack
POU shows the active programs/subprograms in the same format as the interpreter, only later (namely when the movement is run). In doing so, the interpreter output CallstackInfo (SMC_NCCallstackInfo)
and the interpolator are passed to it as VAR_IN_OUT
variables. SMC_NCCallstackInfo
stores all call stack changes, including the corresponding SMC_GeoInfo
object number, in a ring buffer. At this time, this restricts the number of storable call stack changes between the interpretation time and the interpolation time to 128. Because the ring buffer does not meet multitasking criteria, SMC_DisplayNCCallstack
has to be called from the interpreter task.
The sample program CNC Example 07: Using Expressions and Subprograms shows an example of the display of the call stack at interpolation time.