Timer auf 0 setzen

der_NooB

Level-2
Beiträge
285
Reaktionspunkte
8
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Profis,

ich habe eine Frage: Ich habe ein Programm geschrieben, bei dem meine Motoren jeweils eine bestimmte Laufzeit haben und dann ausgeschaltet werden sollen, wenn die Zeit abgelaufen ist.

Das funktioniert jedoch nur am Anfang einmal, und dann wird die Zeit nicht wieder auf 0 gesetzt. Ich habe versucht, dies mit ET zu erzwingen, aber es funktioniert nicht.

Ich bin dankbar für eure Erklärungen.
003.png
 
Das ist einer der Klassiker bei den Fehlern, der bedingte Aufruf von Timern oder Flankenauswertungen.
Ein TON-Timer startet bei einer positiven Flanke. Du setzt in 30 zwar die Eingänge der Timer zurück, rufst diese aber nicht auf, daher bekommt der Timer davon nichts mit und denkt beim nächsten Aufruf mit IN = TRUE, dass dieser nie FALSE war.
Die Ausführung des Timers sollte immer außerhalb von Bedingungen und ähnlichem erfolgen, lediglich die Eingänge sollten innerhalb von Bedingungen und CASE-Anweisungen gesetzt werden.
Das Schreiben von ET lösch bitte raus.
Nachtrag: Da war einmal Bedingungen zu viel, das musste Eingänge heißen.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
1) Du musst den Timer auch aufrufen mit IN:=false (oder PT:=0ms). Nur beschreiben des Timer.Ausgangs ET tut dem Timer gar nichts.
2) Es ist keine gute Idee, Timer nur bedingt (nur manchmal) aufzurufen, weil dann bekommen sie Signalwechsel am IN-Eingang nicht mit. Timer müssen in jedem Zyklus-Durchlauf aufgerufen werden.
 
Das ist einer der Klassiker bei den Fehlern, der bedingte Aufruf von Timern oder Flankenauswertungen.
Ein TON-Timer startet bei einer positiven Flanke. Du setzt in 30 zwar die Eingänge der Timer zurück, rufst diese aber nicht auf, daher bekommt der Timer davon nichts mit und denkt beim nächsten Aufruf mit IN = TRUE, dass dieser nie FALSE war.
Die Ausführung des Timers sollte immer außerhalb von Bedingungen und ähnlichem erfolgen, lediglich die Bedingungen sollten innerhalb von Bedingungen und CASE-Anweisungen gesetzt werden.
Das Schreiben von ET lösch bitte raus.
Ach so, super! Es hat funktioniert. Vielen Dank für die anhaltende Hilfe.
 
1) Du musst den Timer auch aufrufen mit IN:=false (oder PT:=0ms). Nur beschreiben des Timer.Ausgangs ET tut dem Timer gar nichts.
2) Es ist keine gute Idee, Timer nur bedingt (nur manchmal) aufzurufen, weil dann bekommen sie Signalwechsel am IN-Eingang nicht mit. Timer müssen in jedem Zyklus-Durchlauf aufgerufen werden.
Ach so, deswegen haben die manchmal gesponnen. Danke! so meinst stimmt004.png
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Du hast es leider immer noch nicht ganz begriffen.
Du rufst jetzt zwar die Timer, wie empfohlen, außerhalb der Bedingung auf, gleichzeitig aber auch noch innerhalb der CASE-Anweisung. Das ist jetzt zwar nicht schlimm, aber doppelt gemoppelt.
In der CASE-Anweisung musst Du nur die Eingänge setzen, soweit die Zeit immer gleich bleiben soll halt nur IN.
 
Habe noch gesehen, ändere mal bei IN die Logik "iSchrittnummer_Muehle = ..." in ein einfaches TRUE ab, man muss es ja nicht komplizierter als notwendig machen. Der Timer soll ja auf jeden Fall gestartet werden.
 
