Hier soll ein Beispielprogramm vorgestellt werden, in dem innerhalb eines textuellen Programms auf HORST auf Register zugegriffen wird, die den Programmablauf bestimmen.
1. Funktion
Das Roboterprogramm enth�lt drei F�lle (Cases), die �ber eine Funktionsnummer aufgerufen werden. Die Funktionsnummer wird �ber das Int-Register von der SPS an den Roboter gesendet.
Innerhalb der Cases k�nnen unterschiedliche Teilprogramme aufgerufen werden. In diesem Beispiel wird im Case 0 keine Funktion ausgef�hrt, im zweiten Case werden unterschiedliche Positionen angefahren und im dritten Case wird einer Position angefahren, deren Koordinaten �ber die Float-Register von der SPS an den Roboter �bertragen werden. �ber einen Abbruchbefehl k�nnen die Fahrbewegungen abgebrochen werden.
Die Steuerung des Programms erfolgt �ber das setzen von Aktions- und Statusbits. �ber ein Start-Bit, dass von der SPS an den Roboter geschickt wird, wird ein Case gestartet. Sobald das Start-Bit vom Roboter erkannt wird, wird das Aktiv-Bit gesetzt. Ist ein Case vollst�ndig bearbeitet oder es wurde abgebrochen, wird das aktiv-Bit zur�ckgesetzt. �ber das Abbruch-Bit kann ein Teilprogramm abgebrochen werden.
2. SPS-Programm
Im TIA-Portal wird f�r das Aufrufen der Cases ein Funktionsbaustein im OB1 angelegt. �ber den Start-Eingang wird der Case, welche �ber die Funktionsnummer ausgew�hlt wird, ausgef�hrt.
�ber den abort-Befehl kann der Case abgebrochen werden. Die Funktionsnummer ist eine Ganzzahl (Integer), die dem Baustein am Eingang mitgegeben wird. Wird ein Case ausgef�hrt , nimmt der Baustein busy -Ausgang den Wert 1 an. Ist das Teilprogramm durchlaufen, wird der busy-Ausgang zur�ckgesetzt und der done-Ausgang gesetzt.
Im ersten Netzwerk des "Execute_Function"-Funktionsbausteins, wird abgefragt ob der done-Ausgang gesetzt ist. Ist dies der Fall, werden die folgenden Netzwerke �bersprungen und auf einen erneuten Start-Befehl gewartet.
Wenn der busy-Ausgang nicht gesetzt ist, wird bei einer positiven Flanke am start-Eingang der busy-Ausgang gesetzt.
Nimmt der busy-Ausgang den Wert 1 an, es wurde noch keine Funktionsnummer an den Roboter gesendet(start_ack) und das aktiv-Bit ist nicht gesetzt, wird die Funktionsnummer aus dem Eingang in das erste Int-Register geschrieben. Damit die Funktionsnummer an den Roboter �bertragen wird, muss anschlie�end die Maske des jeweiligen Regsiters gesetzt werden. Anschlie�end wird auch das start-Bit und dessen Maske auf 1 gesetzt. Die bausteininterne Variable "start_ack" speichert den Zustand in dem die Funktionsnummer in das Register �bertragen wurde.
Ist das start_ack- und das busy-Bit gesetzt, sowie das program_startet-Bit nicht gesetzt, wird bei einer positiven Flanke am aktive-Bit die Maske f�r das Int-Register und das start-Bit zur�ckgesetzt.
Die Variable "program_startet" speichert den Zustand indem der Roboter das start-Bit erkannt hat und nun aktiv ist.
Wird das abort-Bit (bit_register[2]) sowie dessen Maske gesetzt (w�hrend das busy- und das program-startet-Bit gesetzt sind), wird der Abbruchbefehl an den Roboter gesendet.
Bei einer negativen Flanke am aktive-Bit wird der SPS signalisieret, dass der Case vollst�ndig bearbeitet oder abgebrochen wurde. Ist dies der Fall, wird der busy-Ausgang zur�ckgesetzt und der done-Ausgang gesetzt. Zus�tzlich werden die internen Variablen sowie die Flanken zur�ckgesetzt.
3. Roboterprogramm
Im Roboterprogramm werden zu Beginn die Adressen f�r die Aktions- und Statusbits festgelegt und diese initialisiert.
// Festlegen der Register-Adressen der verwendeten Aktions- und Status-Bits
var bit_start = 0; // Start-Bit wird von der SPS an den Roboter geschickt.
var bit_active = 1; // Wird vom Roboter an die SPS geschickt. Gibt an, dass der Roboter ein Case ausf�hrt.
var bit_abort = 2; // Kann vom Roboter an die SPS gesendet werden, um ein Case bzw. Teilprogramm abzubrechen.
// Initalisieren der Bits
setBoolRegister(bit_start, 0);
setBoolRegister(bit_active, 0);
setBoolRegister(bit_abort, 0);
Anschlie�end wird in einer (while-)Schleife auf das Setzen des Start-Bits gewartet. �ber den Befehlt getBoolRegister(Adresse), kann aus den einzelnen Bit-Registern gelesen werden.
Ist diese Bedingung erf�llt, wird das Aktive-Bit gesetzt (setBitRegsiter(Adresse,Wert) und die Funktionsnummer aus dem ersten (bzw. 0ten) Int-Regsiter gelesen. Das Lesen des Int-Registers erfolgt �ber den Befehl "getIntRegsiter(Adresse)".
// Dauerschleife zum Abfragen der Bits bzw. zum Aufrufen der Funktionsnummer
while(true){
if(getBoolRegister(bit_start) == 1){
//Bit gibt an, dass der Roboter nun aktiv ist und eine Bewegung ausf�hrt
setBoolRegister(bit_active, 1);
// Lesen der Funktionsnummer aus den Int-Registern
var function_number = getIntRegister(0);
// Aufrufen der execute-Funktion, in der die F�lle(Cases) angelegt sind
execute_function(function_number);
}
//Warte f�r 200 ms um die Rechenlast zu minimieren
sleep(200);
}
Anschlie�end wird der Case, welcher �ber die Funktionsnummer ausgew�hlt wird, ausgef�hrt. Die Cases bestehen aus einer try-catch-Funktion. Das eigentliche Teilprogramm erfolgt innerhalb des try-Bereichs. Ist dies nicht m�glich, bzw. Tritt dabei ein Fehler auf, wird dieser in eim Hinweistext im Catch-Bereich ausgegeben. Ist das Teilprogramm erfolgreich durchgef�hrt oder ein auftretender Fehler best�tigt, wird anschlie�end das active-Bit zur�ckgesetzt.
function execute_function(function_number){
try {
switch(function_number){
case 0: {
// Keine Aktion bei Funktionsnummer = 0
break;
}
case 1: {
// Ausf�hren Programm 1
program_1();
break;
}
case 2: {
// Ausf�hren Programm 2
program_2();
break;
}
}
}
catch(e) {
//Zeige einen m�glichen Fehler als Info
show_info(e);
} finally{
//R�cksetzen des bit_active, somit kann �ber die SPS festgestellt werden, ob die Bewegung abgeschlossen ist
setBoolRegister(bit_active, 0);
}
}
Im Case 1 werden drei wahllose Positionen angefahren. Das Anfahren erfolgt �ber den erweiterten move-Befehl. Bei diesem Befehl ist es m�glich eine Abbruchbedingung zu definieren.
Der Abbruchbefehlt wird �ber ein Interrupt erzeugt. Innerhalb des Interrupts wird das Abbruch-Bit �berwacht, nimmt dieses der Wert 1 an, wird der Bewegungsbefehl abgebrochen.
Die Variable "bit_abort" die im Namen des Interrupts aufgerufen wird, ist eine Variable in der die Adresse des Abbruch-Bits steht. In diesem Beispiel enth�lt die Variable bit_abort die Zahl 2. (Achtung die Nummerierung der Register beginnt bei 0). Neben dem Abbruch des Fahrbefehls, ist es auch m�glich den Fahrbefehl zu pausieren. In dem oben genannten Link werden die unterschiedlichen Optionen des erweiterten move-Befehl beschrieben.
function program_1(){
// Beispielhaftes anfahren von unterschiedlichen Punkten, mit Abbruchbedingung bit_abort =1
move({
'Coord': 'JOINT',
'MoveType': 'JOINT',
'PoseRelation': 'ABSOLUTE',
'anyconfiguration': false,
'speed.ratio': 1.0,
'targetjoints.j1': -36.78999999999998,
'targetjoints.j2': 55.24999999999907,
'targetjoints.j3': -9.32936896029222,
'targetjoints.j4': 0.0,
'targetjoints.j5': 0.0,
'targetjoints.j6': 0.0,
'interrupt':[
{
'name': 'BOOL_REGISTER_'+bit_abort,
'operator': '==',
'type': 'CANCEL',
'value': 1.0
}
]
}, "Wegpunkt 1");
move({
'Coord': 'JOINT',
'MoveType': 'JOINT',
'PoseRelation': 'ABSOLUTE',
'anyconfiguration': false,
'speed.ratio': 1.0,
'targetjoints.j1': 0.259999999999728,
'targetjoints.j2': 65.38999999999908,
'targetjoints.j3': -47.969368814615606,
'targetjoints.j4': 0.0,
'targetjoints.j5': 0.0,
'targetjoints.j6': 0.0,
'interrupt':[
{
'name': 'BOOL_REGISTER_'+bit_abort,
'operator': '==',
'type': 'CANCEL',
'value': 1.0
}
]
}, "Wegpunkt 2");
move({
'Coord': 'JOINT',
'MoveType': 'JOINT',
'PoseRelation': 'ABSOLUTE',
'anyconfiguration': false,
'speed.ratio': 1.0,
'targetjoints.j1': -60.83999999999948,
'targetjoints.j2': 65.38999999999908,
'targetjoints.j3': -47.969368814615606,
'targetjoints.j4': 0.0,
'targetjoints.j5': 0.0,
'targetjoints.j6': 0.0,
'interrupt':[
{
'name': 'BOOL_REGISTER_'+bit_abort,
'operator': '==',
'type': 'CANCEL',
'value': 1.0
}
]
}, "Wegpunkt 3");
}
Im Case 2 wird eine Position von der SPS an den Roboter �bertragen und angefahren, sobald das Start-Bit von der SPS gesetzt wird. Auch dieser Fahrbefehl erfolgt �ber den Erweiterten move-Befehl.
In diesem Befehl, kann unter anderem ausgew�hlt werden, wie die Position angefahren wird. In diesem Beispiel wird die Position �ber die Achswinkel definiert. Die sechs Achswinkel werden in den ersten sechs Float-Registern von der SPS an den Roboter �bertragen. Daf�r werden die Adressen f�r die sechs Achswinkel vergeben und anschlie�end die jeweiligen Float-Register direkt im Move-Befehlt aufgerufen. Alternativ kann innerhalb des move-Befehls die kartesischen Koordinaten gew�hlt werden und die x-,y-z-Koordinaten sowie die rx-,ry-, rz-Rotationen in den Float-Register an den Roboter �bertragen werden.
function program_2(){
// Beispiehaftes anfahren einer Position, die Koordinaten werden von der SPS an den Roboter �bertragen.
// Mit Abbruchbedingung bit_abort =1
// Festlegen der Float-Register-Adressen
var Achswinkel_1= 0;
var Achswinkel_2= 1;
var Achswinkel_3= 2;
var Achswinkel_4= 3;
var Achswinkel_5= 4;
var Achswinkel_6= 5;
move({
'Coord': 'JOINT',
'MoveType': 'JOINT',
'PoseRelation': 'ABSOLUTE',
'anyconfiguration': false,
'speed.ratio': 1.0,
'targetjoints.j1': getFloatRegister(Achswinkel_1),
'targetjoints.j2': getFloatRegister(Achswinkel_2),
'targetjoints.j3': getFloatRegister(Achswinkel_3),
'targetjoints.j4': getFloatRegister(Achswinkel_4),
'targetjoints.j5': getFloatRegister(Achswinkel_5),
'targetjoints.j6': getFloatRegister(Achswinkel_6),
'interrupt':[
{
'name': 'BOOL_REGISTER_'+bit_abort,
'operator': '==',
'type': 'CANCEL',
'value': 1.0
}
]
}, "Wegpunkt 4");
}
Das Roboter- sowie das SPS-Programm kann unter den folgenden Links heruntergeladen werden: