Alarmmeldung abwechselnd anzeigen

Crypt0key

Level-2
Beiträge
9
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

folgender Hintergrund:
Ich habe eine Modbus TCP Verbindung zwischen einer S7-1518F und einer Climatix POL638.00 realisiert. Diese ist stabil und ich kann das HoldingRegist, InputRegister, Coils und Inputs lesen bzw. schreiben.

Zusätzlich habe ich ein PopUp erstellt wo der Bediener die Anlage Ein-/Ausschalten, Alarm quittieren etc. kann.

Problem: Es gibt 4 Alarm Worte, Beispiel: Bit0 von Wort 1 = Rotor Störung
Auf dem von mir erstellen PoPup kann jedoch nur ein Alarm angezeigt werden
Muss von Wort auf Integer gewandelt werden, Beispiel: Wort1 Bit0 = Integer 1 , Wort1 Bit 15 = Integer 15 usw.
Der Integer ist dem Wert in der TextListe zugeordnet

Wunsch: Alle aktiven Alarme alle 3 Sekunden abwechselnd anzeigen

Ich habe schon mal angefangen und die einzelnen Bits der Wörter in ein ArrayofBool geschoben und anschließen die einzelnen aktiven Bits in einen Alarm Buffer.
Jetzt müssten die aktiven Bits alle 3 Sekunden abwechselnd "geloopt" werden und dann der Index von dem Array einem Integer zugeordnet werden.
4.png1.png
3.png
Hat jemand eine Idee bzw. einen komplett anderen Lösungsansatz?

Vielen Dank im Voraus!
Gruß
 
Problem: Es gibt 4 Alarm Worte, ...
Wenn ich das richtig deute, geht es hier um 64 AlarmMeldungen, je 16 pro AlarmWort.
... Beispiel: Bit0 von Wort 1 = Rotor Störung
Auf dem von mir erstellen PoPup kann jedoch nur ein Alarm angezeigt werden
Für das PopUp müsstest Du also nacheinander alle 64 Bits prüfen.
Ist ein Bit False oder sind die 3 s einer gültigen AlarmMeldung abgelaufen, kommt die Prüfung des/der nächsten Bits.
Da die Anzeige der anstehenden Alarme jeweils 3 s bestehen bleiben soll, erscheint mir die Verwendung einer FOR-Schleife in der gezeigten Form (das Abklappern von 1 bis 16) nicht so ganz zielführend zu sein.

"AbsichtsErklärung" in SCL-ähnlicher Form und völlig ungetestet:
Code:
// ix  : TEMP, INT
// idx : TEMP, INT
// busyWaiting : TEMP, BOOL 
// activeAlarmNr : STATIC or GLOBAL, INT, 0 :  no alarm active, 1..64 active alarm-nr
// array[ ] STATIC, WORD : 1..64, source-array with none up to max. 64 TRUE elements that is being evaluated
// arrayDisplay[ ] STATIC, WORD : 1..64, destiny-array with none or max. 1 TRUE element at any time

activeAlarmNr := LIMIT( MN := 0, IN := activeAlarmNr, MX := 64 ) ; // shift the alarm-nr into the valid range 0 .. 64

IF activeAlarmNr < 1 THEN
    busyWaiting := FALSE ;
ELSE
    busyWaiting := Array[activeAlarmNr] AND TOF_Timer.Q ;
END_IF ;

IF NOT busyWaiting THEN
    arrayDisplay[activeAlarmNr] := FALSE ;           // deactivate the previously displayed alarm-nr
    
    TOF_Timer.IN := TRUE ;                           // stop the timer if still running and alarm no longer active
    FOR ix := 1 to 64                                // test the next 64 alarm-bits
        idx := ( activeAlarmNr + ix ) MOD 64 + 1 ;   // correct the overflow of idx
        IF Array[idx] THEN                           // if an active alarm is encountered, then ...
            activeAlarmNr := idx ;                   // ... store the alarm-nr
            arrayDisplay[activeAlarmNr] := TRUE ;    // ... and activate display
            
            TOF_Timer.IN  := Array[activeAlarmNr] ;  // start the Timer on negative edge of IN
            EXIT ;
        END_IF ;
    END_FOR ;
    IF ix = 65 THEN activeAlarmNr := 0 ;             // 0 : no alarm active
END_IF ;