Du hast es leider immer noch nicht ganz begriffen.
Du rufst jetzt zwar die Timer, wie empfohlen, außerhalb der Bedingung auf, gleichzeitig aber auch noch innerhalb der CASE-Anweisung. Das ist jetzt zwar nicht schlimm, aber doppelt gemoppelt.
In der CASE-Anweisung musst Du nur die Eingänge setzen, soweit die Zeit immer gleich bleiben soll halt nur IN.
Meinst du so, auch wenn die Bedingung die SK-Nummer wäre? Der erste Satz beginnt mit SK 00.006.png
Habe noch gesehen, ändere mal bei IN die Logik "iSchrittnummer_Muehle = ..." in ein einfaches TRUE ab, man muss es ja nicht komplizierter als notwendig machen. Der Timer soll ja auf jeden Fall gestartet werden.
Stimmt, Da die SK-Nummer sowieso durchlaufen wird, bin ich jetzt etwas verwirrt. Soll ich meine Timer in der SK und außerhalb aufrufen oder nur außerhalb mit IN und PT?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Du rufst die Timer nur außerhalb auf. Da die Zeit immer gleich bleibt in Deinem Fall mit PT := XXX, aber ohne IN.
Den Eingang IN setzt Du innerhalb der CASE-Anweisung auf TRUE oder FALSE, dafür brauchst Du aber keine Bedingung, sondern kannst einfach TRUE nehmen, oder später halt FALSE.
 
Ich habe mir gerade mal Dein Programm genauer angesehen. Kann es sein, dass Du überhaupt nicht weißt, wie Timer eigentlich funktionieren? Hast Du Dir mal die Hilfetexte zu Timern durchgelesen? ET brauchst Du nicht. Lies Dir bitte mal den Hilfetext durch und pass Dein Programm an. Als Tipp werfe ich hier mal "Q" in den Raum.
Und auch wie Du in den nächsten Schritt schaltest ist mehr als seltsam.
Wieso setzt Du eine Variable auf TRUE die Du dann auf TRUE abfragst? Das Setzen der Variablen und die Abfrage kannst Du Dir doch komplett schenken, wenn die Zeit abgelaufen ist soll es weitergehen.
 
Zuletzt bearbeitet:
Oderb du rufst sie ausserhalb auf mit der von dir schon verwendeten Bedingung der Schrittnummer und schaltest dann, wenn der Zeitwert erreicht ist auf den nächsten Schritt. Dadurch ist dann der Timer auch wieder "auf 0".
Ich meine aber mich erinnern zu können, dass wir dieses Thema schon so 3 bis 7 mal mit dir hatten - beratungs-resistent ?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Oderb du rufst sie ausserhalb auf mit der von dir schon verwendeten Bedingung der Schrittnummer und schaltest dann, wenn der Zeitwert erreicht ist auf den nächsten Schritt. Dadurch ist dann der Timer auch wieder "auf 0".
Ach so, du meinst, den Schritt 40 brauche ich gar nicht, da die ja logischerweise eh ausschalten, wenn es auf den nächsten Schritt springt.
Ich habe mir gerade mal Dein Programm genauer angesehen. Kann es sein, dass Du überhaupt nicht weißt, wie Timer eigentlich funktionieren? Hast Du Dir mal die Hilfetexte zu Timern durchgelesen? ET brauchst Du nicht. Lies Dir bitte mal den Hilfetext durch und pass Dein Programm an.
Meinst du, was die Software rot markiert hat? Wenn ja, ich weiß, dass es keinen Sinn macht, aber ich dachte, warum nicht versuchen?

Aber wenn du den Vergleich zwischen ET und meinem DW meinst, dann habe ich am Anfang versucht, mit Q zu schalten, aber es hat nicht gemacht, was ich wollte. Ich denke, es lag bestimmt daran, dass ich einen anderen Fehler hatte.
Als Tipp werfe ich hier mal "Q" in den Raum.

Und auch wie Du in den nächsten Schritt schaltest ist mehr als seltsam.
Wieso setzt Du eine Variable auf TRUE die Du dann auf TRUE abfragst? Das Setzen der Variablen und die Abfrage kannst Du Dir doch komplett schenken, wenn die Zeit abgelaufen ist soll es weitergehen.
Ach so, du meinst, ohne IF-Anweisung nur mit den Timern zu arbeiten.

Das macht Sinn.

Ich denke, heute bin ich nicht klar im Kopf, und ich muss mich mehr mit den Timern vertraut machen.

Ich hänge mein Programm an, der wie geplant funktioniert, und versuche jetzt, das umzusetzen, was du mir empfohlen hast.

Danke.007.png
Ich meine aber mich erinnern zu können, dass wir dieses Thema schon so 3 bis 7 mal mit dir hatten - beratungs-resistent ?
mit Timern noch nicht 🫢
 
