taylor1982
Level-2
- Beiträge
- 34
- Reaktionspunkte
- 1
FUNCTION_BLOCK FB100
//***********************************************************************************************************************************
//Der FB durchsucht einen DB mit 1024 Störmeldungen und gibt die Störnummer am Ausgang aus.
//Sind mehrere Störungen auf "TRUE" so wird jede Störnummer min. 2sek im Wechsel nacheinander angezeigt.
//Der Baustein ist noch nicht getestet!!!!!!!!!!!!
//***********************************************************************************************************************************
AUTHOR : Thomas
NAME : Anz Störnummer
VERSION : '1.0'
//vom 13.11.2012
//Vereinbarungsteil (Deklaration):
//--------------------------------
//Eingangsvariablen
VAR_INPUT
Sperr_DB : BLOCK_DB ;
Sperr_Nr : INT := 0 ;
Takt_10Hz : BOOL := False ;
END_VAR
//---------------------------------
//Ausgangsvariablen
VAR_OUTPUT
Anz_Sperr_Nr : INT := 0 ;
END_VAR
//---------------------------------
//Durchgangsvariablen
VAR_IN_OUT
END_VAR
//---------------------------------
//Statische Variablen:
VAR
HM : ARRAY [0..7] OF BOOL ; // Noch nicht eingesetzte Hilfsmerker: 4; 5; 6; 7;
Step : INT := 0 ; // Schrittindex DB bitweise nach "TRUE" durchsuchen
Word_Index : INT := 0 ;
Bit_Index : INT := 0 ;
Bit_Maske : WORD:= 0 ;
Anz_Stop : BOOL:= FALSE ; // Sperrt den Wechsel der Anzeige für die min Anzeigedauer (2sek)
Min_Anzeigezeit : INT := 0 ;
END_VAR
//---------------------------------
//Temporäre Variablen:
VAR_TEMP
Wordnummer : INT ;
Wordadresse : INT ;
Bitnummer : INT ;
END_VAR
//----------------------------------
//Sprungmarken:
LABEL
SPRUNG_001 ;
No_Step_0 ;
No_Step_1 ;
No_Step_2 ;
No_Step_3 ;
END_LABEL
//Anweisungsteil (Programm):
//***********************************************************************************************************************************
BEGIN
// Durchsuche DB Bits nach "TRUE" und Ausgabe der Störnummern im 2Sek Takt
//--------------------------------------------------------------------------
// Schritt 0: Word_Index auf Ende? Wenn ja setze Index auf Anfang
//--------------------------------------------------------------------
IF Step <> 0 THEN // Kein Schritt 0
GOTO No_Step_0 ; // Überspringe Schritt 0
END_IF ;
IF Bit_index > 15 THEN // Hat der Bit_index max überschritten
Bit_index := 0 ; // setze Bit_index auf 0
Word_index:= Word_index+2 ; // erhöhe Word_index um 2( Wortadressierung nur über gerade Bytenummern)
Step := 1 ; // Gehe zu Schritt 1
END_IF ;
No_Step_0:
// Schritt 1: Bit_Index auf Ende ? Wenn ja Setze Bit_index auf "0" und erhöhe Word_index um "2"
//-----------------------------------------------------------------------------------------------
IF Step <> 1 THEN // kein Schritt 1
GOTO No_Step_1 ; // Überspringe Schritt 1
END_IF ;
IF Word_index > 127 THEN // Hat der Word_index max überschritten
Word_index := 0 ; // Setze Word_index auf 0
Step := 2 ; // Gehe zu Schritt 2
END_IF ;
No_Step_1:
// Schritt 2: Leerschritt
//-----------------------------------------------------------------------------
IF Step <> 2 THEN // Kein Schritt 2
GOTO No_Step_2 ; // überspringe Schritt 2
Step := 3 ; // setze Schritt 3
END_IF ;
No_Step_2:
// Schritt 3: Durchsuche Sperrword Bitweise auf "TRUE" und berechne und übergebe Störnummer an Anzeige
//--------------------------------------------------------------------------------------------------------
IF Step <> 3 OR Anz_Stop THEN // Kein Schritt 3
GOTO No_Step_3 ; // überspringe Schritt 3
END_IF ;
Bit_Maske := 2#0000_0000_0000_0001 ; // In Bitmaske das erste Bit auf "1" setzen
Bit_Maske := ROL(IN:=Bit_Maske, N:=Bit_index) ; // Die "1" auf den richtigen Platz rotieren
IF (Sperr_DB.DW[Word_index] AND Bit_Maske) = 0 THEN // Falls der Bitvergleich "0" ist
Bit_index := Bit_index+1 ; // erhöhe den Bit_index für die nächste Bitüberprüfung
Step := 0 ; // Setze Schritt 0
GOTO No_Step_3 ; // Überspringe Schritt 3
ELSIF Anz_Stop = TRUE THEN // Minimale Anzeigezeit ist noch nicht abgelaufen
GOTO No_Step_3 ; // überspringe Schritt 3
ELSIF (Sperr_DB.DW[Word_index] AND Bit_Maske) <> 0 THEN // Bitvergleich auf nicht Signal "0"
Anz_Sperr_Nr := ((Word_index/2)*16)+(Bit_index+1) ; // Wenn Bitvergleich "1" berechne Störnummer und sende zur Anzeige
Anz_Stop := TRUE ; // Sperre die Anzeige einer weiteren Störnummer bis die min. Anzeigezeit die Freigabe erteilt
Bit_index := Bit_index+1 ; // Erhöhe den Bit_index für die nächte Bitüberprüfung
Step := 0 ; // Zurück zu Schritt 0
END_IF ;
No_Step_3:
// Minimale Anzeigezeit (2Sekunden)
//------------------------------------
IF Anz_Stop = TRUE AND Takt_10Hz = TRUE AND HM[3] = FALSE THEN // Erzeuge Zähltakt
HM[3] := TRUE ;
Min_Anzeigezeit := Min_Anzeigezeit+1 ; // Zähle Zeitspeicher hoch
ELSIF Takt_10Hz = FALSE THEN
HM[3] := FALSE ; // Rücksetze Hilfsmerker
END_IF ;
IF Min_Anzeigezeit = 20 THEN // Abfrage ob 2 sek erreicht
Anz_Stop := FALSE ; // Wenn ja rücksetze Anzeigen Stop
Min_Anzeigezeit := 0 ; // und rücksetze Zeitspeicher
END_IF ;
//Programmende
END_FUNCTION_BLOCK
Wieviele Bits können gleichzeitig gesetzt sein?
Harald
FUNCTION_BLOCK FB100
//***********************************************************************************************************************************
//Der Baustein setzt oder rücksetzt ein Bit in einem DB mit 1024 boolschen Variablen. Die Anwahl des Bits erfolgt über eine Int-Zahl
//am Eingang :"Sperr_Nr". Die Nummerierung und Adressierung sind gleich mit den Störmeldungen im WinCC flexible. Über "Set" wird das
//gewählte Bit gesetzt und über "Reset" wieder zurückgesetzt. "Reset_All" setzt alle Bits im DB auf Signal "0".
//Am Ausgang "Anz_Sperr_Nr" werden nacheinander alle auf "TRUE" gesetzten Bits für mindestens 2sek angezeigt.
//***********************************************************************************************************************************
AUTHOR : 'T.H.'
NAME : 'Sperren'
VERSION : '1.0'
//vom 17.11.2012
//Vereinbarungsteil (Deklaration):
//--------------------------------
//Eingangsvariablen
VAR_INPUT
Sperr_DB : BLOCK_DB ;
Sperr_Nr : INT := 0 ;
Set : BOOL := False ;
Reset : BOOL := False ;
Reset_All : BOOL := False ;
Takt_10Hz : BOOL := False ;
END_VAR
//---------------------------------
//Ausgangsvariablen
VAR_OUTPUT
Anz_Sperr_Nr : INT := 0 ;
END_VAR
//---------------------------------
//Durchgangsvariablen
VAR_IN_OUT
END_VAR
//---------------------------------
//Statische Variablen:
VAR
Loeschindex : INT := 0 ;
HM : ARRAY [0..7] OF BOOL ; // Noch nicht eingesetzte Hilfsmerker: 4; 5; 6; 7;
Word_Index : INT := 0 ;
Bit_Index : INT := 0 ;
Anz_Stop : BOOL:= FALSE ; // Sperrt den Wechsel der Anzeige für die min Anzeigedauer (2sek)
Min_Anzeigezeit : INT := 0 ;
END_VAR
//---------------------------------
//Temporäre Variablen:
VAR_TEMP
Wordnummer : INT ;
Wordadresse : INT ;
Bitnummer : INT ;
Bit_Maske : WORD ;
END_VAR
//----------------------------------
//Sprungmarken:
LABEL
No_Choose ;
No_Anz ;
END_LABEL
//Anweisungsteil (Programm):
//***********************************************************************************************************************************
BEGIN
// Setze / Rücksetze Sperre
//---------------------------
IF Sperr_Nr <= 0 OR Sperr_Nr > 1024 THEN // Freigabe
GOTO No_Choose ;
ELSIF Sperr_Nr > 0 THEN // Berechnung Wordadresse
Wordadresse := ((Sperr_nr-1)/16)*2 ;
Bitnummer := (Sperr_Nr-1)-(Wordnummer*16) ; // Berechnung Bitnummer
END_IF ;
IF Set = TRUE AND HM[0] = FALSE THEN // Erzeuge Setzimpuls
HM[0] := TRUE ;
Bit_Maske := 2#0000_0000_0000_0001 ; // Setze Alle Bits auf "False" nur Bit 0 auf "TRUE"
Bit_Maske := ROL(IN:= Bit_Maske, N:=Bitnummer) ; // Rotiere "TRUE" auf richtige Position
Sperr_DB.DW[Wordadresse] := Bit_Maske OR Sperr_DB.DW[Wordadresse]; // Schreibe Ergebnis in Datenbaustein ohne andere Bits zu verändern
ELSIF Set = FALSE AND HM[0] = TRUE THEN
HM[0] := FALSE ; // Hilfsmerker Flanke zurücksetzen
END_IF ;
// Rücksetzen Bit
IF Reset = TRUE AND HM[1] = FALSE THEN // Erzeuge Rücksetzimpuls
HM[0] := TRUE ;
Bit_Maske := 2#1111_1111_1111_1110 ; // Setze alle Bits auf "TRUE" nur Bit 0 auf "False"
Bit_Maske := ROL(IN:= Bit_Maske, N:=Bitnummer) ; // Rotiere "FALSE" auf richtige Position
Sperr_DB.DW[Wordadresse] := Bit_Maske AND Sperr_DB.DW[Wordadresse] ; // Schreibe Ergebnis in Datenbaustein ohne die anderen Bits zu beeinflussen
ELSIF Reset = FALSE AND HM[1] THEN
HM[1] := FALSE ; // Hilfsmerker Flanke zurücksetzen
END_IF ;
No_Choose:
// Alles zurücksetzen
//---------------------
IF Reset_All = TRUE AND HM[2] = FALSE THEN // Impuls setzen für Reset All
HM[2] := TRUE ;
Loeschindex := 0 ; // Setze Löschindex einmalig auf 0
REPEAT
Sperr_DB.DW[Loeschindex] := 0 ; // Schreibe 0 in Datenwort
Loeschindex := Loeschindex +2 ; // Index erhöhen für nächstes Datenwort
UNTIL Loeschindex = 128 // Bis Endadresse erreicht ist
END_REPEAT ;
ELSIF Reset_All = FALSE THEN // Rücksetze Hilfsmerker
HM[2] := FALSE ;
END_IF ;
// Durchsuche DB Bits nach "TRUE" und Ausgabe der Sperrnummern im 2Sek Takt
//--------------------------------------------------------------------------
IF Word_index = 126 AND Bit_index > 15 AND Anz_Stop = TRUE THEN // Word_index und Bit_index auf max und Mindestanzeigedauer ist noch nicht abgelaufen
GOTO No_Anz ; // Überspringe Suchfunktion
END_IF ;
// Bit_Index über Ende? Wenn ja Setze Bit_index auf "0" und erhöhe Word_index um "2"
//-----------------------------------------------------------------------------------------------
IF Bit_index > 15 THEN // Hat der Bit_index max überschritten
Bit_index := 0 ; // setze Bit_index auf 0
Word_index:= Word_index+2 ; // erhöhe Word_index um 2( Wortadressierung nur über gerade Bytenummern)
END_IF ;
// Word_Index auf Ende? Wenn ja setze Index auf Anfang
//--------------------------------------------------------------------
IF Word_index >= 128 THEN // Hat der Word_index max überschritten
Word_index := 0 ; // Setze Word_index auf 0
Anz_Sperr_Nr := 0 ; // Lösche Anzeige
END_IF ;
// Durchsuche Sperrword Bitweise auf "TRUE" und berechne und übergebe Sperrnummer an Anzeige
//--------------------------------------------------------------------------------------------------------
Bit_Maske := 2#0000_0000_0000_0001 ; // In Bitmaske das erste Bit auf "1" setzen
Bit_Maske := ROL(IN:=Bit_Maske, N:=Bit_index) ; // Die "1" auf den richtigen Platz rotieren
IF (Sperr_DB.DW[Word_index] AND Bit_Maske) = 0 THEN // Falls der Bitvergleich "0" ist
Bit_index := Bit_index+1 ; // erhöhe den Bit_index für die nächste Bitüberprüfung
GOTO No_Anz ; // Überspringe Ausgabe auf Anzeige
ELSIF (Sperr_DB.DW[Word_index] AND Bit_Maske) <> 0 AND Anz_Stop = FALSE THEN // Bitvergleich auf nicht Signal "0"
Anz_Sperr_Nr := ((Word_index/2)*16)+(Bit_index+1) ; // Wenn Bitvergleich "1" berechne Sperrnummer und sende zur Anzeige
Anz_Stop := TRUE ; // Sperre die Anzeige einer weiteren Sperrnummer bis die min. Anzeigezeit die Freigabe erteilt
Bit_index := Bit_index+1 ; // Erhöhe den Bit_index für die nächte Bitüberprüfung
END_IF ;
No_Anz:
// Minimale Anzeigezeit (2Sekunden)
//------------------------------------
IF Anz_Stop = TRUE AND Takt_10Hz = TRUE AND HM[3] = FALSE THEN // Erzeuge Zähltakt
HM[3] := TRUE ;
Min_Anzeigezeit := Min_Anzeigezeit+1 ; // Zähle Zeitspeicher hoch
ELSIF Takt_10Hz = FALSE THEN
HM[3] := FALSE ; // Rücksetze Hilfsmerker
END_IF ;
IF Min_Anzeigezeit = 20 THEN // Abfrage ob 2 sek erreicht
Anz_Stop := FALSE ; // Wenn ja rücksetze Anzeigen Stop
Min_Anzeigezeit := 0 ; // und rücksetze Zeitspeicher
END_IF ;
//Programmende
Ich habe endlich mal den Baustein getestet und noch so einige Fehler gefunden und verschiedene Sachen geändert.
Für die gesuchte Funktion ist eigentlich nur der untere Teil wichtig.(Ab // Durchsuche DB Bits nach "TRUE" und.....)
Die Anzeigezeit könnte man ja dann sogar rausnehmen und den Ausgang in einen FIFO schieben.
Gute Nacht
Code:FUNCTION_BLOCK FB100 //*********************************************************************************************************************************** //Der Baustein setzt oder rücksetzt ein Bit in einem DB mit 1024 boolschen Variablen. Die Anwahl des Bits erfolgt über eine Int-Zahl //am Eingang :"Sperr_Nr". Die Nummerierung und Adressierung sind gleich mit den Störmeldungen im WinCC flexible. Über "Set" wird das //gewählte Bit gesetzt und über "Reset" wieder zurückgesetzt. "Reset_All" setzt alle Bits im DB auf Signal "0". //Am Ausgang "Anz_Sperr_Nr" werden nacheinander alle auf "TRUE" gesetzten Bits für mindestens 2sek angezeigt. //*********************************************************************************************************************************** AUTHOR : 'T.H.' NAME : 'Sperren' VERSION : '1.0' //vom 17.11.2012 //Vereinbarungsteil (Deklaration): //-------------------------------- //Eingangsvariablen VAR_INPUT Sperr_DB : BLOCK_DB ; Sperr_Nr : INT := 0 ; Set : BOOL := False ; Reset : BOOL := False ; Reset_All : BOOL := False ; Takt_10Hz : BOOL := False ; END_VAR //--------------------------------- //Ausgangsvariablen VAR_OUTPUT Anz_Sperr_Nr : INT := 0 ; END_VAR //--------------------------------- //Durchgangsvariablen VAR_IN_OUT END_VAR //--------------------------------- //Statische Variablen: VAR Loeschindex : INT := 0 ; HM : ARRAY [0..7] OF BOOL ; // Noch nicht eingesetzte Hilfsmerker: 4; 5; 6; 7; Word_Index : INT := 0 ; Bit_Index : INT := 0 ; Anz_Stop : BOOL:= FALSE ; // Sperrt den Wechsel der Anzeige für die min Anzeigedauer (2sek) Min_Anzeigezeit : INT := 0 ; END_VAR //--------------------------------- //Temporäre Variablen: VAR_TEMP Wordnummer : INT ; Wordadresse : INT ; Bitnummer : INT ; Bit_Maske : WORD ; END_VAR //---------------------------------- //Sprungmarken: LABEL No_Choose ; No_Anz ; END_LABEL //Anweisungsteil (Programm): //*********************************************************************************************************************************** BEGIN // Setze / Rücksetze Sperre //--------------------------- IF Sperr_Nr <= 0 OR Sperr_Nr > 1024 THEN // Freigabe GOTO No_Choose ; ELSIF Sperr_Nr > 0 THEN // Berechnung Wordadresse Wordadresse := ((Sperr_nr-1)/16)*2 ; Bitnummer := (Sperr_Nr-1)-(Wordnummer*16) ; // Berechnung Bitnummer END_IF ; IF Set = TRUE AND HM[0] = FALSE THEN // Erzeuge Setzimpuls HM[0] := TRUE ; Bit_Maske := 2#0000_0000_0000_0001 ; // Setze Alle Bits auf "False" nur Bit 0 auf "TRUE" Bit_Maske := ROL(IN:= Bit_Maske, N:=Bitnummer) ; // Rotiere "TRUE" auf richtige Position Sperr_DB.DW[Wordadresse] := Bit_Maske OR Sperr_DB.DW[Wordadresse]; // Schreibe Ergebnis in Datenbaustein ohne andere Bits zu verändern ELSIF Set = FALSE AND HM[0] = TRUE THEN HM[0] := FALSE ; // Hilfsmerker Flanke zurücksetzen END_IF ; // Rücksetzen Bit IF Reset = TRUE AND HM[1] = FALSE THEN // Erzeuge Rücksetzimpuls HM[0] := TRUE ; Bit_Maske := 2#1111_1111_1111_1110 ; // Setze alle Bits auf "TRUE" nur Bit 0 auf "False" Bit_Maske := ROL(IN:= Bit_Maske, N:=Bitnummer) ; // Rotiere "FALSE" auf richtige Position Sperr_DB.DW[Wordadresse] := Bit_Maske AND Sperr_DB.DW[Wordadresse] ; // Schreibe Ergebnis in Datenbaustein ohne die anderen Bits zu beeinflussen ELSIF Reset = FALSE AND HM[1] THEN HM[1] := FALSE ; // Hilfsmerker Flanke zurücksetzen END_IF ; No_Choose: // Alles zurücksetzen //--------------------- IF Reset_All = TRUE AND HM[2] = FALSE THEN // Impuls setzen für Reset All HM[2] := TRUE ; Loeschindex := 0 ; // Setze Löschindex einmalig auf 0 REPEAT Sperr_DB.DW[Loeschindex] := 0 ; // Schreibe 0 in Datenwort Loeschindex := Loeschindex +2 ; // Index erhöhen für nächstes Datenwort UNTIL Loeschindex = 128 // Bis Endadresse erreicht ist END_REPEAT ; ELSIF Reset_All = FALSE THEN // Rücksetze Hilfsmerker HM[2] := FALSE ; END_IF ; // Durchsuche DB Bits nach "TRUE" und Ausgabe der Sperrnummern im 2Sek Takt //-------------------------------------------------------------------------- IF Word_index = 126 AND Bit_index > 15 AND Anz_Stop = TRUE THEN // Word_index und Bit_index auf max und Mindestanzeigedauer ist noch nicht abgelaufen GOTO No_Anz ; // Überspringe Suchfunktion END_IF ; // Bit_Index über Ende? Wenn ja Setze Bit_index auf "0" und erhöhe Word_index um "2" //----------------------------------------------------------------------------------------------- IF Bit_index > 15 THEN // Hat der Bit_index max überschritten Bit_index := 0 ; // setze Bit_index auf 0 Word_index:= Word_index+2 ; // erhöhe Word_index um 2( Wortadressierung nur über gerade Bytenummern) END_IF ; // Word_Index auf Ende? Wenn ja setze Index auf Anfang //-------------------------------------------------------------------- IF Word_index >= 128 THEN // Hat der Word_index max überschritten Word_index := 0 ; // Setze Word_index auf 0 Anz_Sperr_Nr := 0 ; // Lösche Anzeige END_IF ; // Durchsuche Sperrword Bitweise auf "TRUE" und berechne und übergebe Sperrnummer an Anzeige //-------------------------------------------------------------------------------------------------------- Bit_Maske := 2#0000_0000_0000_0001 ; // In Bitmaske das erste Bit auf "1" setzen Bit_Maske := ROL(IN:=Bit_Maske, N:=Bit_index) ; // Die "1" auf den richtigen Platz rotieren IF (Sperr_DB.DW[Word_index] AND Bit_Maske) = 0 THEN // Falls der Bitvergleich "0" ist Bit_index := Bit_index+1 ; // erhöhe den Bit_index für die nächste Bitüberprüfung GOTO No_Anz ; // Überspringe Ausgabe auf Anzeige ELSIF (Sperr_DB.DW[Word_index] AND Bit_Maske) <> 0 AND Anz_Stop = FALSE THEN // Bitvergleich auf nicht Signal "0" Anz_Sperr_Nr := ((Word_index/2)*16)+(Bit_index+1) ; // Wenn Bitvergleich "1" berechne Sperrnummer und sende zur Anzeige Anz_Stop := TRUE ; // Sperre die Anzeige einer weiteren Sperrnummer bis die min. Anzeigezeit die Freigabe erteilt Bit_index := Bit_index+1 ; // Erhöhe den Bit_index für die nächte Bitüberprüfung END_IF ; No_Anz: // Minimale Anzeigezeit (2Sekunden) //------------------------------------ IF Anz_Stop = TRUE AND Takt_10Hz = TRUE AND HM[3] = FALSE THEN // Erzeuge Zähltakt HM[3] := TRUE ; Min_Anzeigezeit := Min_Anzeigezeit+1 ; // Zähle Zeitspeicher hoch ELSIF Takt_10Hz = FALSE THEN HM[3] := FALSE ; // Rücksetze Hilfsmerker END_IF ; IF Min_Anzeigezeit = 20 THEN // Abfrage ob 2 sek erreicht Anz_Stop := FALSE ; // Wenn ja rücksetze Anzeigen Stop Min_Anzeigezeit := 0 ; // und rücksetze Zeitspeicher END_IF ; //Programmende
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?