Muss von Wort auf Integer gewandelt werden, Beispiel: Wort1 Bit0 = Integer 1 , Wort1 Bit 15 = Integer 15 usw.
Der Integer ist dem Wert in der TextListe zugeordnet
INT ist die laufende Nr der AlarmMldg 1..64 mit der der Text verknüpft werden kann, quasi der Index des Ziel-Arrays.
Wunsch: Alle aktiven Alarme alle 3 Sekunden abwechselnd anzeigen
Die Programmiierung des Timers habe ich geschlabbert bzw. nur angedeutet, da ich im Moment kein brauchbares Beispiel gefunden habe und gleich in die Heia muss. ;)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wunsch: Alle aktiven Alarme alle 3 Sekunden abwechselnd anzeigen
(...)
Hat jemand eine Idee bzw. einen komplett anderen Lösungsansatz?
Hier zwei Bausteine in SCL, die das auf verschiedene Weise für ein 16-Bit Word machen:
Die Bausteine könnte man auf 64 Bit erweitern und im gewünschten Weiterschalt-Intervall (3s) aufrufen.
 
Wenn ich das richtig deute, geht es hier um 64 AlarmMeldungen, je 16 pro AlarmWort.

Für das PopUp müsstest Du also nacheinander alle 64 Bits prüfen.
Ist ein Bit False oder sind die 3 s einer gültigen AlarmMeldung abgelaufen, kommt die Prüfung des/der nächsten Bits.
Da die Anzeige der anstehenden Alarme jeweils 3 s bestehen bleiben soll, erscheint mir die Verwendung einer FOR-Schleife in der gezeigten Form (das Abklappern von 1 bis 16) nicht so ganz zielführend zu sein.

"AbsichtsErklärung" in SCL-ähnlicher Form und völlig ungetestet:
Code:
// ix  : TEMP, INT
// idx : TEMP, INT
// busyWaiting : TEMP, BOOL
// activeAlarmNr : STATIC or GLOBAL, INT, 0 :  no alarm active, 1..64 active alarm-nr
// array[ ] STATIC, WORD : 1..64, source-array with none up to max. 64 TRUE elements that is being evaluated
// arrayDisplay[ ] STATIC, WORD : 1..64, destiny-array with none or max. 1 TRUE element at any time

activeAlarmNr := LIMIT( MN := 0, IN := activeAlarmNr, MX := 64 ) ; // shift the alarm-nr into the valid range 0 .. 64

IF activeAlarmNr < 1 THEN
    busyWaiting := FALSE ;
ELSE
    busyWaiting := Array[activeAlarmNr] AND TOF_Timer.Q ;
END_IF ;

IF NOT busyWaiting THEN
    arrayDisplay[activeAlarmNr] := FALSE ;           // deactivate the previously displayed alarm-nr
   
    TOF_Timer.IN := TRUE ;                           // stop the timer if still running and alarm no longer active
    FOR ix := 1 to 64                                // test the next 64 alarm-bits
        idx := ( activeAlarmNr + ix ) MOD 64 + 1 ;   // correct the overflow of idx
        IF Array[idx] THEN                           // if an active alarm is encountered, then ...
            activeAlarmNr := idx ;                   // ... store the alarm-nr
            arrayDisplay[activeAlarmNr] := TRUE ;    // ... and activate display
           
            TOF_Timer.IN  := Array[activeAlarmNr] ;  // start the Timer on negative edge of IN
            EXIT ;
        END_IF ;
    END_FOR ;
    IF ix = 65 THEN activeAlarmNr := 0 ;             // 0 : no alarm active
END_IF ;


INT ist die laufende Nr der AlarmMldg 1..64 mit der der Text verknüpft werden kann, quasi der Index des Ziel-Arrays.

Die Programmiierung des Timers habe ich geschlabbert bzw. nur angedeutet, da ich im Moment kein brauchbares Beispiel gefunden habe und gleich in die Heia muss. ;)
Vielen Dank schon mal für den Code, sieht schon sehr brauchbar aus, werde ich mir bei Gelegenheit mal genauer ansehen. :)
Was ich jedoch gerade nicht ganz verstehe ist z.B. Array[activeAlarmNr] Wie realisiere ich das in TIA? Ich kann ja kein Array von einem Int erstellen?

Wenn ich das richtig deute, geht es hier um 64 AlarmMeldungen, je 16 pro AlarmWort.
Das ist korrekt!
 