Funktioniert es denn jetzt ? Aus meiner Sicht hast du immer noch denselben Fehler drin wie ganz zu Anfang - also beratungs-resistent ... sorry.
Wenn du denn Code als Text posten würdest und nicht als Screen shot dann würde ich ihn mal so ändern wie ich meine.
Das Einbauen eines Timer-Bausteins in eine bedingte Bearbeitung ist immer eine dumme Sache - macht man eigentlich nicht.
 
Ich weiß nicht, wie man mich so oft missverstehen kann.
Ich hatte geschrieben, dass Du den Timer in der CASE-Anweisung NICHT aufrufen sollst, sondern dort nur die Eingänge setzt. Die Eingänge eines FBs setzt man genauso wie man eine andere Variable setzt, also zum Beispiel fbTON_MV_Mue_EVG.IN := TRUE.
Eine Abfrage auf Q = TRUE, also zum Beispiel IF fbTON_MV_Mue_EVG.Q THEN sollte eigentlich funktionieren.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich weiß nicht, wie man mich so oft missverstehen kann.
Ich hatte geschrieben, dass Du den Timer in der CASE-Anweisung NICHT aufrufen sollst, sondern dort nur die Eingänge setzt. Die Eingänge eines FBs setzt man genauso wie man eine andere Variable setzt, also zum Beispiel fbTON_MV_Mue_EVG.IN := TRUE.
Eine Abfrage auf Q = TRUE, also zum Beispiel IF fbTON_MV_Mue_EVG.Q THEN sollte eigentlich funktionieren.
Ach so,

das habe ich leider nicht so verstanden, sondern so, wie ich es gemacht habe.
Code:
fbTon_Luftmotor_M2_EVG(IN := TRUE);
Im Endeffekt machen die das Gleiche, oder?
vielen lieben Dank ^_^
 
Zuletzt bearbeitet:
Funktioniert es denn jetzt ?
ja :´)
Aus meiner Sicht hast du immer noch denselben Fehler drin wie ganz zu Anfang - also beratungs-resistent ... sorry.
Wenn du denn Code als Text posten würdest und nicht als Screen shot dann würde ich ihn mal so ändern wie ich meine.
Das Einbauen eines Timer-Bausteins in eine bedingte Bearbeitung ist immer eine dumme Sache
In anderen Programmen habe ich extra Aktionen für die Timer gemacht, damit sie immer einsatzbereit sind.
ich hänge an was ich meine
- macht man eigentlich nicht.

Code:
fbTon_Luftmotor_M2_EVG   (PT := DWORD_TO_TIME(dwLM_EVG_1*1000));

fbTon_Luftmotor_M2_AVG   (PT := DWORD_TO_TIME(dwLM_AVG  *1000));

fbTon_Luftmotor_M2_EVG_SK(PT := DWORD_TO_TIME(dwLM_EVG_2_SK*1000));


fbTon_MV_Mue_EVG         (PT := DWORD_TO_TIME(dwMV_AVG*1000));

fbTon_MV_Mue_EVG_2       (PT := DWORD_TO_TIME(dwMV_Mue_EVG_2*1000));


// Schrittkette Lüfter und Bläse

