WHILE / RETURN mit ablaufender Zeit

hoOLLOow

Level-1
Beiträge
30
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
habe ein kleines Problem. Ich will entweder eine RETURN-
oder eine WHILE-Schleife nutzen, die 30 Sekunden überprüft wird.

Mit einer WHILE sieht es bis jetzt wie folgt aus, jedoch funktioniert es nicht!

Deklarationen:
Code:
PROGRAM MAIN
VAR
    zaehler: TIME;
    var1: UDINT;
    strg: STRING;
END_VAR
Die Anweisung is nur ein Bespiel:
Code:
var1:=1;
zaehler:=t#30000ms;
WHILE zaehler<>t#0ms DO
    Var1 := Var1*2;
    zaehler := zaehler-t#1000ms;
END_WHILE
strg:= UDINT_TO_STRING(var1);
Das Ergebnis bekomme ich nur leider nicht nach erst 30 Sekunden, sondern sofort.
Code:
var1 = 16#40000000
zaehler = T#0ms
zaehler = T#0ms
var1 = 16#40000000
zaehler = T#0ms

strg = '1073741824'           var1 = 16#40000000

Was mache ich falsch?

Gruß Mathias
 
Du benutzt wie du so schön schreibst einen Zähler! Dieser wieder in der While-Schleife incrementiert. Dies geschieht allerdings ohne jegliche Zeitverzögerung, auch wenn der Zähler "Zeitwerte" besitzt.

Mein Vorschlag wäre es, dass du einen Timer benutzt. Möchtest du Multiplikation nur jede Sekunde durchführen? Dann würde ich den Timer immer für 1 Sek laufen lassen und nach Ablauf die Multiplikation durchführen. Das ganze könntest du dann 30 Mal wiederholen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
habe ein kleines Problem. Ich will entweder eine RETURN-
oder eine WHILE-Schleife nutzen, die 30 Sekunden überprüft wird.

Mit einer WHILE sieht es bis jetzt wie folgt aus, jedoch funktioniert es nicht!

Deklarationen:
Code:
PROGRAM MAIN
VAR
    zaehler: TIME;
    var1: UDINT;
    strg: STRING;
END_VAR
Die Anweisung is nur ein Bespiel:
Code:
var1:=1;
zaehler:=t#30000ms;
WHILE zaehler<>t#0ms DO
    Var1 := Var1*2;
    zaehler := zaehler-t#1000ms;
END_WHILE
strg:= UDINT_TO_STRING(var1);
Das Ergebnis bekomme ich nur leider nicht nach erst 30 Sekunden, sondern sofort.
Ist Klar, weil die Eingangsbedingung schon nach dem ersten Zyklus nicht mehr gilt.
DIe While-Schleife wird solange durchlaufen (in einem Zyklus) bis die Abbruchbedingung verfällt. Vergleichbar mit einer FOR-Schleife.
While ist hier denkbar ungünstig.

Probier mal:
Code:
VAR
  ton1: TON;
END_VAR

