Ablaufzuweisung...

xinix

Level-1
Beiträge
46
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin moin,

ich habe ja nun viel über CASE & Co, dank Eurer Hilfe dazugelernt und rumprobiert. Ich komme damit auch super gut klar. Nun stellt sich bei den Probeprogrammierungen meiner Wasseraufbereitung für die Teichanlage folgende Aufgabe, bei der Ich noch mal einen guten Rat bräuchte...

Ausgangssituation:

Es gibt zwei verschieden Filterzyklen, die sich aus folgenden Funktionen zusammen setzen:

Funktion Filtern ( über eine pumpe x_P1 )
Funktion Spülen ( über eine Pumpe x_P2 )
Funktion Pause

Dieses wollte ich als Betriebsart-Enumeratinswert anlegen

jede dieser Betriebsarten wollte ich in eine CASE packen. Soweit so gut.

Nun ist es aber so, dass sich sowohl die Betriebszeiten als auch die eigentliche Ablauffolge der Betriebsarten mit einem Aufruf steuern möchte.

Beispiel: Die Anlage geht in Betribszustand und soll dann folgende Blöcke aufrufen:

Block I
60min Pause

Block II
20min Filtern
30sec Spülen
20min Filtern
30sec Spülen
30min Filtern
30sec Spülen
180sec Filtern

Block III
60min Pause

Block 2 und 3 soll dann x-mal wiederholt werden bis ein besonderer Block alle x Zyklen dazwischen kommt. Dieser dient zum Auswurf der Filterspülung in den Gulli... :)

Block Auswurf:

60min Filtern
30sec Spülen
3min Filtern
30sec Spülen
180sec Filtern

und wieder von vorn...

ich hoffe man wird schlau draus und es wird nich zu kompliziert darauf zu antworten ?!?

Danke!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Für solche rein zeitgesteuerten Abläufe kann man sich schon einen eigenen, erweiterten TON-FB bauen, z. B. so:
Code:
TYPE enSecTONState :  (* Ausgabestatus für fbSecTON *)
    (
    Off,     (* Timer läuft nicht *)
    Busy,   (* Timer läuft *)
    Done   (* Timer ist abgelaufen *)
    );
END_TYPE

FUNCTION_BLOCK fbSecTON (* TON mit Soll-/Istwert in Sekunden *)
VAR_INPUT
    In:BOOL;             (* Timer-Start, wie TON.In *)
    PTSec:UDINT;      (* Zeitsollwert in Sekunden *)
END_VAR
VAR_OUTPUT
    State:enSecTONState;  (* Status, s. oben *)
    ETSec:UDINT;               (* Abgelaufene Zeit in Sekunden *)
END_VAR
VAR
    Timer:TON;                   (* Interner Timer *)
END_VAR
(* fbSecTON-Anweisungsteil *)
Timer(In:=In,
         PT:=UDINT_TO_TIME(PTSec*1000));
IF In
THEN
    IF Timer.Q
    THEN
        State:=Done;
    ELSE
        State:=Busy;
    END_IF;
ELSE
    State:=Off;
END_IF;
ETSec:=TIME_TO_UDINT(Timer.ET)/1000;

(* Aufrufbeispiel im Programm *)

BlockIISecTON(In:=Block=BlockII,
                     PtSec:=4470);   (* Gesamtzeit für BlockII *);
if BlockIISecTON.State=Busy
THEN
   CASE BlockIISecTON.ETSec of
      0..1199:       (* Filtern *);
      1200..1229: (* Spülen *);
      1230..2429: (* Filtern *);
       (* usw. *)
       ELSE
          (* Spülen und Filtern ausschalten *)
          (* Bei abgelaufener Zeit Block umschalten *)
         IF BlockIISecTON.State=Done
         THEN
            Block:=BlockIII;
         END_IF;
   END_CASE;
END_IF;
 
Danke für das tolle Beispiel und Deine Mühe!

Kann ich soweit ganz gut nachvollziehen, da es gut an die Frage angelehnt ist. Werde ich mich mal am WE ausgiebig mit beschäftigen.

Kann ich den Ablauf eigentlich auch stoppen und Rücksetzten? Ich meine wenn ich das "Teichkraftwerk" mal anhalte und neu starte.

Sorry kann ich so auf dem ersten Blick nicht erkennen....

Danke!
 
...es gibt viele Wege nach Rom..
meine Weg wäre mit AS zum Ziel zu gelangen.
Dort kannst du auch mit SFC arbeiten, d.h. Kette anhalten, Reset, Anzeige aktueller Schritt, Tippbetrieb sind damit ganz schnell zu realisieren
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Kann ich den Ablauf eigentlich auch stoppen und Rücksetzten? Ich meine wenn ich das "Teichkraftwerk" mal anhalte und neu starte.
Rücksetzen schon, mit In:=False, wie bei einem normalen TON auch. Wenn Du den Zeitablauf aber nicht ab-, sondern nur unterbrechen willst, wäre ein TON als interner Timer des eigenen FB's nicht meine erste Wahl. Dann würde ich das Ganze eher auf einem Programmzykluszähler aufbauen.
 
Einfach gemacht: Pack deine Abläufe - wie gewohnt in eine Enum-Variable - Jeder Schritt ist ein Zustand.

ZB.

B1_Pause
B2_Filtern01

B2_Spuelen01
...

B3_Pause
B4_Auswurf

Du kannst nun vom Zustand B2_xxxx zu B4_Auswurf springen, wenn du eine bestimmte Zahl B2 gefahren hast. Das ist dann einfach ein Zähler.Den erhöhst du jedesmal, wenn Block 3 den letzten Schritt erreicht hat. Am Anfang von Block 2 fragst du dann, ob der Zähler gross genug ist und springst zu B4_Auswurf.

Es ist also ganz einfach :)

Dann brauchts du noch einen TON-Timer. Den musst du nach Benutzung in der If-Abfrage für den Zustandswechsel zurücksetzen:

timer(in:=False);
timer(in:=True);

Und schon funkt er auch im nächsten Zustand.
 
Zuletzt bearbeitet:
Also ich habe mir das eben mal genau angeschaut...

...das ist ja alles der MEGA HAMMMMMMEEERRR! Werde gleich mal loslegen... Mal schauen wo die Reise hin geht....

Danke für die Tipps!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Dann brauchts du noch einen TON-Timer. Den musst du nach Benutzung in der If-Abfrage für den Zustandswechsel zurücksetzen:

timer(in:=False);
timer(in:=True);

Und schon funkt er auch im nächsten Zustand.

Wenn ich das richtig verstanden habe, setze ich die TON Zeit auch erst im jeweiligen CASE?
 
Zurück
Oben