CASE iSchritnummer_Muehle OF


    00: // Zeit um den Lüfter zu starten

       fbTon_Luftmotor_M2_EVG(IN := TRUE);

        IF TIME_TO_DWORD(fbTon_Luftmotor_M2_EVG.et) = dwLM_EVG_1*1000 THEN

            xM2_Mue := TRUE;

            iSchritnummer_Muehle := 10;

        END_IF


    05: // Eine Sekunde in SK um den Lüfter zu starten

        fbTon_Luftmotor_M2_EVG_SK(IN:= TRUE);

        IF TIME_TO_WORD(fbTon_Luftmotor_M2_EVG_SK.ET) = dwLM_EVG_2_SK*1000 THEN

            xM2_Mue := TRUE;

            IF xM2_Mue THEN

                iSchritnummer_Muehle := 10;

            END_IF

        END_IF


    10: // Laufzeit bis der Lüfter stoppt

        fbTon_Luftmotor_M2_AVG(IN := TRUE);

        IF TIME_TO_DWORD(fbTon_Luftmotor_M2_AVG.eT) = dwLM_AVG*1000 THEN

            xM2_Mue := FALSE;

        END_IF

        IF xM2_Mue = FALSE THEN

            iSchritnummer_Muehle := 20;

        END_IF


    20: // Zeit, in der MV einschaltet erstes mal

        fbTon_MV_Mue_EVG(IN := TRUE);

        IF TIME_TO_DWORD(fbTon_MV_Mue_EVG.et) = dwMV_AVG*1000 THEN

            xMv1_Mue := TRUE;

            iSchritnummer_Muehle := 30;

        END_IF


    30: // MV ausschalten und für das zweite Mal einschalten

        xMv1_Mue := FALSE;

        IF iSchritnummer_Muehle = 30 AND NOT xMv1_Mue THEN

            fbTon_MV_Mue_EVG_2(IN := TRUE);

        END_IF


        IF TIME_TO_DWORD(fbTon_MV_Mue_EVG_2.ET) = dwMV_Mue_EVG_2*1000 THEN

            xMv1_Mue := TRUE;

            iSchritnummer_Muehle := 40;

        END_IF


    40: // Zeiten zurücksetzen

        xMv1_Mue := FALSE;

        IF NOT xMv1_Mue AND NOT xM2_Mue THEN

            fbTon_Luftmotor_M2_AVG.IN := FALSE;

            fbTon_Luftmotor_M2_EVG.IN := FALSE;

            fbTon_MV_Mue_EVG.IN := FALSE;

            fbTon_Luftmotor_M2_EVG_SK.IN := FALSE;

            fbTon_MV_Mue_EVG_2.IN := FALSE;


            iSchritnummer_Muehle := 05;

        END_IF


END_CASE
 

Anhänge

  • 20.png
    20.png
    205,4 KB · Aufrufe: 3
  • 21.png
    21.png
    142,9 KB · Aufrufe: 3
Zuletzt bearbeitet von einem Moderator:
Ich habe das jetzt in dem Beitrag mal geändert und die Tags mit eingefügt ...

@der_NooB :
Ich würde die Sache mit den Timern in etwa so umsetzen (und den Rest vom Code habe ich dann auch gleich "ein wenig" verschlankt ;)) :
Code:
fbTon_Luftmotor_M2_EVG   (IN := iSchritnummer_Muehle = 00 ,
                          PT := DWORD_TO_TIME(dwLM_EVG_1*1000));
fbTon_Luftmotor_M2_AVG   (IN := iSchritnummer_Muehle = 10 ,
                          PT := DWORD_TO_TIME(dwLM_AVG  *1000));
fbTon_Luftmotor_M2_EVG_SK(IN := iSchritnummer_Muehle = 05 ,
                          PT := DWORD_TO_TIME(dwLM_EVG_2_SK*1000));


fbTon_MV_Mue_EVG         (IN := iSchritnummer_Muehle = 20 ,
                          PT := DWORD_TO_TIME(dwMV_AVG*1000));
fbTon_MV_Mue_EVG_2       (IN := iSchritnummer_Muehle = 30 ,
                          PT := DWORD_TO_TIME(dwMV_Mue_EVG_2*1000));


// Schrittkette Lüfter und Bläse

CASE iSchritnummer_Muehle OF


    00: // Zeit um den Lüfter zu starten
        IF fbTon_Luftmotor_M2_EVG.Q THEN

            xM2_Mue := TRUE;
            iSchritnummer_Muehle := 10;

        END_IF


    05: // Eine Sekunde in SK um den Lüfter zu starten
        IF TfbTon_Luftmotor_M2_EVG_SK.Q THEN

            xM2_Mue := TRUE;
            iSchritnummer_Muehle := 10;

        END_IF


    10: // Laufzeit bis der Lüfter stoppt
        IF bTon_Luftmotor_M2_AVG.Q THEN

            xM2_Mue := FALSE;
            iSchritnummer_Muehle := 20;

        END_IF


    20: // Zeit, in der MV einschaltet erstes mal
        IF fbTon_MV_Mue_EVG.Q THEN

            xMv1_Mue := TRUE;
            iSchritnummer_Muehle := 30;

        END_IF


    30: // MV ausschalten und für das zweite Mal einschalten

        xMv1_Mue := FALSE;

        IF fbTon_MV_Mue_EVG_2.Q THEN

            xMv1_Mue := TRUE;
            iSchritnummer_Muehle := 40;

        END_IF


    40: // Zeiten zurücksetzen

        xMv1_Mue := FALSE;
        xMv2_Mue := FALSE;
         iSchritnummer_Muehle := 05;

END_CASE
 
Zurück
Oben