ton1(IN := NOT ton1.Q , PT :=t#30s);
IF ton1.Q THEN
    ....  (* Aktion *)
END_IF
Diese Aktion wird alle 30 Sekunden ausgeführt.
edit: hab's nochmal geändert (vereinfacht) :)
 
Zuletzt bearbeitet:
Jetzt ist nur die Frage, ob er seine Aktion dreißig Sekunden lang oder erst nach dreißig Sekunden ausführen will.
 
Für "30 Sekunden lang" fragt man einfach ab:
Code:
IF ton1.IN THEN
    (* Aktion *)
END_IF
Diese Anweisung wird immer 30 Sekunden lang durchlaufen (endlos)

Für eine einmalig Ausführung nach 30 Sekunden setzt man:
Code:
ton1(IN := NOT ton1.Q [B]AND (*Bedingung*)[/B] , PT :=t#30s);
IF ton1.Q THEN
   (* Aktion *)
[B]   (*Bedingung := FALSE *)[/B]
END_IF
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Jetzt ist nur die Frage, ob er seine Aktion dreißig Sekunden lang oder erst nach dreißig Sekunden ausführen will.

Na jede Sekunde einmal. Nicht erst nach 30 Sekunden.

Die Sache von Trinitaucher mit dem TON-Timer bin ich am basteln.

Schreibe dann nochmal wenns klappt.
 
So siehts es erstmal aus...
Code:
PROGRAM MAIN
VAR
    var1        : UDINT;
    strg        : STRING;
    Zeit        : TON;
END_VAR
Code:
var1:=1;
    Zeit(IN := NOT Zeit.Q , PT :=t#30s);
    IF Zeit.Q THEN
            Var1 := Var1*2;
    END_IF
strg:= UDINT_TO_STRING(var1);

So nun fehlt nur noch ein Zähler für die Berechnung der Var1-Berechnung.
 
Zuletzt bearbeitet:
Dein Code wird immer nach 30 Sekunden ausgeführt, wobei var1 in jedem Zyklus =1 ist, außer alle 30 Sekunden. Dann ist var = 2 ;).
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Probiers mal damit:
Code:
IF zaehler < 30 THEN
 Timer(IN:= TRUE, PT:= t#1s);
 IF Timer.Q THEN
  Timer(IN:= FALSE);
  var1 := var1*2;
  zaehler := zaehler + 1;
 END_IF
END_IF
IF zaehler = 30 THEN
 strg := UDINT_TO_STRING(var1);
END_IF
 
Das ist immer noch nicht die optimale Lösung.
Im Endeffekt soll folgendes geschehen:
(die var1-Berechnung ist ja nur eine Beispiel-Anweisung)
Die Schleife soll 10min lang alle 10 Sekunden oder jede Sekunde versuchen eine Mail über AMS zu senden (SMTP-Funktionsblock).

Nur Fragen ich weiß...
Vielleicht ist jetzt klar was wann wo passieren soll.

Aber ich baue auch noch weiter.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Meine Version macht 30 Sekunden lang jede Sekunde eine Var1-Berechnung.

Wenn du nun 10 Minuten lang alle 10 Sekunden eine Berechung durchführen willst, dann stellst du beim Timer PT:= t#10s ein. Zusätzlich benutzt du dann folgende Bedingungen, damit das ganze 10 Sekunden läuft:
1. zaehler < 60
2. zaehler = 60

Wenn du jede Sekunde eine Berechnung machen willst, dann kannst du den timer so lassen und nimmst stattdessen folgende Bedingungen:
1. zaehler < 600
2. zaehler = 600
 
oder:
Code:
IF Zaehler = 0 (* oder anderer Beginn *) THEN
    var1:=1;
END_IF

Zeit(IN := NOT Zeit.Q , PT :=t#30s);
IF Zeit.Q THEN
    Var1 := Var1*2;
    Zaehler := Zaehler +1;
END_IF

IF Zaehler > (*Max Wert*) THEN
   strg:= UDINT_TO_STRING(var1);

    (* evtl. noch *)
   Zaehler := 0;
   var1 := 0
END_IF
Alle 30 Sekunden wird "Zaehler" hochgezählt. Nach Erreichen des Max-Wertes wird die Aktion ausgeführt und ggf. noch die Zaehler zurückgesetzt
 
Meine Version macht 30 Sekunden lang jede Sekunde eine Var1-Berechnung.

Wenn du nun 10 Minuten lang alle 10 Sekunden eine Berechung durchführen willst, dann stellst du beim Timer PT:= t#10s ein. Zusätzlich benutzt du dann folgende Bedingungen, damit das ganze 10 Sekunden läuft:
1. zaehler < 60
2. zaehler = 60

Wenn du jede Sekunde eine Berechnung machen willst, dann kannst du den timer so lassen und nimmst stattdessen folgende Bedingungen:
1. zaehler < 600
2. zaehler = 600

Klingt verdammt logisch. Danke.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Die Schleife soll 10min lang alle 10 Sekunden oder jede Sekunde versuchen eine Mail über AMS zu senden (SMTP-Funktionsblock).
Du kannst auch einfach über einen stink normalen Zähler die Anzahl der SPS-Zyklen mitzählen. Die Zykluszeit ist ja bekannt.

Beispiel mit 10ms Zykluszeit, jede 1 Sekunde eine Aktion, 10Minuten Ausführungszeit gesamt:
Code:
Zahler1 := Zahler1  + 1;

IF Zahler2 < 600 THEN
   IF Zahler1 > 100 THEN
     (* Nachricht verschicken *)
     Zahler1 := 0;
     Zahler2 := Zahler2 + 1;
   END_IF
END_IF

edit: mehrmals angepasst ;-)
 
Zuletzt bearbeitet:
Du kannst auch einfach über einen stink normalen Zähler die Anzahl der SPS-Zyklen mitzählen. Die Zykluszeit ist ja bekannt.
Meinst du diese zykluszeit. hab ich eben aus dem Manual des BC9000, was ich nutze, rausgesucht.

Reaktionszeit des BC9000
ADS Zeit(ms)
TCP 23 bis 50 ms + Task-Zeit auf dem BC9000 (Jitter)
UDP 2 bis 3 ms + Task-Zeit auf dem BC9000 (Jitter)

Also kann ich von 50ms ausgehen. Im System-Manager (System-Konfiguration >> Task1) habe ich Zyklusticks 80 (80.000ms)
eingestellt. hat das etwas damit zu tun?

Ist zwar ein bisschen Off-Topic, aber ich hoffe diese kurze Nebenfrage passt hier mal eben so schnell rein.
 
Zuletzt bearbeitet:
Zurück
Oben