Beispiel: Textuelles HORST-Programm mit SPS Logiksteuerung

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:

Beispielprogramm horstFX Cases

SPS-Programm Cases