WinCC Programm Alarm vs. Bit Alarm

Zuviel Werbung?
-> Hier kostenlos registrieren
Ok, um hier jetzt nicht zu weit vom ursprünglichen Thema abzudriften: hier haben wir offensichtlich (sehr) unterschiedliche Backgrounds.:D


Bleibe trotzdem noch kurz beim Teilaspekt "Sprache":
Finde halt, dass es -bei unserer Arbeitsweise mit getrennten SPS- und HMI-Projekten- für mich (als der HMI-Spezi) und unsere Übersetzer leichter zu handhaben ist, wenn es EINE Textliste mit EINER zugehörigen Handhabungsvorschrift gibt.


Gruß, Fred
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ok, um hier jetzt nicht zu weit vom ursprünglichen Thema abzudriften: hier haben wir offensichtlich (sehr) unterschiedliche Backgrounds.:D


Bleibe trotzdem noch kurz beim Teilaspekt "Sprache":
Finde halt, dass es -bei unserer Arbeitsweise mit getrennten SPS- und HMI-Projekten- für mich (als der HMI-Spezi) und unsere Übersetzer leichter zu handhaben ist, wenn es EINE Textliste mit EINER zugehörigen Handhabungsvorschrift gibt.


Gruß, Fred

Das bleibt ja auch so, du exportierst ja das ganze TIA Projekt und
wählst aus was exportiert werden soll. Darunter fallen nicht nur die
HMI Texte sondern auch Meldetexte auf der PLC Seite.

Für mich ist wirklich nur die Menge der Sprachen ein Makel, wo doch
Speicher nur bei Siemens teuer ist.
 
@rostiger Nagel:
Das bleibt ja auch so, du exportierst ja das ganze TIA Projekt und
wählst aus was exportiert werden soll. Darunter fallen nicht nur die
HMI Texte sondern auch Meldetexte auf der PLC Seite.
...

Nein, ich müsste die Texte aus ZWEI Projekten exportieren, HMI und SPS.
Außerdem gelten für HMI-Texte stringentere Vorgaben (Textlänge, Handhabung von Zeilenumbrüchen etc.), die strenggenommen ein getrenntes Bearbeiten des Übersetzers erfordern würden, damit er sich nicht dauernd verhaspelt (Alles schon gehabt...:|)


@ducati:
Auch beim TIA-Portal werden getrennte Süppchen gekocht: Projekt und Bibliothek z.B.
Schöner Mist, wenn du eigentlich alle verwendeten HMI-Komponenten in einem Projekt haben willst (damit eine Weiterbearbeitung durch andere Personen nicht zwingend die Weitergabe von globalen (Werks-)Bibliotheken erfordert).
Zumal der Bibliotheks-Editor für Bildbausteine gelinde gesagt eine Vollkatastrophe ist... (Besonders, was Texte -also Sprachen-angeht!)


Gruß, Fred
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke erst mal für die vielen Hinweise. Ich meine, dass für unsere Anlagen der Programm Alarm besser ist. Wir haben die das Hmi möglich dumm gehalten und somit alles in die PLC genommen. Die Umschaltung der Sprachen geht. die Listen müssen halt in die PLC eingefügt werden.
 
Also wir nutzen nur noch ProgrammAlarm von Siemens.
Ich sehe es schon als großen Vorteil, das derjenige der den Alarm Programmiert, sofort an der gleichen Stelle diesen auch pflegt, inklusive Zusatzwerte.

Was mich am Programalarm nervt, ist das wir den ganzen nochmal Kapseln mussten, um nur eine bestimmte Anzahl Pro Zyklus auszulösen, da er sonst zuviel Performance verbraucht.

Sieht bei uns dann so aus:

