TYPE "UDT_MELDEEINTRAG"
VERSION : 0.1
STRUCT
Melde_Nr : INT ; (* Nr. der Meldung *)
Zeitstempel : DATE_AND_TIME; (* Zeitstempel des Auftretens der Meldung *)
Meldetext : STRING[20]; (* Meldetext *)
END_STRUCT;
END_TYPE
FUNCTION_BLOCK MELDEARCHIV_CHRON
TITLE = 'MELDEARCHIV_CHRON'
NAME : MLDGARCC
VERSION : '0.1'
AUTHOR : TWI
(* Meldearchiv (z.B. für Anzeige an Bedienpanels)
---------------------------------------------------
In ein Meldearchiv wird bei Störung ein Eintrag mit aktuellem Zeitstempel sowie dem Störmeldetext eingetragen.
Geht die Störung, so wird der Eintrag aus der Liste entfernt und nachfolgene Meldungen rücken nach vorne, sodass
die Meldeliste immer in chronologischer Reihenfolge ist.
Die neueste Meldung steht immer am Index 1 der Liste.
Kommen oder gehen viele Meldungen in einem Zyklus so kann dies die Zykluszeit erheblich erhöhen, da hier eine große Anzahl von
Kopieroperationen in einer Schleife durchgeführt werden! Deswegen die Stringlänge auf die benötigte Menge kürzen, oder
die Werte für MAX_ANZ_GEKOMMEN / MAX_ANZ_GEGANGEN entsprechend heruntersetzen. *)
CONST
MAX_EINTRAEGE := 49 + 1;
TEXT_LEN := 20;
(* Maximale Anzahl der verarbeitbaren Meldungen pro Aufruf (Zyklus) *)
MAX_ANZ_GEKOMMEN := 20;
MAX_ANZ_GEGANGEN := 20;
END_CONST
VAR_INPUT
Aktuelle_Zeit : DATE_AND_TIME;
END_VAR
VAR_IN_OUT
Stoerung : ARRAY [1..MAX_EINTRAEGE] OF BOOL; (* als IN_OUT damit nur POINTER übergeben wird *)
Stoertext : ARRAY [1..MAX_EINTRAEGE] OF STRING[TEXT_LEN]; (* als IN_OUT damit nur POINTER übergeben wird *)
Meldearchiv : ARRAY [1..MAX_EINTRAEGE] OF UDT_MELDEEINTRAG;
END_VAR
VAR_TEMP
i : INT;
j : INT;
anz_gekommen : INT; (* Zur Begrenzung der in einem Zyklus zu verarbeitenden Meldungen bei Meldeschauer *)
anz_gegangen : INT;
gegangen : BOOL;
gekommen : BOOL;
gefunden_pos : INT;
gefunden : BOOL;
END_VAR
VAR
Stoerung_alt : ARRAY [1..MAX_EINTRAEGE] OF BOOL; (* Letzter Zustand der Variable *)
anz : INT; (* Anzahl der Einträge im Meldearchiv *)
END_VAR
(********************************************************************************************)
(* Anweisungsteil *)
anz_gekommen := 0;
anz_gegangen := 0;
FOR i := 1 TO MAX_EINTRAEGE BY 1 DO
(* Auf Flanken prüfen *)
IF Stoerung[i] = true AND Stoerung_alt[i] = false THEN
gekommen := true;
anz_gekommen := anz_gekommen + 1;
ELSIF Stoerung[i] = false AND Stoerung_alt[i] = true THEN
gegangen := true;
anz_gegangen := anz_gegangen + 1;
ELSE
gegangen := false;
gekommen := false;
END_IF;
(* Meldeschauerbegrenzung *)
IF anz_gekommen > MAX_ANZ_GEKOMMEN THEN
RETURN;
ELSIF anz_gegangen > MAX_ANZ_GEGANGEN THEN
RETURN;
END_IF;
Stoerung_alt[i] := Stoerung[i]; (* Für nächsten Zyklus merken *)
(******************* Eintragen in Meldearchiv ***********************************************)
IF gekommen THEN
(* Alle Einträge um eins nach hinten schieben *)
FOR j := anz TO 1 BY -1 DO
Meldearchiv[j + 1] := Meldearchiv[j];
END_FOR;
anz := anz + 1;
Meldearchiv[1].Melde_Nr := i;
Meldearchiv[1].Zeitstempel := Aktuelle_Zeit;
Meldearchiv[1].Meldetext := Stoertext[i];
(********************* Austragen aus Meldearchiv ********************************************)
ELSIF gegangen THEN
(* Eintrag suchen *)
gefunden := false;
FOR j := 1 TO anz DO
IF Meldearchiv[j].Melde_Nr = i THEN
gefunden := true;
gefunden_pos := j;
EXIT;
END_IF;
END_FOR;
IF gefunden THEN
(* Alle nachfolgenden Meldungen rücken um eins nach vorne *)
FOR j := gefunden_pos TO (anz - 1) DO
Meldearchiv[j] := Meldearchiv[j + 1];
END_FOR;
(* Letzten Eintrag zurücksetzen *)
Meldearchiv[anz].Melde_Nr := 0;
Meldearchiv[anz].Zeitstempel := DATE_AND_TIME#1990-01-01-00:00:00.0;
Meldearchiv[anz].Meldetext := '';
anz := anz - 1; (* Archiv um eins verkürzen *)
END_IF;
END_IF;
(********************************************************************************************)
END_FOR;
END_FUNCTION_BLOCK