Frage bez. FOR-Schleife (Beckhoff CX9000-001)

apmIng

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

Seit gestern sitze ich an einer FOR-Schleife, die einfach nicht funktionieren will. Da ich bei SPS erst seit Kurzem dabei bin, weiss ich nicht mehr Rat.

Aufgabe: in einer FOR-Schleife soll eine beliebige Anzahl von kurzen Flashes (mit irgendeiner Lampe o.ä.) generiert werden. Ich übergebe der Schleife eine positive ganze Zahl und erwarte, dass die Schleife mir eine entspr. Anzahl von kurzen (1s) Blinks liefert, mit 1s Pause zwischen den Blinks.

Die Schleife sieht so aus:

FOR (counter := 1 TO myNumber BY 1) DO
timer (IN:= TRUE, PT:=T#1s);
IF (timer.Q = TRUE) THEN
greenLightControl := TRUE;
END_IF;

timer (IN:= TRUE, PT:=T#1s);
IF (timer.Q = TRUE) THEN
greenLightControl := FALSE;
END_IF;
END_FOR;

Komischerweise wird bei der Abarbeitung der Schleife der counter sofort auf myNumber gesetzt und die Pausen, die in der Schleife mit dem timer generiert werden sollten, werden ignoriert. Für sich alleine, liefert der timer aber schon eine Pause, die ja auch bei zyklischem Ablauf berücksichtigt werden sollte.

Habe ich da was falsch verstanden? Alles andere klappt einwandfrei.

Danke für Eure Hilfe!
 
Hi

Eine FOR -Schleife bleibt im Zylkus nicht stehen. Das macht Dir WHILE.
Die FOR-Schleife hat in jedem Zyklus hochgezähtl daher bist Du sofort auf dem Sollwert gelandet.

Ich würds damit probieren:

Code:
IF counter <= mynumber THEN
timer (IN:= TRUE AND NOT timer2.Q, PT:=T#1s);
IF (timer.Q = TRUE) THEN
greenLightControl := TRUE;
END_IF;

timer2 (IN:= timer.Q, PT:=T#1s);
IF (timer2.Q = TRUE) THEN
greenLightControl := FALSE;
END_IF;

trig(CLK:=timer2.Q );

IF trig.Q THEN
COUNTER := COUNTER +1;
END_IF

END_IF
Timer : TON;
Timer2 : TOF;
trig : F_trig;

Ist nur schnell gebastelt, kannste noch verbessern.
Sollte aber funktionieren.

Du hast für Pause und Betrieb beide Mal den gleichen Timer verwendet.


Gruss Anis
 
Zuviel Werbung?
-> Hier kostenlos registrieren
... ich würde nicht innerhalb einer Schleife und auch nicht innerhalb einer Abfrage einen Timer-Aufruf unterbringen.
Ich kann jetzt nicht für Beckhoff & Co. sprechen aber innerhalb einer S7 würde in SCL dieser Aufruf unter den genannten Bedingungen auch nicht funktionieren.

Gruß
Larry
 
Hi
Eine FOR -Schleife bleibt im Zylkus nicht stehen. Das macht Dir WHILE.
Die FOR-Schleife hat in jedem Zyklus hochgezähtl daher bist Du sofort auf dem Sollwert gelandet.
Danke für die Info.

> Eine FOR -Schleife bleibt im Zylkus nicht stehen.

Was ich nicht verstehe - die FOR-Schleife läuft doch in jedem SPS-Zyklus komplett durch - bis sie beendet ist und erst dann läuft SPS-Zyklus weiter. Oder irre ich mich? Weil - wie kann eine FOR-Schleife nicht stehen bleiben (in diesem Fall für die o.g. Sekunden) wenn sie doch durch eben den timer dazu gezwungen wird? Zwingt etwa ein SPS-Zyklus die FOR-Schleife dazu, den Anweisungsblock zu ignorieren, wenn dessen Ausführung länger dauert, als ein SPS-Zyklus?

Bei WHILE/REPEAT-Schleife bekomme ich immer (auch bei billigsten Beispielen) einen SPS-Timeout und muss die CPU resetten, da diese sonst weder im Config, noch im Runmode startet.

Komme aus der C++/Java - Welt und hatte bisher leider recht wenig mit zyklischer Programmausführung zu tun. Habe hier sechs Bücher über SPS-Programmierung liegen (u.a. von Tiegelkamp, Kaftan, Wellenreuther und Krätzig) - nirgendwo wird es auf das Problem eingegangen - daher vermute ich einen DAU.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
... ich würde nicht innerhalb einer Schleife und auch nicht innerhalb einer Abfrage einen Timer-Aufruf unterbringen.
Ich kann jetzt nicht für Beckhoff & Co. sprechen aber innerhalb einer S7 würde in SCL dieser Aufruf unter den genannten Bedingungen auch nicht funktionieren.

Gruß
Larry

Yep, genau.
Und selbst wenn du die For-Schleife nutzen willst/sollst, z.Bsp. aus Übungsgründen, dann mußt du das Hochzählen des Counters auch in irgendeiner Form mit dem Timer verknüpfen, denn Counter wird bei jedem Zyklusdurchgang einfach hochgezählt und ist somit ruckzuck durch.
 
@ LL

ich würde nicht innerhalb einer Schleife und auch nicht innerhalb einer Abfrage einen Timer-Aufruf unterbringen
Stimmt. Geb ich Dir Recht. Funzen tuts, is aber ned unbedingt schön.

Beispiel:
Code:
IF counter <= mynumber THEN
do_job := TRUE;
ELSE
do_job := FALSE;
END_IF
@ampIng

Du hast Deine Frage selber beantwortet. Die FOR-Schleife läuft durch.

Wie Ralle gesagt hat:
....denn Counter wird bei jedem Zyklusdurchgang einfach hochgezählt und ist somit ruckzuck durch.

Die WHILE-Schleife bleibt solange hängen, bis sie "beendet" ist.
Da Du innerhalb Deiner WHILE-Schleife zwei Timer aufrufst, mit einer gesamten Wartezeit von 2 Sekunden dauert die WHILE-Schleife auch mindestens 2 Sekunden. Somit bleibt der Zyklus für diese Zeit auch in der Schleife stehen.
Ergebnis:
Dein Zyklus dauert mind. 2 Sekunden was eine Zykluszeitüberschreitung zur Folge hat und den WatchDog auslöst.


Anis
 
Zuletzt bearbeitet:
Du bist wohl noch nicht ganz in der Echtzeit-Welt angekommen. (In diesem Sinne Willkommen! :smile: )

Wenn du im TwinCAT eine Zykluszeit von 1ms hast, hast du nur wenige us Zeit, um die Berechnungen zu erledigen. Vergiss die WHILE Schleife! Den Timeout Fehler erhälst du, wenn dein Programm nicht innerhalb von den paar us abgearbeitet wird! Für deine Verzögerung von 2 Sekunden musst du eine andere Lösung finden. (Siehe oben)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@TE:
das Stichwort ist hier "zyklische Programm-Bearbeitung" was hier heißt : "es wird immer alles abgearbeitet" und "der Zyklus muß irgendwann beendet sein".

Die Lösung für dich könnte sein, dass du die Timer direkt zu einem Taktgeber verschaltest und dessen Impulse nach einem Start-Impuls zählst.
Ist der Zähler = Wunschwert löscht du den Start wieder und damit die Freigabe dafür die Impulse auf einen Ausgang (oder ähnlich) zu geben ...

Gruß
Larry
 
@ LL

Was ja eigentlich (sofern ich Dich richtig verstehe) etwa dem entspricht,
was ich bereits als Lösung (Beitrag #2) im Code vorgeschlagen habe.
Inkl. der Verbesserung nach Deinem berechtigten Einwand (Beitrag #7).

Oda??

Gruss
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Was ich nicht verstehe - die FOR-Schleife läuft doch in jedem SPS-Zyklus komplett durch - bis sie beendet ist und erst dann läuft SPS-Zyklus weiter. Oder irre ich mich? Weil - wie kann eine FOR-Schleife nicht stehen bleiben (in diesem Fall für die o.g. Sekunden) wenn sie doch durch eben den timer dazu gezwungen wird?
Da hast Du ein grundsätzliches Verständnisproblem. Die Schleife wird schon in jedem SPS-Zyklus komplett durchlaufen, aber beim Aufruf eines Timers bleibt das Programm nicht an dieser Stelle stehen, bis der Timer abgelaufen ist. Beim Aufruf wird nur geprüft, ob die Zeit abgelaufen ist, und in diesem Fall Timer.Q=True. Wenn das nicht im aktuellen SPS-Zyklus der Fall ist, dann vielleicht im Nächsten.
 
Dann fass ich es nochmals zusammen. So müsst es gehen:

Code:
VAR
    Enable                    : BOOL;
    myNumber               : INT;
    Time_On                 :TON;
    Time_Off                 :TOF;
    Counter                  : INT;
    Trig                        : F_TRIG;
    greenLightControl     : BOOL;
    Cmd_DoJob             : BOOL;
END_VAR


IF Counter < mynumber THEN
    Cmd_DoJob  := TRUE;
ELSE
    Cmd_DoJob  := FALSE;
END_IF


Time_On (IN:=Enable AND Cmd_DoJob AND NOT Time_Off.Q, PT:=T#1s);
Time_Off (IN:= Time_On.Q, PT:=T#1s);

greenLightControl :=  Enable AND NOT Time_Off.Q;


Trig(CLK:=Time_Off.Q );

IF Trig.Q THEN
    Counter := Counter +1;
END_IF

IF NOT Cmd_DoJob THEN
    Enable := FALSE;
END_IF



Achtung, je nach Verwendung muss Enable ein In/Out sein.
 
Eine Frage habe ich aber noch.....

Falls er die FOR-Schleife für die Schule oder so verwenen muss....
Ralle hat etwas gesagt vonwegen das Hochzählen mit einem Timer verknüpfen...

Wie kann denn der Counter einr FOR-Schleife beeinflusst werden?
Da bin ich jetzt ehrlichgesagt überfragt. Dafür verwende ich FOR/WHILE
zu selten, zumindest in zyklischen SPS-Programmen.

Gruss
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Eine FOR- oder WHILE-Schleife würde ich hier gar nicht hernehmen sondern exakt es so machen, wie in deinem Code :
Code:
IF Trig.Q THEN
    Counter := Counter +1;
END_IF ;
... allerdings bei näherem hinsehen würde ich das Ganze noch mit einer Flanke würzen, damit nicht die x-Takte gleich mit den ersten Trig.Q zu Stande kommen ...

Gruß
Larry
 
Oops - Schande über mich ... :(
Trig ist ja gar nicht der Timer - sorry, da hatte ich (nochmals) nicht richtig hingesehen ...
 
Ach was....

War doch jetzt ne nette Ablenkung frei nach....
... und weil es nur eine nette Ablenkung war muß man sich wohl auch keine Mühe geben ... :rolleyes:

Was mich generell an diesem ST stört:
Es verführt unerfahrene Programmierer unheimlich zu ereignisorientierter Programmierung mit überwiegend bedingten Zuweisungen, was zu lauter solchen undurchdachten und unvollständigen Programmen mit logischen Fehlern führt, wie hier und in anderen Threads leider immer wieder zu sehen ist. Es wird ohne Plan einfach losgetippt - "nur schnell gebastelt" - der Anwender wird zum ewigen Betatester, weil diese Programme aus dem Entwurfsstadium nie herauskommen - auch wenn noch so viel nachgeflickt wird. :(

Harald
 
Zurück
Oben