Hier zwei Bausteine in SCL, die das auf verschiedene Weise für ein 16-Bit Word machen:
Die Bausteine könnte man auf 64 Bit erweitern und im gewünschten Weiterschalt-Intervall (3s) aufrufen.
Vielen Dank, werde ich mir ebenfalls mal ansehen! :)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Was ich jedoch gerade nicht ganz verstehe ist z.B. Array[activeAlarmNr] Wie realisiere ich das in TIA? Ich kann ja kein Array von einem Int erstellen?
Du hattest in Beitrag #1 'SCATTER' verwendet und ich hatte unterstellt, dass genau damit eine eventuelle Umsetzung von Bit eines Wortes in ein BOOL-Element eines Array of BOOL gemacht wird bzw. gemacht werden soll. Dieses Kapitel hatte ich in meinem Code ausgelassen und einfach vorausgesetzt, dass das QuellArray und das ZielArray bereits in dieser From (Array Of BOOL) vorhanden sind.
Die Elemente von QuellArray und ZielArray sind nicht INT, sondern BOOL aber der Index der beiden Arrays - über den auf die Elemente zugegriffen wird - ist INT.
Mit meiner Version der FOR-Schleife wollte ich dafür sorgen, dass ...
- ... nach jedem Start eines SchleifenDurchlaufes maximal 64 ArrayElemmente (nämlich maximal alle genau einmal) abgefragt werden. Hier droht nämlich die Entstehung einer EndlosSchleife, wenn keines der 64 Elemente den Status TRUE hat.
- ... nach jedem Start eines SchleifenDurchlaufs nicht mit einer festen IndexNr begonnen wird, sondern mit der IndexNr, die auf die zuletzt angezeigte folgt.
Deshalb wird die Summe aus zwei Zahlen gebildet, die jeweils im Bereich 0..64 (Beginn) bzw. 1..64 (LaufVariable der FOR-Schleife) liegen können und die Summe wird mit dem MOD-Operator dann noch auf den ZahlenBereich 0..63 beschränkt und durch die Addition von 1 in den Bereich 1..64 veschoben.

Der ganz andere LösungsWeg, auf den Harald (PN/DP) hinweist, ist nicht so ganz leicht zu verstehen/nachzuvollziehen.
Wenn man diesen Lösungsweg kennt und versteht, kann dies nur von Vorteil sein. Wenn man diesen Lösungsweg aber programmiert, so bringt man damit die meisten, die ihn zu verstehen suchen, in arge Verlegenheit!
Soll der zu programmierende Baustein eine "black box" werden, um deren Inhalt sich niemand zu kümmern hat, dann ist Haralds Lösung die "direktere" Lösung insofern, als ...
- ... das nächste TRUE-Bit nicht mühsam per "Trial and Error" gesucht werden muss, sondern direkt über die Bildung eines ZweierKomplements und eine UND-Verküpfung berechnet wird.
- ... die Ermittlung der Bit-Nr raffinierterweise die system-interne Umwandlung von FestkommaZahl in GleitkommaZahl "missbraucht". Allerdings dürfte die Wirkungsweise für viele absolut unverständlich sein.
Ja, bei Haralds Vorschlag entfallen ganz einfach zwei mühsame SuchVorgänge (von denen der zweite überhaupt erst durch Weglassen des ersten erforderlich wird) und werden zielgerichtet durch Berechnungen ersetzt. Das macht das Auffinden der nächsten aktiven Meldung sehr elegant und schnell (und leider auch unverständlich).
Eine (FOR-)Schleife sollte hierbei nicht mehr nötig sein.

Übrigens, bei 3 x 16 Bit = 48 Bit, wie in Deiner Anwendung, drängt sich das Arbeiten mit dem DatenTyp LINT (= 64 Bit) auf.
Vorausgesetzt, es liegt eine CPU vor, die den DatenTyp LINT kennt und ausserdem Berechnungen mit LINT-Variablen beherrscht.
Die o.g. Bildung des ZweierKomplements erfordert ...
- ... entweder einerseits die TypeCasts LWORD --> LINT und LINT --> LWORD und das korrekte Ermitteln des Ergebnisses von 'A := -A ;' für LINT-Variablen
- ... oder andererseits die TypeCasts LWORD --> LINT und LINT --> LWORD sowie das korrekte Ermitteln des Ergebnisses einer Addition bzw. Subtraktion und einer Invertierung bzw. Negation bzw. einer XOR-Verknüpfung von LINT-Variablen.
Eine UND-Verknüpfung von LINT-Variablen wird in beiden Fällen benötigt.
Ferner sollte natürlich der DatenTyp LREAL für die CPU kein Fremdwort sein.
 
Zuletzt bearbeitet:
Ich meinte die zwei Schleifen-Lösungen von vollmi in SCL, nicht meine AWL-Berechnung.
Hier zwei Bausteine in SCL, die das auf verschiedene Weise für ein 16-Bit Word machen:
 
Zurück
Oben