1. Verwendung von O-Codes

O-Codes sorgen für die Ablaufsteuerung in NC-Programmen. Jeder Satz hat eine zugehörige Nummer, die nach dem O verwendet wird. Es muss darauf geachtet werden, dass die O-Nummern richtig zugeordnet werden. O-Codes verwenden den Buchstaben O und nicht die Zahl Null als erstes Zeichen in der Nummer wie O100 oder o100. O-Codes werden auch manchmal o-Worte (engl. o-words) genannt und diese Begriffe sind austauschbar.

Anmerkung
Die Verwendung des Kleinbuchstaben o erleichtert die Unterscheidung von einer 0, die möglicherweise falsch geschrieben wurde. Zum Beispiel ist bei o100 leichter zu erkennen als O100, dass es sich nicht um eine 0 handelt.

2. Nummerierung

Nummerierte o-Codes müssen für jedes Unterprogramm eine eindeutige Nummer haben,

Beispiel für eine Nummerierung
(der Beginn von o100)
o100 sub
(beachten Sie, dass der if-endif-Block eine andere Nummer verwendet)
  (der Anfang von o110)
  o110 if [#2 GT 5]
    (etwas Code hier)
  (das Ende von o110)
  o110 endif
  (etwas mehr Code hier)
(das Ende von o100)
o100 endsub

3. Kommentare

Kommentare in der gleichen Zeile wie das o-Wort sollten nicht verwendet werden, da sich das Verhalten in Zukunft ändern kann.

Das Verhalten ist undefiniert, wenn:

  • Die gleiche Nummer für mehr als einen Block verwendet wird.

  • Andere Wörter in einer Zeile mit einem o-Wort verwendet werden.

  • Kommentare in einer Zeile mit einem o-Wort verwendet werden.

4. Subroutines

Unterroutinen beginnen mit oNNN sub und enden mit oNNN endsub. Die Zeilen zwischen oNNNsub und oNNN endsub werden nicht ausgeführt, bis das Unterprogramm mit oNNN call aufgerufen wird. Jede Subroutine muss eine eindeutige Nummer verwenden.

Beispiel für ein Unterprogramm
o100 unter
  G53 G0 X0 Y0 Z0 (Eilgang zum Referenzpunkt der Maschine)
o100 Endsub

(das Unterprogramm wird aufgerufen)
o100 call
M2

Weitere Informationen finden Sie in den Abschnitten G53, G0 und M2.

O- Return (engl. für Rücksprung oder Rückkehr)

Innerhalb einer Subroutine kann o- return ausgeführt werden. Damit kehrt man sofort zum aufrufenden Code zurück, so als wäre man auf o- endsub gestoßen.

O- Return-Beispiel
o100 sub
  (Prüfung, ob Parameter #2 größer als 5 ist)
  o110 if [#2 GT 5]
    (Rückkehr zum Anfang des Unterprogramms, wenn der Test wahr ist)
    o100 return
  o110 endif
    (dies wird nur ausgeführt, wenn Parameter #2 nicht größer als 5 ist)
    (DEBUG, parameter 1 ist [#1])
o100 endsub

Weitere Informationen finden Sie in den Abschnitten Binäre Operatoren und Parameter.

O- Call (engl. für Aufruf)

o- Call nimmt bis zu 30 optionale Argumente auf, die als #1, #2 , …, #N an das Unterprogramm übergeben werden. Die Parameter von #N+1 bis #30 haben den gleichen Wert wie im aufrufenden Kontext. Bei der Rückkehr aus dem Unterprogramm werden die Werte der Parameter #1 bis #30 (unabhängig von der Anzahl der Argumente) auf die Werte zurückgesetzt, die sie vor dem Aufruf hatten. Die Parameter #1 - #30 sind lokal für das Unterprogramm.

Da 1 2 3 als die Zahl 123 geparst wird, müssen die Parameter in eckige Klammern gesetzt werden. Im Folgenden wird eine Unterroutine mit 3 Argumenten aufgerufen:

O- Call-Beispiel
o100 sub
  (Prüfung, ob Parameter #2 größer als 5 ist)
  o110 if [#2 GT 5]
    (Rückkehr zum Anfang des Unterprogramms, wenn der Test wahr ist)
    o100 return
  o110 endif
    (dies wird nur ausgeführt, wenn Parameter #2 nicht größer als 5 ist)
    (DEBUG, Parameter 1 ist [#1])
    (DEBUG, Parameter 3 ist [#3])
o100 endif

o100 call [100] [2] [325]

Unterprogrammkörper dürfen nicht verschachtelt werden. Sie dürfen erst aufgerufen werden, nachdem sie definiert wurden. Sie können von anderen Funktionen aufgerufen werden und können sich selbst rekursiv aufrufen, wenn dies sinnvoll ist. Die maximale Verschachtelungsebene eines Unterprogramms ist 10.

Unterprogramme können den Wert von Parametern oberhalb von #30 ändern und diese Änderungen werden für den aufrufenden Code sichtbar sein. Unterprogramme können auch den Wert von global named parameters (d.h. Parameter, deren Namen mit dem Unterstrich "_" beginnen) ändern.

4.1. Fanuc-Style Numbered Programs

Nummerierte Programme (sowohl Haupt- als auch Unterprogramme), die M-Codes M98 call und M99 return und ihre jeweiligen semantischen Unterschiede sind eine Alternative zu den oben beschriebenen rs274ngc-Unterprogrammen, die aus Gründen der Kompatibilität mit Fanuc- und anderen Maschinensteuerungen bereitgestellt werden.

Nummerierte Programme sind standardmäßig aktiviert und können durch Einfügen von DISABLE_FANUC_STYLE_SUB = 1 in den Abschnitt [RS274NGC] der INI-Datei deaktiviert werden.

Anmerkung
Nummerierte Haupt- und Unterprogrammdefinitionen und -aufrufe unterscheiden sich sowohl in der Syntax als auch in der Ausführung vom traditionellen rs274ngc. Um Verwechslungen vorzubeugen, gibt der Interpreter eine Fehlermeldung aus, wenn Definitionen eines Stils mit Aufrufen eines anderen Stils vermischt werden.
Nummeriertes Unterprogramm Einfaches Beispiel
o1 (Beispiel 1) ; Hauptprogramm 1, "Beispiel 1"
M98 P100 ; Unterprogramm 100 aufrufen
M30 ; Hauptprogramm beenden

o100 ; Beginn des Unterprogramms 100
  G53 G0 X0 Y0 Z0 ; Eilgang zum Referenzpunkt
M99 ; Rückkehr aus Unterprogramm 100
o1 (Titel)

Der optionale Hauptprogramm-Anfangsblock gibt dem Hauptprogramm die Nummer 1. Einige Steuerungen behandeln einen optionalen, in Klammern gesetzten Kommentar als Programmtitel, "Beispiel 1" in diesem Beispiel, aber dies hat keine besondere Bedeutung im rs274ngc-Interpreter.

M98 P- <L->

Aufruf eines nummerierten Unterprogramms. Der Satz M98 P100 ist analog zur traditionellen o100 call-Syntax, darf aber nur zum Aufruf eines folgenden nummerierten Unterprogramms verwendet werden, das mit o100M99 definiert wurde. Ein optionales L-Wort legt eine Schleifenanzahl fest.

M30

Das Hauptprogramm muss mit M02 oder M30 (oder M99; siehe unten) beendet werden.

O- Beginn der Unterprogrammdefinition

Markiert den Beginn einer nummerierten Unterprogrammdefinition. Der Block o100 ist ähnlich wie o100 sub, außer dass er später in der Datei platziert werden muss als der aufrufende Block M98 P100.

M99 Rückkehr aus nummeriertem Unterprogramm

Der Block M99 ist analog zur traditionellen o100 endsub-Syntax, darf aber nur ein nummeriertes Programm beenden (o100 in diesem Beispiel) und darf nicht ein Unterprogramm beenden, das mit der o100 sub-Syntax beginnt.

Der Unterprogrammaufruf M98 unterscheidet sich vom rs274ngc `o call`in folgender Weise:

  • Das nummerierte Unterprogramm muss in der Programmdatei auf den M98-Aufruf folgen. Der Interpreter gibt einen Fehler aus, wenn das Unterprogramm vor dem Aufrufblock steht.

  • Die Parameter #1, #2, …, #30 sind global und in nummerierten Unterprogrammen zugänglich, ähnlich wie höher nummerierte Parameter in Aufrufen im traditionellen Stil. Änderungen an diesen Parametern innerhalb eines Unterprogramms sind globale Änderungen, die nach der Rückkehr des Unterprogramms bestehen bleiben.

  • M98"-Unterprogrammaufrufe haben keinen Rückgabewert.

  • M98"-Unterprogrammaufrufblöcke können ein optionales L-Wort enthalten, das eine Schleifenwiederholungszahl angibt. Ohne das L-Wort wird das Unterprogramm nur einmal ausgeführt (äquivalent zu M98 L1). Ein M98 L0-Satz führt das Unterprogramm nicht aus.

In seltenen Fällen kann der M-Code M99 zur Beendigung des Hauptprogramms verwendet werden, wo er ein Endlosprogramm anzeigt. Wenn der Interpreter ein M99 im Hauptprogramm erreicht, springt er an den Anfang der Datei zurück und setzt die Ausführung bei der ersten Zeile fort. Ein Beispiel für die Verwendung eines Endlosprogramms ist ein Aufwärmzyklus einer Maschine; ein M30-Satz zum Löschen des Programmendes könnte verwendet werden, um den Zyklus an einem sauberen Punkt zu beenden, wenn der Bediener bereit ist.

Vollständiges Beispiel für ein nummeriertes Unterprogramm
o1 ; Hauptprogramm 1
  #1 = 0
  (PRINT,X MAIN BEGIN: 1=#1)
  M98 P100 L5 ; Unterprogramm 100 aufrufen
  (PRINT,X MAIN END: 1=#1)
M30 ; Hauptprogramm beenden

o100 ; Unterprogramm 100
  #1 = [#1 + 1]
  M98 P200 L5 ; Aufruf des Unterprogramms 200
  (PRINT,>> o100: #1)
M99 ; Rückkehr aus Unterprogramm 100

o200 ; Unterprogramm 200
  #1 = [#1 + 0.01]
  (PRINT,>>>>> o200: #1)
M99 ; Rückkehr aus Unterprogramm 200

In diesem Beispiel wird der Parameter #1 auf 0 initialisiert. Das Unterprogramm o100 wird fünfmal in einer Schleife aufgerufen. Innerhalb jedes Aufrufs von "o100 wird das Unterprogramm o200 fünfmal in einer Schleife aufgerufen, also insgesamt 25-mal.

Beachten Sie, dass der Parameter #1 global ist. Am Ende des Hauptprogramms, nach den Aktualisierungen innerhalb von o100 und o200, wird sein Wert gleich 5.25 sein.

5. Looping

Die while-Schleife hat zwei Strukturen: while/endwhile, und do/while. In beiden Fällen wird die Schleife verlassen, wenn die while Bedingung als falsch bewertet wird. Der Unterschied besteht darin, wann die Testbedingung erfüllt ist. Die do/while Schleife führt den Code in der Schleife aus und überprüft dann die Testbedingung. Die while/endwhile Schleife führt zuerst den Test durch.

While Endwhile Beispiel
(eine Sägezahnform zeichnen)
G0 X1 Y0 (auf Startposition fahren)
#1 = 0 (Parameter #1 den Wert 0 zuweisen)
F25 (Vorschubgeschwindigkeit einstellen)
o101 while [#1 LT 10]
  G1 X0
  G1 Y[#1/10] X1
  #1 = [#1+1] (Inkrementieren des Testzählers)
o101 endwhile
M2 (Programm beenden)
Do While-Beispiel
#1 = 0 (Parameter #1 wird der Wert 0 zugewiesen)
o100 do
  (Fehlersuche, Parameter 1 = #1)
  o110 if [#1 EQ 2]
    #1 = 3 (weisen Sie dem Parameter #1 den Wert 3 zu)
    (msg, #1 wurde der Wert 3 zugewiesen)
    o100 continue (zum Anfang der Schleife springen)
  o110 endif
  (hier etwas Code)
  #1 = [#1 + 1] (Inkrementieren des Testzählers)
o100 while [#1 LT 3]
(msg, Schleife fertig!)
M2

Innerhalb einer while-Schleife wird mit o- break die Schleife sofort verlassen, und mit o- continue wird sofort zur nächsten Auswertung der while Bedingung übergegangen. Wenn sie immer noch wahr ist, beginnt die Schleife wieder von vorne. Wenn sie falsch ist, wird die Schleife verlassen.

6. Conditional

Die if Bedingung besteht aus einer Gruppe von Anweisungen mit der gleichen o Nummer, die mit if beginnen und mit endif enden. Optionale elseif und else Bedingungen können zwischen dem beginnenden if und dem endenden endif stehen.

Wenn die if Bedingung als wahr bewertet wird, dann wird die Gruppe von Anweisungen nach der if bis zur nächsten Bedingungszeile ausgeführt.

Wenn die if Bedingung als falsch bewertet wird, werden die elseif Bedingungen der Reihe nach ausgewertet, bis eine als wahr bewertet wird. Wenn die elseif Bedingung wahr ist, werden die auf die elseif folgenden Anweisungen bis zur nächsten Bedingungszeile ausgeführt. Wenn keine der if oder elseif Bedingungen als wahr ausgewertet wird, werden die auf die else folgenden Anweisungen ausgeführt. Wenn eine Bedingung zu wahr ausgewertet wird, werden keine weiteren Bedingungen in der Gruppe ausgewertet.

If Endif Beispiel
(if parameter #31 is equal to 3 set S2000)
o101 if [#31 EQ 3]
  S2000
o101 endif
If ElseIf else EndIf-Beispiel
(if parameter #2 is greater than 5 set F100)
o102 if [#2 GT 5]
  F100
o102 elseif [#2 LT 2]
(else if parameter #2 is less than 2 set F200)
  F200
(else if parameter #2 is 2 through 5 set F150)
o102 else
  F150
o102 endif

Mehrere Bedingungen können durch elseif Anweisungen getestet werden, bis der else Pfad schließlich ausgeführt wird, wenn alle vorangegangenen Bedingungen falsch sind:

If elseif else endif-Beispiel
(wenn Parameter #2 größer als 5 ist, F100 einstellen)
o102 wenn [#2 GT 5]
  F100
(wenn Parameter #2 kleiner als 2 ist, wird F200 gesetzt)
o102 elseif [#2 LT 2]
  F20
(Parameter #2 liegt zwischen 2 und 5)
o102 else
  F200
o102 endif

7. Repeat

Mit repeat werden die Anweisungen innerhalb von repeat/endrepeat die angegebene Anzahl von Malen ausgeführt. Das Beispiel zeigt, wie Sie eine diagonale Reihe von Formen fräsen könnten, beginnend an der aktuellen Position.

Beispiel mit repeat
(5 diagonale Formen fräsen)
G91 (Inkremental-Modus)
o103 repeat [5]
... (Fräscode hier einfügen)
G0 X1 Y1 (diagonale Bewegung zur nächsten Position)
o103 endrepeat
G90 (Absoluter Modus)

8. Indirektion

Die o-Zahl kann durch einen Parameter und/oder eine Berechnung angegeben werden.

Beispiel für Indirektion
o[#101+2] call
Berechnung von Werten in O-Wörtern

Weitere Informationen zur Berechnung von Werten finden Sie in den folgenden Abschnitten:

9. Calling Files

Um eine separate Datei mit einem Unterprogramm aufzurufen, geben Sie der Datei den gleichen Namen wie Ihrem Aufruf und fügen Sie ein sub und endsub in die Datei ein. Die Datei muss sich in dem Verzeichnis befinden, auf das PROGRAM_PREFIX oder SUBROUTINE_PATH in der INI-Datei verweist. Der Dateiname darf nur Kleinbuchstaben, Zahlen, Bindestriche und Unterstriche enthalten. Eine benannte Subroutinendatei kann nur eine einzige Subroutinendefinition enthalten.

Beispiel für eine benannte Datei
o<myfile> call
Beispiel für eine nummerierte Datei
o123 call

In der aufgerufenen Datei müssen die oxxx sub und endsub enthalten sein und die Datei muss eine gültige Datei sein.

Beispiel für eine aufgerufene Datei
(filename myfile.ngc)
o<myfile> sub
  (code here)
o<myfile> endsub
M2
Anmerkung
Die Dateinamen sind nur Kleinbuchstaben, so dass o<MyFile> vom Interpreter in o<myfile> umgewandelt wird. Weitere Informationen über den Suchpfad und Optionen für den Suchpfad finden Sie im Abschnitt zur INI-Konfiguration.

10. Subroutine return values

Unterprogramme können optional einen Wert durch einen optionalen Ausdruck in einer endsub oder return Anweisung zurückgeben.

Beispiel für einen Rückgabewert
o123 return [#2 *5]
...
o123 endsub [3 * 4]

Der Rückgabewert eines Unterprogramms wird im <_value> <gcode:predefined-named-parameters,predefined named parameter>> gespeichert, und der <_value_returned> vordefinierte Parameter wird auf 1 gesetzt, um anzuzeigen, dass ein Wert zurückgegeben wurde. Beide Parameter sind global und werden kurz vor dem nächsten Unterprogrammaufruf gelöscht.

11. Errors

Die folgenden Anweisungen führen zu einer Fehlermeldung und zum Abbruch des Interpreters:

  • ein "return" oder "endsub", außerhalb einer Unterdefinition

  • ein Label (benamte Markierung) für repeat, das an anderer Stelle definiert ist

  • ein Label für while, das an anderer Stelle definiert ist und sich nicht auf ein do bezieht

  • ein an anderer Stelle definiertes Label für if

  • ein undefiniertes Label bei else oder elseif

  • ein Label auf else, elseif oder endif, das nicht auf ein passendes if verweist

  • eine Bezeichnung für break oder continue, die nicht auf ein passendes while oder do verweist

  • eine Bezeichnung für endrepeat oder ``endwhile`, die nicht auf ein entsprechendes while oder repeat verweist

Um diese Fehler zu nicht-fatalen Warnungen auf stderr zu machen, setzen Sie Bit 0x20 bei der Option [RS274NGC]FEATURE= in mask ini.