301 lines
8.7 KiB
Text
301 lines
8.7 KiB
Text
[[cha:o-codes]]
|
|
|
|
= O Codes
|
|
|
|
O-codes provide for flow control in NC programs. Each block has an
|
|
associated number, which is the number used after O. Care must be taken
|
|
to properly match the O-numbers. O codes use the letter 'O' not the
|
|
number zero as the first character in the number like O100.
|
|
|
|
.Numbering Example
|
|
----
|
|
o100 sub
|
|
(notice that the if-endif block uses a different number)
|
|
o110 if [#2 GT 5]
|
|
(some code here)
|
|
o110 endif
|
|
(some more code here)
|
|
o100 endsub
|
|
----
|
|
|
|
The behavior is undefined if:
|
|
|
|
* The same number is used for more than one block
|
|
* Other words are used on a line with an O- word
|
|
* Comments are used on a line with an O-word
|
|
|
|
[NOTE]
|
|
Using the lower case o makes it easier to distinguish from a 0
|
|
that might have been mistyped. For example o100 is easier to
|
|
see than O100 that it is not a 0.
|
|
|
|
The following statements cause an error message and abort the
|
|
interpreter:
|
|
|
|
- a `return` or `endsub` not within a sub defintion
|
|
- a label on `repeat` which is defined elsewhere
|
|
- a label on `while` which is defińed elsewhere and not referring to a `do`
|
|
- a label on `if` defined elsewhere
|
|
- a undefined label on `else` or `elseif`
|
|
- a label on `else`, `elseif` or `endif` not pointing to a matching `if`
|
|
- a label on `break` or `continue` which does not point to a matching `while` or `do`
|
|
- a label on `endrepeat` or `endwhile` no referring to a corresponding `while` or `repeat`
|
|
|
|
To make these errors non-fatal warnings on stderr, set bit 0x20 in
|
|
the `[RS274NGC]FEATURE=` mask ini option.
|
|
|
|
[[ocode:subroutines]]
|
|
== Subroutines
|
|
(((Subroutines)))
|
|
|
|
Subroutines extend from a 'O- sub' to an 'O- endsub' . The lines
|
|
between 'O- sub' and 'O- endsub' are not executed until
|
|
the subroutine is called with 'O- call'.
|
|
|
|
.Subroutine Example
|
|
----
|
|
o100 sub
|
|
G53 G0 X0 Y0 Z0 (rapid move to machine home)
|
|
o100 endsub
|
|
...
|
|
o100 call (call the subroutine here)
|
|
M2
|
|
----
|
|
See <<gcode:g53,G53>> & <<gcode:g0,G0>> & <<mcode:m2-m30,M2>> sections for more
|
|
information.
|
|
|
|
.O- Return
|
|
Inside a subroutine, 'O- return' can be executed. This immediately
|
|
returns to the calling code, just as though 'O- endsub' was encountered.
|
|
|
|
.O- Return Example
|
|
----
|
|
o100 sub
|
|
o110 if [#2 GT 5] (test if parameter #2 is greater than 5)
|
|
o100 return (return to top of subroutine if test is true)
|
|
o110 endif
|
|
(some code here that only gets executed if parameter #2 is less than 5)
|
|
o100 endsub
|
|
----
|
|
See the <<gcode:binary-operators,Binary Operators>> & <<gcode:parameters,Parameters>> sections for more information.
|
|
|
|
.O- Call
|
|
'O- Call' takes up to 30 optional arguments, which are passed to the
|
|
subroutine
|
|
as '#1', '#2' , ..., #N. Parameters from #N+1 to #30 have the same
|
|
value as in the
|
|
calling context. On return from the subroutine, the values of
|
|
parameters #1 through #30 (regardless of the number of arguments) will
|
|
be restored to the values they had before the call. Parameters #1 - #30
|
|
are local to the subroutine.
|
|
|
|
Because '1 2 3' is parsed as the number 123, the parameters must be
|
|
enclosed in
|
|
square brackets. The following calls a subroutine with 3 arguments:
|
|
|
|
.O- Call Example
|
|
----
|
|
o200 call [1] [2] [3]
|
|
----
|
|
|
|
Subroutine bodies may not be nested. They may only be called after
|
|
they are defined. They may be called from other functions, and may call
|
|
themselves recursively if it makes sense to do so. The maximum
|
|
subroutine nesting level is 10.
|
|
|
|
Subroutines do not have 'return values', but they may change the value
|
|
of parameters above #30 and those changes will be visible to the
|
|
calling code. Subroutines may also change the value of global named
|
|
parameters.
|
|
|
|
[[ocode:looping]]
|
|
== Looping
|
|
(((Subroutines, Looping)))
|
|
|
|
The 'while loop' has two structures: 'while/endwhile', and 'do/while'. In
|
|
each case, the loop is exited when the 'while' condition evaluates to
|
|
false. The difference is when the test condition is done. The 'do/while'
|
|
loop runs the code in the loop then checks the test condition. The
|
|
'while/endwhile' loop does the test first.
|
|
|
|
.While Endwhile Example
|
|
----
|
|
(draw a sawtooth shape)
|
|
G0 X1 Y0 (move to start position)
|
|
#1 = 0 (assign parameter #1 the value of 0)
|
|
F25 (set a feed rate)
|
|
o101 while [#1 LT 10]
|
|
G1 X0
|
|
G1 Y[#1/10] X1
|
|
#1 = [#1+1] (increment the test counter)
|
|
o101 endwhile
|
|
M2 (end program)
|
|
----
|
|
|
|
.Do While Example
|
|
----
|
|
#1 = 0 (assign parameter #1 the value of 0)
|
|
o100 do
|
|
(debug, parameter 1 = #1)
|
|
o110 if [#1 EQ 2]
|
|
#1 = 3 (assign the value of 3 to parameter #1)
|
|
(msg, #1 has been assigned the value of 3)
|
|
o100 continue (skip to start of loop)
|
|
o110 endif
|
|
(some code here)
|
|
#1 = [#1 + 1] (increment the test counter)
|
|
o100 while [#1 LT 3]
|
|
(msg, Loop Done!)
|
|
M2
|
|
----
|
|
|
|
Inside a while loop, 'O- break' immediately exits the loop, and 'O-
|
|
continue' immediately skips to the next evaluation of the 'while'
|
|
condition. If it is still true, the loop begins again at the top. If
|
|
it is false, it exits the loop.
|
|
|
|
[[ocode:conditional]]
|
|
== Conditional
|
|
(((Subroutines, Conditional Loops)))
|
|
|
|
The 'if' conditional consists of a group of statements with the same 'o' number
|
|
that start with 'if' and end with 'endif'. Optional 'elseif' and 'else' conditions
|
|
may be between the starting 'if' and the ending 'endif'.
|
|
|
|
If the 'if' conditional evaluates to true then the group of statements
|
|
following the 'if' up to the next conditional line are executed.
|
|
|
|
If the 'if' conditional evaluates to false then the 'elseif' conditions are
|
|
evaluated in order until one evaluates to true. If the 'elseif' condition is
|
|
true then the statements following the 'elseif' up to the next conditional
|
|
line are executed. If none of the 'if' or 'elseif' conditions evaluate to true
|
|
then the statements following the 'else' are executed. When a condition is
|
|
evaluated to true no more conditions are evaluated in the group.
|
|
|
|
.If Endif Example
|
|
----
|
|
o101 if [#31 EQ 3] (if parameter #31 is equal to 3 set S2000)
|
|
S2000
|
|
o101 endif
|
|
----
|
|
|
|
.If ElseIf Else EndIf Example
|
|
----
|
|
o102 if [#2 GT 5] (if parameter #2 is greater than 5 set F100)
|
|
F100
|
|
o102 elseif [#2 LT 2] (else if parameter #2 is less than 2 set F200)
|
|
F200
|
|
o102 else (else if parameter #2 is 2 through 5 set F150)
|
|
F150
|
|
o102 endif
|
|
----
|
|
|
|
Several conditons may be tested for by 'elseif' statements until the
|
|
'else' path is finally executed if all preceding conditons are false:
|
|
|
|
.If Elseif Else Endif Example
|
|
----
|
|
O102 if [#2 GT 5] (if parameter #2 is greater than 5 set F100)
|
|
F100
|
|
O102 elseif [#2 LT 2] (else if parameter #2 less than 2 set F200)
|
|
F20
|
|
O102 else (parameter #2 between 2 and 5)
|
|
F200
|
|
O102 endif
|
|
----
|
|
|
|
[[ocode:repeat]]
|
|
== Repeat
|
|
(((Subroutines, Repeat Loop)))
|
|
|
|
The 'repeat' will execute the statements inside of the
|
|
repeat/endrepeat the specified number of times. The example shows how
|
|
you might mill a diagonal series of shapes starting at the present
|
|
position.
|
|
|
|
.Repeat Example
|
|
----
|
|
(Mill 5 diagonal shapes)
|
|
G91 (Incremental mode)
|
|
o103 repeat [5]
|
|
... (insert milling code here)
|
|
G0 X1 Y1 (diagonal move to next position)
|
|
o103 endrepeat
|
|
G90 (Absolute mode)
|
|
----
|
|
|
|
[[ocode:indirection]]
|
|
== Indirection
|
|
(((Indirection)))
|
|
|
|
The O-number may be given by a parameter and/or calculation.
|
|
|
|
.Indirection Example
|
|
----
|
|
o[#101+2] call
|
|
----
|
|
|
|
.Computing values in O-words
|
|
For more information on computing values see the following sections
|
|
|
|
* <<gcode:parameters,Parameters>>
|
|
* <<gcode:expressions,Expressions>>
|
|
* <<gcode:binary-operators,Binary Operators>>
|
|
* <<gcode:functions,Functions>>
|
|
|
|
[[ocode:calling-files]]
|
|
== Calling Files
|
|
(((Calling Files)))
|
|
|
|
To call a separate file with a subroutine name the file the same as
|
|
your call and include a sub and endsub in the file. The file must be in the
|
|
directory pointed to by 'PROGRAM_PREFIX' or 'SUBROUTINE_PATH' in the ini file.
|
|
The file name can include *lowercase* letters, numbers, dash, and underscore
|
|
only. A named subroutine file can contain only a single subroutine definition.
|
|
|
|
.Named File Example
|
|
----
|
|
o<myfile> call
|
|
----
|
|
|
|
.Numbered File Example
|
|
----
|
|
o123 call
|
|
----
|
|
|
|
In the called file you must include the oxxx sub and endsub and the
|
|
file must be a valid file.
|
|
|
|
.Called File Example
|
|
----
|
|
(filename myfile.ngc)
|
|
o<myfile> sub
|
|
(code here)
|
|
o<myfile> endsub
|
|
M2
|
|
----
|
|
|
|
[NOTE]
|
|
The file names are lowercase letters only so 'o<MyFile>' is converted to 'o<myfile>'
|
|
by the interpreter. More information about the search path and options for the
|
|
search path are in the INI Configuration Section.
|
|
|
|
== Subroutine return values(((Return Values)))
|
|
|
|
Subroutines may optionally return a value by an optional expression at
|
|
an 'endsub' or 'return' statement.
|
|
|
|
.Return value example
|
|
----
|
|
o123 return [#2 *5]
|
|
...
|
|
o123 endsub [3 * 4]
|
|
----
|
|
|
|
A subroutine return value is stored in the '#<_value>'
|
|
<<gcode:predefined-named-parameters, predefined named parameter>> , and
|
|
the '#<_value_returned>' predefined parameter is set to 1, to indicate
|
|
a value was returned. Both parameters are global, and are cleared just
|
|
before the next subroutine call.
|
|
|
|
// vim: set syntax=asciidoc:
|