TIA Schrittkette mit Wartezeit zwischen den Schritten

KleinerLehrling

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

Als SPS Neuling bin ich gerade dabei meine erste Schrittkette umzusetzen, komme jedoch auf keinen grünen Zweig.

Ich möchte ganz simpel, dass eine Drehachse sich für eine gewisse Zeit in die eine und anschließende in die andere Richtung dreht.
Hier dachte ich, könne ich die Einschaltverzögerung nutzen, doch da "IN" immer aktiv ist, wenn in den jeweiligen Case gesprungen wird, zählt die Zeit nicht erneut auf 5s und schaltet den Ausgang stattdessen sofort durch.

Ich habe viel probiert und gelesen, doch ich komme gerade einfach nicht weiter. Sehr wahrscheinlich ist es keine große Sache oder die Methode ist für meinen Anwendungsfalls sowieso ungeeignet. Wie auch immer, vielen Dank für jegliche Hilfe :).

Liebe Grüße!


Code:
REGION Dauerlauf Start
    
    #R_TRIG_Dauerlauf_Start(CLK := "DB_4_Ansteuerung".b_HMI_Start_Dauerlauf,
                            Q => #R_TRIG_Dauerlauf_Start.Q);
    
    
    IF #R_TRIG_Dauerlauf_Start.Q = TRUE
        AND
        "DB_4_Ansteuerung".b_HMI_Automatikbetrieb = TRUE
    THEN
        #b_Dauerlauf_gestartet := 1;
        #Schrittnummer.Aktueller_Schritt := 0;
      
        
    END_IF;
    
END_REGION

REGION Schrittkette Dauerlauf
    // Statement section REGION
    
    CASE #Schrittnummer.Aktueller_Schritt OF
        0:  // Drehen im Uhrzeigersinn
            
            #TON_Dauerlauf_Drehen(IN := #b_Dauerlauf_gestartet,
                                   PT := t#5s,
                                   Q => #b_TON_Drehen_abgelaufen);
            
            IF "DB_4_Ansteuerung".b_HMI_STOP_Dauerlauf = TRUE
            THEN
                #Schrittnummer.Aktueller_Schritt := 88;
                
            END_IF;
            
            IF #b_TON_Drehen_abgelaufen = TRUE
            THEN
                #b_Dauerlauf_gestartet := 0;
                #b_test := 1;
                "b_Drehen" := 1;
                #Schrittnummer.Aktueller_Schritt := #Schrittnummer.Aktueller_Schritt + 1;
                
            END_IF;
            
            
        1:  // Drehen gegen den Uhrzeigersinn
            
            #TON_Dauerlauf_DrehenG(IN := #b_test,
                                  PT := t#5s,
                                  Q => #b_TON_DrehenG_abgelaufen);
            
            IF "DB_4_Ansteuerung".b_HMI_STOP_Dauerlauf = TRUE
            THEN
                #Schrittnummer.Aktueller_Schritt := 88;
                
            END_IF;
            
            IF #b_TON_DrehenG_abgelaufen = TRUE
            THEN
                #b_test := 0;
                "b_DrehenG" := 1;
                #Schrittnummer.Aktueller_Schritt := 0;
                
            END_IF;
            
    END_CASE;
 
Die Zeiten auf jedenfall außerhalb der Case-Anweisung aufrufen. Eine Zeit benötigt eine Flanke am Input, um zu starten, also den Übergang von low auf high, aber wenn sie selbst nur zeitweise aufgerufen wird, sieht sie diese Flenke u.U. niemals. Die Zeit steuerst du mit Variablen an, die du im Case setzt und rücksetzt.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Die Zeiten auf jedenfall außerhalb der Case-Anweisung aufrufen. Eine Zeit benötigt eine Flanke am Input, um zu starten, also den Übergang von low auf high, aber wenn sie selbst nur zeitweise aufgerufen wird, sieht sie diese Flenke u.U. niemals. Die Zeit steuerst du mit Variablen an, die du im Case setzt und rücksetzt.
Man kann Zeiten auch in der CASE lassen, dann muss jedoch mit RESET_TIMER der Timer beim ersten Aufruf des Schritts bzw. nach einem Schritt wechsel gelöscht werden.
 
