Zuviel Werbung? - > Hier kostenlos beim SPS-Forum registrieren

Seite 2 von 2 ErsteErste 12
Ergebnis 11 bis 20 von 20

Thema: Programmierung einer zyklischen Beckhoff SPS mit ST

  1. #11
    Registriert seit
    25.11.2010
    Ort
    OWL
    Beiträge
    745
    Danke
    27
    Erhielt 164 Danke für 142 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Das ist immer noch ein Ablaufprogramm. Du gehst immer noch davon aus, dass das Programm an bestimmten Stellen wartet, bis die gerade ausgeführte Funktion beendet ist, aber das tut es nicht und darf es auch nicht.
    Was Du brauchst, ist eine Schrittkette, die nacheinander die Schritte "Paket suchen nach links", "Paket suchen nach rechts" und "Paket abschieben" ausführt. Das könnte so aussehen:
    Code:
    VAR CONSTANT
       WartenAufStart:USINT:=0;
       SuchenLinks:USINT:=1;
       SuchenRechts:USINT:=2;
       Abschieben:USINT:=3;
    END_VAR
    VAR
       AktuellerSchritt:USINT;
    END_VAR
    
    CASE AktuellerSchritt OF
       WartenAufStart:
          (* Reset aller Ausgänge *)
          IF StartFreigabe THEN   (* per Taster, Timer oder sonstwie *)
             (* Linkslauf einschalten *)
             AktuellerSchritt:=SuchenLinks;
          END_IF
       SuchenLinks:
          IF Lichtschranke THEN
             (* In Abhängigkeit vom Paketzähler Links- oder Rechtslauf einschalten *)
             AktuellerSchritt:=Abschieben;
          ELSIF Timer1.Q THEN
             (* Rechtslauf einschalten *)
             AktuellerSchritt:=SuchenRechts;
          END_IF
       SuchenRechts:
          IF Lichtschranke THEN
             (* In Abhängigkeit vom Paketzähler Links- oder Rechtslauf einschalten *)
             AktuellerSchritt:=Abschieben;
          ELSIF Timer2.Q THEN
             AktuellerSchritt:=WartenAufStart;
          END_IF
       Abschieben:
          IF Timer3.Q THEN
             IF Zaehler<10 THEN
                Zaehler:=Zaehler+1;
             ELSE
                Zaehler:=0;
             END_IF
             AktuellerSchritt:=WartenAufStart;
          END_IF
    END_CASE
    
    Timer1(IN:=AktuellerSchritt=SuchenLinks,
               PT:=T#5s);
    Timer2(IN:=AktuellerSchritt=SuchenRechts,
               PT:=T#10s);
    Timer3(IN:=AktuellerSchritt=Abschieben,
               PT:=T#20s);
    Geändert von StructuredTrash (06.01.2015 um 11:56 Uhr) Grund: Bei Timeraufrufen ":=" durch "=" ersetzt

  2. #12
    DerBenutzer ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    18.12.2014
    Beiträge
    13
    Danke
    1
    Erhielt 0 Danke für 0 Beiträge

    Standard

    Wie funktioniert die Timerfunktion denn dann? Ich hatte es so verstanden:

    timer.pt:=T#10s // Timer wird initialisiert mit 10 sekunden


    timer.IN:=true; //Timer wird gestartet und unterbricht das Programm


    timer.Q=false //Solange der Timer noch nicht abgelaufen ist
    timer.Q=true //Wenn der Timer abgelaufen ist


    timer.IN:=false; //timer wird "resettet"

    Oder muss ich das so verstehen, dass wenn ein Timer ausgeführt wird, der Rest des Programms erstmal abgearbeitet wird aber am Ende, bevor der neue Zyklus startet, eben die Zeit des Timers gewartet wird?

    Noch ein paar Fragen zu deinem Programm:

    1. Die Timerzuweisung am Ende ist mir so nicht geläufig. Steht dort praktisch das Timer1 bis Timer3 mit den entsprechenden Werten neu initialisiert werden, wenn die Bedingung "Aktuellerschrit:=Abschieben etc." wahr ist?
    Muss Timer.In nicht auch dann im Laufe des Programms nochmal auf False gesetzt werden um ihn zu resetten oder geschieht das durch die erneute Zuweisung am ende des Programms automatisch?

    Aber mal zum Verständnis, was ist eigentlich der Vorteil davon wenn das Programm zyklisch funktioniert und praktisch dauernd aufgerufen wird? Wäre es nicht effizienter so eine Steuerung ereignisgesteuert zu programmieren, sodass
    auf bestimmte Sensoren reagiert werden kann? Auch sehe ich generell nicht den Unterschied, warum es überhaupt so etwas wie SPS gibt. Ich könnte das ganze ja auch mit einem Programm in C#,C,C++ oder was auch immer
    vom PC starten. Da bräuchte ich dann auch keine Zyklen...

  3. #13
    Registriert seit
    25.11.2010
    Ort
    OWL
    Beiträge
    745
    Danke
    27
    Erhielt 164 Danke für 142 Beiträge

    Standard

    Zitat Zitat von DerBenutzer Beitrag anzeigen
    Wie funktioniert die Timerfunktion denn dann?
    So wie ich es in Post #9 beschrieben habe. Das erklärt vielleicht auch die Art der Timeraufrufe in meinem Beispiel.

    Zitat Zitat von DerBenutzer Beitrag anzeigen
    Aber mal zum Verständnis, was ist eigentlich der Vorteil davon wenn das Programm zyklisch funktioniert und praktisch dauernd aufgerufen wird? Wäre es nicht effizienter so eine Steuerung ereignisgesteuert zu programmieren, sodass auf bestimmte Sensoren reagiert werden kann?
    Bei den Maschinen, für die ich Programme schreibe, liegt die Anzahl der Signaleingänge im unteren 3-stelligen Bereich. Es wird hier im Forum aber auch Anwender geben, für die das eher Kleinkram ist. Selbst wenn man eine Hardwareplattform hätte, die soviele Hardware-Interruptkanäle bereitstellt, wäre die Aufgabe, die Interrupts in sinnvoller Weise zu priorisieren, nahezu unlösbar. Die Gefahr, dass ein niedrig priorisierter Interrupt nicht rechtzeitig behandelt wird, weil er andauernd durch höher priorisierte Interrupts unterbrochen wird, wäre zu gross. Dann lieber nur ein Interrupt in einem festen Zeittakt, mit dem alle Signale per Polling abgefragt werden. Natürlich wird damit jede Menge Rechenzeit verbraten, weil in vielen Programmzyklen gar keine Signaländerungen auftreten, aber das eindeutig vorhersehbare Zeitverhalten ist wichtiger. Ausserdem bestehen zwischen einzelnen Steuerungsfunktionen oft Abhängigkeiten, die wesentlich einfacher und sicherer zu handhaben sind, wenn man eine eindeutig festgelegte Bearbeitungsreihenfolge hat.

  4. #14
    Registriert seit
    24.02.2009
    Beiträge
    1.242
    Danke
    23
    Erhielt 276 Danke für 235 Beiträge

    Standard

    Moin.

    Ein Timer unterbricht dein Programm nicht. Das wäre sehr ungünstig wenn er es täte, da eine SPS bei einer Zykluszeitverletzung idR in den Störzustand wechselt (Endlosschleifen sind hier der Klassiker).
    Timer funktionieren wie alle anderen Bausteine im Programm. Sie müssen zyklisch abgearbeitet werden. In jeden Zyklus wird im Timer-Baustein die Differenz aus Startzeit und aktueller Zeit mit der eingestellten Auslösezeit verglichen. Ist die Differenz >= der eingestellten Zeit, wird die durch das Ausgangssignal (Q) angezeigt (je nach Timer-Typ halt).

    Bei den Timeraufrufen am Ende von StructuredTrashs Beispiel hat sich ein kleiner Fehler eingeschlichen.
    Richtig:
    Code:
    Timer1(IN:=AktuellerSchritt = SuchenLinks,            PT:=T#5s); 
    Timer2(IN:=AktuellerSchritt = SuchenRechts,            PT:=T#10s); 
    Timer3(IN:=AktuellerSchritt = Abschieben,            PT:=T#20s);
    AktuellerSchritt = SuchenLinks ist ein Boolscher Ausdruck. Timer1.IN erhält den Wert des Vergleichs von AktuellerSchritt und SuchenLinks. Hat AktuellerSchritt den gleichen Wert wie SuchenLinks dann ist Timer1.IN = true, wenn nicht dann ist er false.
    Alternativ und zum besseren Verständnis kann man auch schreiben:
    Code:
    If AktuellerSchritt = SucheLinks THEN
      Timer1(IN := TRUE, PT := t#5s);
    ELSE
      Timer1(IN := FALSE, PT := t#5s);
    END_IF

    Der zyklische Ablauf von Programm für Industriesteuerungen wurde mit Sicherheit ganz bewusst gewählt
    Ein wichtiger Grund ist z.B. die Konsistenz der Ein- und Ausgangsdaten und die Konsistenz der Programmabarbeitung. Wenn du deine Eingangssignale verarbeitest möchtest du alle Signale als Schnappschuss von EINEM definiertem Zeitpunkt haben. Außerdem arbeitest du ja nicht nur mit Einzelsignalen sondern verknüpfst auch die Zustände mehrerer Signale miteinander, das ist mit Ereignissen garnicht mehr zu bewerkstelligen, wenn diese immer nur den Zustandswechsel von einem Eingang anzeigen.
    Versuche mal das Beispiel von StruckturedTrash als Ereignisgesteuertes Programm umzusetzen und du wirst sehen, dass man selbst bei solchen einfachen Sachen schon an die Grenze stößt.

    PC Programme arbeiten idR auch nur dann rein Ereignisgesteuert, wenn sie nur auf wenige Eingaben (User-Input) reagieren müssen. Aber Bediener können selten mehrere hundert Eingaben gleichzeitig und das x-mal pro Sekunde durchführen. In einer Maschine ist das aber üblich. Alles andere was bei einem PC im Hintergrund läuft wird auch zyklisch abgearbeitet....
    Sänd from mei Kombjudder mitse Dastadurr.

  5. Folgender Benutzer sagt Danke zu MasterOhh für den nützlichen Beitrag:

    StructuredTrash (06.01.2015)

  6. #15
    Registriert seit
    25.11.2010
    Ort
    OWL
    Beiträge
    745
    Danke
    27
    Erhielt 164 Danke für 142 Beiträge

    Standard

    Danke für die Korrektur. Sch... Doppelpunkt.

  7. #16
    DerBenutzer ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    18.12.2014
    Beiträge
    13
    Danke
    1
    Erhielt 0 Danke für 0 Beiträge

    Standard

    Ok das man die Hardware für eine solche Anzahl an Signalen braucht, hatte ich nicht bedacht und das übliche PC Programme auch durchgehend z.B. die Position des Cursors im Hintergrund pollen stimmt ja auch. Es ist zwar alles ein bisschen abstrakt, weil ich mir generell nicht vorstellen kann, rein von der Rechenkapazität und der Geschwindigkeit, dass ein PC der viele Milliarden Operationen pro Sekunde bewältigen kann, diese Signal softwaretechnisch nicht verarbeiten könnte, aber das kann man gerade nicht ändern, da fehlt einfach die Erfahrung im Umgang mit diesen Maschinen bei mir.

    Die Frage ist wenn Schleifen für den Zyklus einer SPS so verheerend sein könnten wegen Störungen, wieso es diese überhaupt gibt. Wenn ich da wenig Spielraum im Bereich von Millisekunden habe, müsste ich ja praktisch die Komplexität und Mächtigkeit jeder Schleife genau beurteilen bevor ich sie überhaupt anwende...

    Grundsätzlich habe ich das Programm jetzt nochmal etwas angepasst, nachdem ich in ein paar .pdf Dateien die Funktionsweise von TON, TOF und TS angeschaut habe, wusste z.B. gar nicht das es außer TON noch was anderes gibt...
    Geändert habe ich Folgendes, erstmal oben die Variablen deklariert für rechtsdrehen und linksdrehen als logisches signal, die drei Timer und den Zähler.
    Danach noch die Bedingung für Rechts und Linkslauf in den CASE SuchenLinks und SuchenRechts eingefügt. Jetzt müsste es ja alles seinen Lauf nehmen wie es sollte.

    Eine kleine Sache bleibt allerdings noch.
    Wie verhält es sich mit dem Zähler?
    Der befindet sich ja in keinem definierten Zustand am Anfang, das heißt eigentlich
    würde der erste Vergleich IF zaehler<=4 THENdann eine Fehlermeldung ausspucken.
    Das problem ist ich kann den zaehler auch nicht mit zaehler:=0;
    bei den globalen Variablen initialisieren, weil ich dann ja immer den Zähler nach einem Zyklus zurücksetzen würde.

    Deswegen bin ich gerade leicht überfragt wie man einen Zähler überhaupt machen soll.
    Code:
    VAR CONSTANT   WartenAufStart:USINT:=0;
       SuchenLinks:USINT:=1;
       SuchenRechts:USINT:=2;
       Abschieben:USINT:=3;
    END_VAR
    VAR
       AktuellerSchritt:USINT;
       Timer1:TON;
       Timer2:TON;
       Timer3:TON;
       zaehler:BYTE;
       RichtungRechts:BOOL;
       RichtungLinks:BOOL;
    END_VAR
    
    
    CASE AktuellerSchritt OF
       WartenAufStart:
          (* Reset aller Ausgänge *)
          IF StartFreigabe THEN   (* per Taster, Timer oder sonstwie *)
             (* Linkslauf einschalten *)
             AktuellerSchritt:=SuchenLinks;
          END_IF
       SuchenLinks:
          IF Lichtschranke THEN
             (* In Abhängigkeit vom Paketzähler Links- oder Rechtslauf einschalten *)
         IF zaehler<=4 THEN
            RichtungRechts:=False;
            RichtungLinks:=True;
         ELSE
            RichtungLinks:=False;
            RichtungRechts:=True;
         END_IF
             AktuellerSchritt:=Abschieben;
          ELSIF Timer1.Q THEN
             (* Rechtslauf einschalten *)
             AktuellerSchritt:=SuchenRechts;
          END_IF
       SuchenRechts:
          IF Lichtschranke THEN
             (* In Abhängigkeit vom Paketzähler Links- oder Rechtslauf einschalten *)
         IF zaehler<=4 THEN
            RichtungRechts:=False;
            RichtungLinks:=True;
         ELSE
            RichtungLinks:=False;
            RichtungRechts:=True;
         END_IF
             AktuellerSchritt:=Abschieben;
          ELSIF Timer2.Q THEN
             AktuellerSchritt:=WartenAufStart;
          END_IF
       Abschieben:
          IF Timer3.Q THEN
             IF Zaehler<10 THEN
                Zaehler:=Zaehler+1;
             ELSE
                Zaehler:=0;
             END_IF
             AktuellerSchritt:=WartenAufStart;
          END_IF
    END_CASE
    
    
    Timer1(IN:=AktuellerSchritt=SuchenLinks,
               PT:=T#5s);
    Timer2(IN:=AktuellerSchritt=SuchenRechts,
               PT:=T#10s);
    Timer3(IN:=AktuellerSchritt=Abschieben,
               PT:=T#20s);
    Geändert von DerBenutzer (06.01.2015 um 12:43 Uhr)

  8. #17
    Registriert seit
    25.11.2010
    Ort
    OWL
    Beiträge
    745
    Danke
    27
    Erhielt 164 Danke für 142 Beiträge

    Standard

    Zitat Zitat von DerBenutzer Beitrag anzeigen
    Ok das man die Hardware für eine solche Anzahl an Signalen braucht, hatte ich nicht bedacht und das übliche PC Programme auch durchgehend z.B. die Position des Cursors im Hintergrund pollen stimmt ja auch. Es ist zwar alles ein bisschen abstrakt, weil ich mir generell nicht vorstellen kann, rein von der Rechenkapazität und der Geschwindigkeit, dass ein PC der viele Milliarden Operationen pro Sekunde bewältigen kann, diese Signal softwaretechnisch nicht verarbeiten könnte, aber das kann man gerade nicht ändern, da fehlt einfach die Erfahrung im Umgang mit diesen Maschinen bei mir.
    Es geht dabei ja auch nicht nur um schiere Rechenleistung, wie MasterOhh und ich schon geschrieben haben.

    Zitat Zitat von DerBenutzer Beitrag anzeigen
    Die Frage ist wenn Schleifen für den Zyklus einer SPS so verheerend sein könnten wegen Störungen, wieso es diese überhaupt gibt. Wenn ich da wenig Spielraum im Bereich von Millisekunden habe, müsste ich ja praktisch die Komplexität und Mächtigkeit jeder Schleife genau beurteilen bevor ich sie überhaupt anwende...
    Stimmt. Deshalb findet man in SPS-Programmen Schleifen auch nicht so oft.

    Zitat Zitat von DerBenutzer Beitrag anzeigen
    Grundsätzlich habe ich das Programm jetzt nochmal etwas angepasst, nachdem ich in ein paar .pdf Dateien die Funktionsweise von TON, TOF und TS angeschaut habe, wusste z.B. gar nicht das es außer TON noch was anderes gibt...
    Geändert habe ich Folgendes, erstmal oben die Variablen deklariert für rechtsdrehen und linksdrehen als logisches signal, die drei Timer und den Zähler.
    Danach noch die Bedingung für Rechts und Linkslauf in den CASE SuchenLinks und SuchenRechts eingefügt. Jetzt müsste es ja alles seinen Lauf nehmen wie es sollte.
    Die Richtung stimmt, aber Weg ist noch lang. Da sind noch einige Kommentare, die Du durch konkreten Code ersetzen musst.

    Zitat Zitat von DerBenutzer Beitrag anzeigen
    Eine kleine Sache bleibt allerdings noch.
    Wie verhält es sich mit dem Zähler?
    Der befindet sich ja in keinem definierten Zustand am Anfang, das heißt eigentlich
    würde der erste Vergleich IF zaehler<=4 THENdann eine Fehlermeldung ausspucken.
    Das problem ist ich kann den zaehler auch nicht mit zaehler:=0;
    bei den globalen Variablen initialisieren, weil ich dann ja immer den Zähler nach einem Zyklus zurücksetzen würde.
    Variablen können im Deklarationsteil mit Werten vorbelegt werden, z. B.
    Code:
    VAR
       Zaehler:BYTE:=0;
    END_VAR
    Ist in Deinem Fall aber nicht notwendig, weil alle Variablen ohne eine solche Vorgabe beim Programmstart auf 0 gesetzt werden.

  9. #18
    DerBenutzer ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    18.12.2014
    Beiträge
    13
    Danke
    1
    Erhielt 0 Danke für 0 Beiträge

    Standard

    Hmm... also ich seh jetzt nicht wo man da noch was ändern müsste. Ich habe mal alles rot markiert was ich gemacht habe. Die StartFreigabe kann man eigentlich immer als True annehmen, habe sie nur pro forma drinnen gelassen, falls man doch mal einen An/Aus Knopf möchte. Danke für den Hinweis mit dem Zähler, das hatte ich gemeint.

    Code:
    VAR CONSTANT   
        WartenAufStart:USINT:=0;
        SuchenLinks:USINT:=1;
        SuchenRechts:USINT:=2;
        Abschieben:USINT:=3;
    END_VAR
    VAR
       AktuellerSchritt:USINT;
       Timer1:TON;
       Timer2:TON;
       Timer3:TON;
       zaehler:BYTE;
       RichtungRechts:BOOL;
       RichtungLinks:BOOL;
    END_VAR
    
    
    
    
    CASE AktuellerSchritt OF
       WartenAufStart:
                
          IF StartFreigabe THEN   (* per Taster, Timer oder sonstwie *)
             RichtungRechts:=False;
             RichtungLinks:=True;
             AktuellerSchritt:=SuchenLinks;
          END_IF
       SuchenLinks:
          IF Lichtschranke THEN
             
             IF zaehler<=4 THEN
                RichtungRechts:=False;
                RichtungLinks:=True;
             ELSE
                RichtungLinks:=False;
                RichtungRechts:=True;
             END_IF
             AktuellerSchritt:=Abschieben;
          ELSIF Timer1.Q THEN
             RichtungLinks:=False;
             RichtungRechts:=True;
             Timer1.IN:=False;
             AktuellerSchritt:=SuchenRechts;
          END_IF
       SuchenRechts:
          IF Lichtschranke THEN
             
             IF zaehler<=4 THEN
                RichtungRechts:=False;
                RichtungLinks:=True;
             ELSE
                RichtungLinks:=False;
                RichtungRechts:=True;
             END_IF
             AktuellerSchritt:=Abschieben;
          ELSIF Timer2.Q THEN
             Timer2.IN:=False;
             AktuellerSchritt:=WartenAufStart;
          END_IF
       Abschieben:
          IF Timer3.Q THEN
             Timer3.IN:=False;
             IF Zaehler<10 THEN
                Zaehler:=Zaehler+1;
             ELSE
                Zaehler:=0;
             END_IF
             AktuellerSchritt:=WartenAufStart;
          END_IF
    END_CASE

  10. #19
    Registriert seit
    25.11.2010
    Ort
    OWL
    Beiträge
    745
    Danke
    27
    Erhielt 164 Danke für 142 Beiträge

    Standard

    Ja, dann wird es wohl Zeit, das Programm mal laufen zu lassen. Die Anzahl der I/Os ist ja recht überschaubar, mit ein paar Schalt- und Anzeigeflächen auf einer Visu-Seite sollte sich das Ganze gut simulieren lassen.

  11. #20
    DerBenutzer ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    18.12.2014
    Beiträge
    13
    Danke
    1
    Erhielt 0 Danke für 0 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Ok dann schonmal vielen Dank für die ausführliche Hilfe und die ganzen erklärungen, ich werde meine Uni mal fragen ob die es organisiert bekommen mir so etwas zur Verfügung zu stellen.

Ähnliche Themen

  1. TIA S7-1212C mit V11 programmiert, mit V13 geändert
    Von kleiner mann im Forum Simatic
    Antworten: 5
    Letzter Beitrag: 19.08.2014, 14:43
  2. Antworten: 0
    Letzter Beitrag: 24.05.2012, 09:35
  3. Antworten: 10
    Letzter Beitrag: 14.04.2012, 17:28
  4. Programmierung einer KL2541 mit Beckhoff
    Von waska87 im Forum CODESYS und IEC61131
    Antworten: 0
    Letzter Beitrag: 20.01.2012, 21:57
  5. Wer programmiert uns eine Beckhoff-Steuerung?
    Von tiefel00 im Forum Suche - Biete
    Antworten: 1
    Letzter Beitrag: 22.10.2010, 16:22

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •