Wartebefehl in ST Schrittkette / wait time

domiup

Level-2
Beiträge
39
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

zu meinem Programm: ich möchte 4 Verschiedene Spannungen über eine Schrittkette anfahren. Die Spannung soll dabei langsam erhöht werden und beim Erreichen der jeweiligen Punkte soll die Spannung 2min anstehen. Die Schrittkette habe ich soweit fertig. Allerdings benötige ich Hilfe bei den Zeiten bzw. beim Erhöhen der Spannung. Hat da jemand eine Lösung für mich?

Code:
PROGRAM PLC_PRG
VAR
    rTestspannung:INT;
    iSchrittkette:INT:=0;
    rPunkt1:INT:=19552;
    rPunkt2:INT:=19968;
    rPunkt3:INT:=21631;
    rPunkt4:INT:=22048;
END_VAR


CASE iSchrittkette OF
    
    1:    rTestspannung:=rPunkt1;
        iSchrittkette:=2;
            
    2:    WHILE rPunkt1 < rPunkt2 DO
        rTestspannung:=rPunkt1;
        rPunkt1:=rPunkt1+1;
        END_WHILE;
        iSchrittkette:=3;
        
    3:    WHILE rPunkt1 < rPunkt3 DO
        rTestspannung:=rPunkt1;
        rPunkt1:=rPunkt1+100;
        END_WHILE;
        iSchrittkette:=4;
        
    4:    WHILE rPunkt1 < rPunkt4 DO
        rTestspannung:=rPunkt1;
        rPunkt1:=rPunkt1+100;
        END_WHILE;
        iSchrittkette:=0;
    
END_CASE
 
Nimm doch einen TON den Du außerhalb der Schrittkette aufrufst und innerhalb der Schrittkette die Eingänge beschaltest und den Ausgang abfragst und dann entsprechend zum nächsten Schritt schaltest. Du musst nur darauf achten, dass der TON zum Start eine steigende Flanke bekommt.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin, ein TON außerhalb der Schrittkette ist, wie @oliver.tonn schon sagt, was Du suchst. Allerdings koppelst Du durch Deine Schrittkette die Addition an die Taskzykluszeit und Timer mittels Task sind immer ungünstig. Ich würde daher einen zweiten Time dafür einbauen. Und Deine Schrittkette ist recht unflexibel was mögliche weitere Zwischenpunkte anbelangt. Mein Vorschlag wäre folgender.

Code:
VAR CONSTANT
    c_usiMAX_POINTS    : USINT := 3; (* base 0 *)
END_VAR

VAR
    rVoltageOut            : REAL;
    aiPoints                : ARRAY[0..c_usiMAX_POINTS] OF INT := 19552, 19968, 21631, 22048;
    aiOffsets                : ARRAY[0..c_usiMAX_POINTS] OF INT := 0, 1, 100, 100;
    usiPoint                : USINT;
    fbDelaySmall            : TON;
    fbDelayLarge            : TON;
    xRun                    : BOOL := TRUE;
    fbRtRun                : R_TRIG;
    usiSate                : USINT;
END_VAR

Code:
fbRtRun(CLK:= xRun);
IF fbRtRun.Q THEN
    usiSate := 1;
    rVoltageOut := aiPoints[ 0 ];
    usiPoint := 1;
ELSIF NOT xRun THEN
    usiSate := 0;
    rVoltageOut := 0;
END_IF

fbDelaySmall(
    IN:= NOT fbDelaySmall.Q AND (usiSate = 1),
    PT:= t#100ms);
fbDelayLarge(
    IN:= NOT fbDelaySmall.Q AND (usiSate = 2),
    PT:= t#2m);

CASE usiSate OF
    0: (* idle *)
        ;

    1: (* add offset *)
        IF fbDelaySmall.Q THEN
            rVoltageOut := rVoltageOut + aiOffsets[ usiPoint ];
        END_IF
        IF rVoltageOut >= aiPoints[ usiPoint ] THEN
            usiSate := 2;
        END_IF

    2: (* wait for large delay *)
        IF fbDelayLarge.Q THEN
            IF usiPoint >= c_usiMAX_POINTS THEN
                usiSate := 0;
            ELSE
                usiPoint := usiPoint + 1;
                usiSate := 1;
            END_IF
        END_IF
END_CASE
 
Vielen Dank für die Hilfe! Ich werde mich mal dran setzen. @oliver.tonn mit WHILE - Schleife hatte ich vor gehabt die Spannung an Punkt1 zb. solange zu erhöhen bis sie den Wert von Punkt2 erreicht. Das hatte auch so funktioniert wie ich es wollte allerdings wollte ich sekündlich erhöhen, was dann nicht funktionierte.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Vielen Dank für die Hilfe! Ich werde mich mal dran setzen. @oliver.tonn mit WHILE - Schleife hatte ich vor gehabt die Spannung an Punkt1 zb. solange zu erhöhen bis sie den Wert von Punkt2 erreicht. Das hatte auch so funktioniert wie ich es wollte allerdings wollte ich sekündlich erhöhen, was dann nicht funktionierte.
Nachtigall ick hör Dir trapsen. Ich sehe eine Katastrophe aufziehen. Du bist mit den Besonderheiten einer SPS vertraut? Komm bitte nicht auf die Idee in der While-Schleife einen Timer zu nutzen die den Ablauf verzögert und schmeiß diese am Besten gleich ganz raus. Ein SPS Programm wird meist zyklisch abgearbeitet und dies muss innerhalb einer definierten Zeit erfolgen. Bei Codesys basierten Steuerungen gibt die Zykluszeit vor, wie lange nach dem vorhergehenden Start das SPS-Programm erneut gestartet wird und alles muss vor dieser Zeit beendet sein. Ein SPS-Programm kann nicht, wie ein PC-Programm, an einer Stelle auf ein Ereignis warten, sondern muss stetig weiterlaufen.
 
Du nimmst einen Timer (SE oder Impuls) und baust dir damit einen Sekundentakt. Wiele SPS (Wago evtl. auch) heben auch Standardbits für soetwas wie Takte.
Den AUsgang des Timeras schaltest du auf eine Flanke, so dass du danach jede Sekunde eine Flanke hast.
Mit dieser Flanke kannst du dann deine Werte hochzählen.

If #SekundenFlanke Then #MeinWert := MeinWert + 1; End_IF;

In der Schrittkette dann:

If #MeinWert > rPunkt1 then usiState := ... End_IF

So in dieser Art.
Willst du schneller hochzählen, dann den Timer kleiner machen (Auchtung, er darf nicht zu klein werden) oder du zählst nicht 1 hoch sondern z.Bsp. 10.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@oliver.tonn bin ein SPS Neuling und habe es durch Try and Error probiert 😂Habe alle Probleme lösen können. Danke für die Hilfe!
Im Interesse anderer Suchender mit einem gleichen oder ähnlichen Problem wäre es gut, wenn Du hier auch erklären/zeigen würdest, wie genau Du Dein Problem gelöst hast.
;)
 
Habe die Lösung von @KLM übernommen und ein wenig auf mein Projekt angepasst. Sprich Variablen geändert und die Arrays weggelassen da es so für mich einfacher zu Verstehen war und ich kein Raum für Erweiterungen brauche. Somit ist ist die professionellere Lösung schon im Chat :)
 
Zurück
Oben