Zuletzt bearbeitet:
Man kann Zeiten auch in der CASE lassen, dann muss jedoch mit RESET_TIMER der Timer beim ersten Aufruf des Schritts bzw. nach einem Schritt wechsel gelöscht werden.
Ich mag, was das angeht, ein Pessimist sein, aber für mich geht der bedingte Aufruf von Timer und Flanken FBs, bis auf gaaaaanz wenige Ausnahmen gar nicht.
Das dies keine gute Idee ist wird einem hier im Forum viel zu oft bewiesen. Zumal es Steuerungshersteller gibt bei denen der Timer nicht automatisch im Hintergrund läuft, sondern dieser muss aktiv zyklisch aufgerufen werden.
 
Zuletzt bearbeitet:
Dein Problem kommt daher, dass der IN des Timers nie 0 wird.
Bei Schrittketten musst du immer aufpassen bei den Schrittwechseln (Immer in einem Zyklus denken):

Zyklus x: Schritt 0
- Der Timer hat IN auf true und läuft fertig.
- Du setzt zwar #b_Dauerlauf_gestartet auf 0, das bekommt der vorher aufgerufene Timer aber in diesem Zyklus nicht mehr mit
- Du setzt dann #b_test := 1 und den Schritt auf 1

Zyklus x+1:
- Springt jetzt in Schritt 1 rein
- Timer wird aufgerufen, direkt wieder mit IN (#b_test) auf true



Ich mache das auch immer so, dass ich Timer und Funktionen unterhalb der Case aufrufe.
Gerade wenn man sich mit der Aufruf-Logik noch nicht so auskennt und die Timer mehrfach verwendet werden.
Außerdem würde ich nur 1 Variable zum versorgen des IN verwenden, sonst kann es wieder zu Überschneidungen kommen.
Weiters würde ich den Ausgang Q nicht auf eine Variable (und wenn doch muss diese statisch sein) legen, sondern im Code direkt .Q abfragen.

Ich lege es immer so an:
TON_WasAuchImmer :TON;
bTON_WasAuchImmer :BOOL;

- bTON_WasAuchImmer wird in den Schritten wo ich ihn brauche TRUE geschalten,
- Zum Weiterschalten wird TON_WasAuchImmer.Q verwendet
- Wenn der Schritt verlassen wird (bzw. bei INIT oder ERROR Schritt) auf FALSE.
- TON_WasAuchImmer wird unten mit IN := bTON_WasAuchImmer aufgerufen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@Ralle
Danke sehr, wenn man drüber nachdenkt, logisch :D - nun funktioniert es (y).

@LehnerTh
Danke für die sehr ausführliche Antwort, mir war bewusst, dass der IN nicht auf 0 geht, jedoch wusste ich zu dem Zeitpunkt nicht, wie ich das anstelle.
Außerdem würde ich nur 1 Variable zum versorgen des IN verwenden, sonst kann es wieder zu Überschneidungen kommen.
Es sind 2 verschiedene TONs, oder missverstehe ich dich dabei?
Ist es "egal" ob unter- oder oberhalb? Bzw. weshalb bevorzugst du unterhalb?
 
Ah ja stimmt, habe das G übersehen, Problem ist aber das gleiche ;)

Prinzipiell ist es egal, du "verlierst" einen Zyklus.
Steht der Aufruf oberhalb, wird der Timer mit der BOOL-Variable erst im Zyklus+1 gestartet, dafür schaltet das verwendete .Q direkt.
Steht er unterhalb, wird der Timer mit der BOOL-Variable im gleichen Zyklus gestartet, dafür schaltet das verwendete .Q erst im Zyklus+1.
 
Zurück
Oben