Code:
FUNCTION_BLOCK "ProgramAlarmGenerator"
TITLE = Handling ProgramAlarm
{ S7_Optimized_Access := 'TRUE' }
FAMILY : General
VERSION : 1.0
   VAR_INPUT 
      AlarmSignal { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   //  zu überwachendes Signal
      Acknowledge { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   //  Quittierung
      AutoQuit { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   //  0 = Quittierung mit Quitt-Signal; 1 = Automatische Quittierung
      SimulationOn { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // Simulation ist eingeschaltet
      ResetAlarmWithSimulation { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // Störung bei Simulation rücksetzen/ ignorieren
   END_VAR


   VAR_OUTPUT 
      ProgramAlarmActive { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // ProgramAlarm aktiv
      AlarmNumberCycle { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : UInt;   // Fortlaufende Alarmnummer in der Aufrufreihenfolge
      ErrorProgramAlarm { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // Fehler ProgramAlarm
      StatusProgramAlarm { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Word;   // Status ProgramAlarm
      ErrorGetAlarm { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // Fehler GetAlarm
      StatusGetAlarm { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Word;   // Status GetAlarmState
      AlarmStateGetAlarm { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Byte;   // Status ProgramAlarm vom GetAlarm Baustein (86 = Alarm inaktiv, 87 = Alarm aktiv)
   END_VAR


   VAR_IN_OUT 
      SetElementMessageType { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // Ausgang um Element-Meldungstyp zu setzen (Error/ Warning/ Information..)
      InstanceProgramAlarm {InstructionName := 'Program_Alarm'; LibVersion := '1.0'; S7_HiddenAssignment := 'Show'} : Program_Alarm;   // ProgramAlarm Instanz
      AdditionalValue1 { S7_HiddenAssignment := 'Hide'; S7_PredefinedAssignment := 'NULL'; S7_ShowAssignmentIfParamsNotIdentical := 'true'} : Variant;   // Begleitwert 1 ProgramAlarm
      AdditionalValue2 { S7_HiddenAssignment := 'Hide'; S7_PredefinedAssignment := 'NULL'; S7_ShowAssignmentIfParamsNotIdentical := 'true'} : Variant;   // Begleitwert 2 ProgramAlarm
      AdditionalValue3 { S7_HiddenAssignment := 'Hide'; S7_PredefinedAssignment := 'NULL'; S7_ShowAssignmentIfParamsNotIdentical := 'true'} : Variant;   // Begleitwert 3 ProgramAlarm
      AdditionalValue4 { S7_HiddenAssignment := 'Hide'; S7_PredefinedAssignment := 'NULL'; S7_ShowAssignmentIfParamsNotIdentical := 'true'} : Variant;   // Begleitwert 4 ProgramAlarm
      AdditionalValue5 { S7_HiddenAssignment := 'Hide'; S7_PredefinedAssignment := 'NULL'; S7_ShowAssignmentIfParamsNotIdentical := 'true'} : Variant;   // Begleitwert 5 ProgramAlarm
      AdditionalValue6 { S7_HiddenAssignment := 'Hide'; S7_PredefinedAssignment := 'NULL'; S7_ShowAssignmentIfParamsNotIdentical := 'true'} : Variant;   // Begleitwert 6 ProgramAlarm
      AdditionalValue7 { S7_HiddenAssignment := 'Hide'; S7_PredefinedAssignment := 'NULL'; S7_ShowAssignmentIfParamsNotIdentical := 'true'} : Variant;   // Begleitwert 7 ProgramAlarm
      AdditionalValue8 { S7_HiddenAssignment := 'Hide'; S7_PredefinedAssignment := 'NULL'; S7_ShowAssignmentIfParamsNotIdentical := 'true'} : Variant;   // Begleitwert 8 ProgramAlarm
      AdditionalValue9 { S7_HiddenAssignment := 'Hide'; S7_PredefinedAssignment := 'NULL'; S7_ShowAssignmentIfParamsNotIdentical := 'true'} : Variant;   // Begleitwert 9 ProgramAlarm
      AdditionalValue10 { S7_HiddenAssignment := 'Hide'; S7_PredefinedAssignment := 'NULL'; S7_ShowAssignmentIfParamsNotIdentical := 'true'} : Variant;   // Begleitwert 10 ProgramAlarm
   END_VAR


   VAR 
      TriggerAlarm { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // Program Alarm auslösen
      ResetAlarm { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // Program Alarm zurücksetzen
      LastSignalProgramAlarm { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // Signal für Program Alarm vom vorherigen Zyklus
      TimestampProgramAlarm { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : LDT;   // Zeitstempel Program Alarm Telegramme wiederholen
      GetAlarmStateAfterTrigger { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // Status Program Alarm nach dem Triggern auslesen
      GetAlarmStateAfterReset { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // Status Program Alarm nach dem Rücksetzen auslesen
      StorageProgramAlarmActive { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // Speichervariable ProgramAlarm aktiv 
      LastSignalExportActive { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;   // Signal für ExportActive vom vorherigen Zyklus
   END_VAR


   VAR_TEMP 
      signalProgramAlarm : Bool;   // Signal für Program Alarm
   END_VAR


   VAR CONSTANT 
      ALARM_INACTIVE : Byte := 16#86;   // ProgramAlarm ist inaktiv
      ALARM_ACTIVE : Byte := 16#87;   // ProgramAlarm ist aktiv
   END_VAR




BEGIN
	
	REGION Program Alarm
	    // init
	    #ErrorProgramAlarm := #ErrorGetAlarm := FALSE;
	    #StatusProgramAlarm := 0;
	    
	    // Quittierung Program Alarm mit Quitt bzw. AutoQuit
	    IF #Acknowledge OR (#AutoQuit AND NOT #AlarmSignal) OR (#SimulationOn AND #ResetAlarmWithSimulation) THEN
	        #StorageProgramAlarmActive := FALSE;
	    END_IF;
	    
	    // Störungssignal verarbeiten
	    IF #AlarmSignal AND NOT (#SimulationOn AND #ResetAlarmWithSimulation) THEN
	        #StorageProgramAlarmActive := TRUE;
	    END_IF;
	    
	    // Ausgang für Platz gestört setzen
	    IF #StorageProgramAlarmActive THEN
	        #SetElementMessageType := TRUE;
	    END_IF;
	    
	    // Status Alarmbit ausgeben
	    #ProgramAlarmActive := #StorageProgramAlarmActive;
	    
	    // Alarmzähler hochzählen
	    "General".ProgramAlarm.CounterProgramAlarms += 1;
	    #AlarmNumberCycle := "General".ProgramAlarm.CounterProgramAlarms;
	    
	    // Trigger für Alarm bilden
	    #signalProgramAlarm := ((#StorageProgramAlarmActive AND NOT "General".ProgramAlarm.ExportActive) OR ("General".ProgramAlarm.SetAllErrorMessages AND "General".ProgramAlarm.CounterProgramAlarms < ("General".ProgramAlarm.StartNumberSetMessage + "General".ProgramAlarm.CountSetMessages) AND "General".ProgramAlarm.CounterProgramAlarms >= "General".ProgramAlarm.StartNumberSetMessage)) AND NOT "General".ProgramAlarm.ActivateAlarmsAfterFirstScan;
	    
	    // Flanke SetAllErrorMessages überwachen => Trigger ablöschen
	    IF "General".ProgramAlarm.ExportActive AND NOT #LastSignalExportActive THEN
	        #TriggerAlarm := FALSE;
	    END_IF;
	    
	    #LastSignalExportActive := "General".ProgramAlarm.ExportActive;
	    
	    // prüfen ob Alarm ausgelöst oder quittiert werden soll
	    IF #signalProgramAlarm AND NOT #LastSignalProgramAlarm AND NOT #TriggerAlarm THEN
	        #TriggerAlarm := TRUE;
	        #TimestampProgramAlarm := "General".DateAndTimeUtc;
	    ELSIF NOT #signalProgramAlarm AND #LastSignalProgramAlarm AND NOT #ResetAlarm THEN
	        #ResetAlarm := TRUE;
	        #TimestampProgramAlarm := "General".DateAndTimeUtc;
	    END_IF;
	    
	    // Alarm auslösen oder quittieren
	    IF #TriggerAlarm AND "General".ProgramAlarm.MessageCounter < "MESSAGES_PER_CYCLE" THEN
	        #InstanceProgramAlarm(SIG := TRUE,
	                              TIMESTAMP := #TimestampProgramAlarm,
	                              SD_1 := #AdditionalValue1,
	                              SD_2 := #AdditionalValue2,
	                              SD_3 := #AdditionalValue3,
	                              SD_4 := #AdditionalValue4,
	                              SD_5 := #AdditionalValue5,
	                              SD_6 := #AdditionalValue6,
	                              SD_7 := #AdditionalValue7,
	                              SD_8 := #AdditionalValue8,
	                              SD_9 := #AdditionalValue9,
	                              SD_10 := #AdditionalValue10,
	                              Status => #StatusProgramAlarm,
	                              Error => #ErrorProgramAlarm);
	        #GetAlarmStateAfterTrigger := TRUE;
	        "General".ProgramAlarm.MessageCounter := "General".ProgramAlarm.MessageCounter + 1;
	    ELSIF #ResetAlarm AND "General".ProgramAlarm.MessageCounter < "MESSAGES_PER_CYCLE" THEN
	        #InstanceProgramAlarm(SIG := FALSE,
	                              TIMESTAMP := #TimestampProgramAlarm,
	                              SD_1 := #AdditionalValue1,
	                              SD_2 := #AdditionalValue2,
	                              SD_3 := #AdditionalValue3,
	                              SD_4 := #AdditionalValue4,
	                              SD_5 := #AdditionalValue5,
	                              SD_6 := #AdditionalValue6,
	                              SD_7 := #AdditionalValue7,
	                              SD_8 := #AdditionalValue8,
	                              SD_9 := #AdditionalValue9,
	                              SD_10 := #AdditionalValue10,
	                              Status => #StatusProgramAlarm,
	                              Error => #ErrorProgramAlarm);
	        #GetAlarmStateAfterReset := TRUE;
	        "General".ProgramAlarm.MessageCounter := "General".ProgramAlarm.MessageCounter + 1;
	    END_IF;
	    
	    // Status Program Alarm nach dem Auslösen prüfen
	    IF #GetAlarmStateAfterTrigger OR #GetAlarmStateAfterReset THEN
	        Get_AlarmState(Alarm := #InstanceProgramAlarm,
	                       AlarmState => #AlarmStateGetAlarm,
	                       Error => #ErrorGetAlarm,
	                       STATUS => #StatusGetAlarm);
	        IF #TriggerAlarm AND #GetAlarmStateAfterTrigger AND #AlarmStateGetAlarm = #ALARM_ACTIVE THEN
	            #TriggerAlarm := FALSE;
	            #GetAlarmStateAfterTrigger := FALSE;
	            IF NOT #signalProgramAlarm THEN
	                #ResetAlarm := TRUE;
	            END_IF;
	            // Status Program Alarm nach dem Rücksetzen prüfen
	        ELSIF #ResetAlarm AND #GetAlarmStateAfterReset AND #AlarmStateGetAlarm = #ALARM_INACTIVE THEN
	            #ResetAlarm := FALSE;
	            #GetAlarmStateAfterReset := FALSE;
	            IF #signalProgramAlarm THEN
	                #TriggerAlarm := TRUE;
	            END_IF;
	        END_IF;
	    END_IF;
	    
	    // Trigger Signal für Flankenauswertung speichern
	    #LastSignalProgramAlarm := #signalProgramAlarm;
	    
	    // ProgramAlarmError
	    IF NOT "General".ProgramAlarm.ProgramAlarmError.Active AND #ErrorProgramAlarm AND #StatusProgramAlarm <> 16#80C4 THEN
	        "General".ProgramAlarm.ProgramAlarmError.Active := TRUE;
	        "General".ProgramAlarm.ProgramAlarmError.State := #StatusProgramAlarm;
	        "General".ProgramAlarm.ProgramAlarmError.AlarmNumberCycle := #AlarmNumberCycle;
	    END_IF;
	    
	    // GetAlarmError
	    IF NOT "General".ProgramAlarm.GetAlarmError.Active AND #ErrorGetAlarm THEN
	        "General".ProgramAlarm.GetAlarmError.Active := TRUE;
	        "General".ProgramAlarm.GetAlarmError.State := #StatusProgramAlarm;
	        "General".ProgramAlarm.GetAlarmError.AlarmNumberCycle := #AlarmNumberCycle;
	    END_IF;
	    
	END_REGION
	
END_FUNCTION_BLOCK
 
Wir haben auch nochmal einen Baustein der mit GetAlarm alle Alarme ausließt, um uns dann je Meldeklasse zu speichern ob ein Alarm anliegt (Und wenn nötig nochmals alle Alarme auf Bits umspeichert, dazu haben wir einfach einen Absoluten DB mit einem Bool Array und setzen das Bit der Alarmnummer).
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Also wir nutzen nur noch ProgrammAlarm von Siemens.
Ich sehe es schon als großen Vorteil, das derjenige der den Alarm Programmiert, sofort an der gleichen Stelle diesen auch pflegt, inklusive Zusatzwerte.

Was mich am Programalarm nervt, ist das wir den ganzen nochmal Kapseln mussten, um nur eine bestimmte Anzahl Pro Zyklus auszulösen, da er sonst zuviel Performance verbraucht.

Das Thema Meldeschwall ist ein Risiko bei ProgramAlarm.
Daher setzen wir ProDiag ein. Macht den Umgang mit ProgramAlarm entspannter.
 
In wie fern unterscheidet sich den dann ProDiag zu ProgrammAlarm?

ProDiag nutzt intern ProgramAlarm.
Du hast aber noch weitere Zusatzfunktionen.
Das ganze kostet Geld ... Aber uns spart es viel Zeit.
Schau mal bei Youtube. Da gibt es einige Videos zum Thema.
Richtig interessant sind z.B. der PLV-Viewer und der Graph-Viewer dann auf nem Comfort-Panel.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wir legen ja so gut wie keinen Alarm von Hand an, da wir 90% unserer Software generieren. Daher wirken sich die PDiag kosten natürlich aus. Kostet ja glaube auch pro 250 Meldungen, oder?
Wie sieht das mit der Performance aus? Und kann man PDiag auch im XML Exportieren, bzw. über Openness importieren?
 
Hui Buuuuu
ich bin seit mehreren Jahren aus dem aktiven Geschäft ausgestiegen und bin unter die Prüfer gegangen (TÜV).
Beschäftige mich derzeit auch mit TIA Projekten obwohl ich aus der Prozessleitsystem Welt (PCS7/CFC Teleperm, T3000) komme.
Was Ducati hier beschreibt ist richtig! Im (Kern) Kraftwerk oder Chemie würde kein Mensch Bitmeldung einsetzen, erstens wegen des ungenauen Zeitstempels und zweitens wegen der elendigen Arbeit. Aber als PCS7 startete konnte es längst nich was Teleperm XP mit UNIX Visu konnte und so ist es mit TIA auch. Es wird ewig dauern bis eine Programmieroberfläche wie CFC, mit den Automatismen geschaffen ist welche es unter PCS7, DELTA-V oder Symphony von ABB gibt. Schade eigentlich.
 
Wie würdet ihr die Sache bewerten, wenn jetzt das Panel über OPC UA von einem anderen Anbieter eingebunden werden soll?
Ich sehe es gerade genau so, SPS- und HMI-Projekt zu trennen und nur mit Bitmeldeverfahren zu arbeiten.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wie würdet ihr die Sache bewerten, wenn jetzt das Panel über OPC UA von einem anderen Anbieter eingebunden werden soll?
Ich sehe es gerade genau so, SPS- und HMI-Projekt zu trennen und nur mit Bitmeldeverfahren zu arbeiten.
Der ProgrammAlarm kann gleich als OPC-UA Alarms & Conditions arbeiten. Ab FW 2.9.
 
Zurück
Oben