FUNCTION_BLOCK "FB_SetAlarmAndLog" { S7_Optimized_Access := 'TRUE' } VERSION : 0.1 VAR_INPUT stSettings : Struct // Grundsätzliche einstellungen des Bausteins sFctnName : String[20]; // Name der Funktion die den Fehler wirft nNoMaxErrors : UInt := 32; // Maximale Anzahl an Fehlern. Werden über "xPlcReOrg" zugewiesen. nType : Int := 0; // 0: IntError | 1: Error | 2: Warning | 3: Information | 4: Debug END_STRUCT; xInAlarm : Bool; // An: Fehler liegt an. | Aus: Kein Fehler liegt an nInAlarmPriority : USInt := 1; // Priorität des Fehlers: 1 = Höchste Prio. | 30 = Niedrigste Prio. nInAlarmNumber : UInt; // Fehlernummer von 0 bis (stSettings.nNoMaxErrors - 1) sInPrefix : String[20]; // Text vor der Fehlermeldung sInAlarmMessage : String[20]; // Text der Fehlermeldung sInSuffix : String[20]; // Text nach der Fehlermeldung wInTextListId_Message : Word; wInTextListId_Function : Word; wInTextListId_Prefix : Word; wInTextListId_Suffix : Word; wInTextListId_Separator : Word; END_VAR VAR_OUTPUT xOutRdy : Bool; // Zeigt an, ob ein neuer Fehler geschrieben werden darf END_VAR VAR_IN_OUT stInOutControlUnitCabinet : "UDT_MainState"; END_VAR VAR RETAIN nAlarmNoOffset : UInt; END_VAR VAR wStatus : Word; xAlarmFlag : Bool; sErrorString : String; xSetProgramAlarm : Bool; fbProgram_Alarm {InstructionName := 'Program_Alarm'; LibVersion := '1.0'} : Program_Alarm; xRetryProgramAlarm : Bool; END_VAR VAR_TEMP xTemp : Bool; tStringParts : Struct sType : String; sNumber : String; sFunctionName : String; END_STRUCT; tString : String; tSetDataLog : Bool; tRunProgramAlarm : Bool; tRenewString : Bool; tDataLogBuffer : "DataLogBuffer"; tRisingAlarm : Bool; // Kommende Meldung tFallingAlarm : Bool; // Gehende Meldung END_VAR BEGIN (* Der Baustein gibt über den Befehl "Program_Alarm" fehler am HMI aus. Achtung, nur jeweils ein Fehler pro Monitoring-Baustein gleichzeitig. Aufbau Fehlermeldung: Fehler 123: Heber 2, Step 230 - Heber nicht am Sensor erkannt BG6061 "sTypeAndNumber: " "sFunctionName" "sInPrefix" "sInErrorMessage" "xInSuffix" nType&(nErrorNumber+Offset) *) (* Fragen: Todo: - Priority-Level *) REGION Alarmnummer abfragen (* IF "DB_AlarmGlobal".xAlarmReOrg THEN #nAlarmNoOffset := "FC_GetAlarmNo_1"(#stSettings.nNoMaxErrors); // #xPlcReOrg := FALSE; // wird wegen "Funktionsname holen" nicht benötigt ELSIF #nAlarmNoOffset = 0 THEN "DB_AlarmGlobal".xAlarmReOrgNextStep := TRUE; END_IF; *) #nAlarmNoOffset := "FC_GetAlarmNo"(#stSettings.nNoMaxErrors); END_REGION REGION Kommende und gehende Meldung erfassen #tRisingAlarm := #xInAlarm AND NOT #xAlarmFlag; #tFallingAlarm := NOT #xInAlarm AND #xAlarmFlag; END_REGION REGION Alarm und Datalog aktivieren IF #nAlarmNoOffset > 0 THEN // Error CASE #stSettings.nType OF 0..1: // (0)Intern Error and (1)Error IF #tRisingAlarm OR #xRetryProgramAlarm THEN #tRunProgramAlarm := TRUE; #xSetProgramAlarm := TRUE; #tRenewString := TRUE; #tSetDataLog := TRUE; #xRetryProgramAlarm := FALSE; ELSIF #tFallingAlarm OR #xRetryProgramAlarm THEN #tRunProgramAlarm := TRUE; #xSetProgramAlarm := FALSE; #tRenewString := FALSE; #tSetDataLog := FALSE; #xRetryProgramAlarm := FALSE; END_IF; // #tRunProgramAlarm := (#xInAlarm <> #xAlarmFlag);//OR #stMachineState.xQuitError; //!!!! // #tSetDataLog := #xInAlarm AND NOT #xAlarmFlag; // #tRenewString := #xInAlarm <> #xAlarmFlag; // #xSetProgramAlarm := #xInAlarm; 2..4: // Warning, Information, Debug IF #xInAlarm AND NOT #xAlarmFlag THEN #tRunProgramAlarm := TRUE; #xSetProgramAlarm := TRUE; #tRenewString := TRUE; #tSetDataLog := TRUE; ELSIF NOT #xInAlarm AND #xAlarmFlag THEN #tRunProgramAlarm := TRUE; #xSetProgramAlarm := FALSE; #tRenewString := FALSE; #tSetDataLog := FALSE; ELSIF #stInOutControlUnitCabinet.xQuitError THEN #tRunProgramAlarm := TRUE; #xSetProgramAlarm := FALSE; #tRenewString := FALSE; #tSetDataLog := FALSE; END_IF; END_CASE; END_IF; END_REGION REGION Fehler zu String zusammenfügen IF #tRenewString THEN REGION Type And Number CASE #stSettings.nType OF 0: #tStringParts.sType := 'Int.Fehler'; 1: #tStringParts.sType := 'Fehler'; 2: #tStringParts.sType := 'Warnung'; 3: #tStringParts.sType := 'Info'; 4: #tStringParts.sType := 'Debug'; ELSE: #tStringParts.sType := 'WrongNType'; END_CASE; #tStringParts.sNumber := UINT_TO_STRING(#nAlarmNoOffset + #nInAlarmNumber); #tStringParts.sNumber[1] := ' '; // Vorzeichen entfernen END_REGION REGION Function Name #tStringParts.sFunctionName := CONCAT(IN1 := ' in ', IN2 := #stSettings.sFctnName); END_REGION REGION Zusammenfügen #tString := CONCAT(IN1 := #tStringParts.sType ,IN2 := #tStringParts.sNumber, IN3 := #tStringParts.sFunctionName, IN4 := ' | ', IN5 := #sInPrefix); IF #sInPrefix <> '' THEN #tString := CONCAT(IN1 := #tString, IN2 := ' | '); END_IF; #tString := CONCAT(IN1 := #tString, IN2 := #sInAlarmMessage); IF #sInAlarmMessage <> '' THEN #tString := CONCAT(IN1 := #tString, IN2 := ' | '); END_IF; #sErrorString := CONCAT(IN1 := #tString, IN2 := #sInSuffix); END_REGION REGION Nummer überprüfen IF #nInAlarmNumber > #stSettings.nNoMaxErrors - 1 OR #nInAlarmNumber < 0 THEN #sErrorString := CONCAT(IN1 := 'Falsche Fehlernummer in Baustein: ', IN2 := #stSettings.sFctnName); END_IF; END_REGION END_IF; END_REGION REGION ProgramAlarm Setzen IF #tRunProgramAlarm THEN #fbProgram_Alarm(SIG := #xSetProgramAlarm, Status => #wStatus, Error => #xTemp, SD_1 := #wInTextListId_Message, SD_2 := #sInPrefix, SD_3 := #sInSuffix, SD_4 := #wInTextListId_Function, SD_5 := #wInTextListId_Separator); END_IF; END_REGION REGION Datalog schreiben // Es ist nur 1 Datalog pro Zyklus möglich. Deshalb werden Fehler in einen Fehlerbuffer (FIFO) geschrieben und abgearbeitet. // Datalogs werden nur geschrieben wenn die Priorität hoch genug ist. IF #tSetDataLog AND #nInAlarmPriority <= 0 THEN #tDataLogBuffer."Time" := "FC_TimeAsString"(); #tDataLogBuffer.AlarmNr := UINT_TO_INT(#nAlarmNoOffset + #nInAlarmNumber); #tDataLogBuffer.AlarmType := #tStringParts.sType; #tDataLogBuffer.Error := CONCAT(IN1 := #sInPrefix, IN2 := ' ', IN3 := #sInAlarmMessage, IN4 := ' ', IN5 := #sInSuffix); #tDataLogBuffer.Function := #stSettings.sFctnName; // #xTemp := "FC_WriteDatalogToDB"(#tDataLogBuffer); END_IF; END_REGION REGION Ausgänge setzen #xOutRdy := NOT #xInAlarm AND NOT #xAlarmFlag AND #nAlarmNoOffset > 0; END_REGION REGION Flanken #xAlarmFlag := #xInAlarm; END_REGION REGION Fehler in ProgramAlarm Bearbeitung IF #xTemp AND ((#wStatus = 16#80C1) OR (#wStatus = 16#80C2) OR (#wStatus = 16#80C3) OR (#wStatus = 16#80C4)) THEN #xRetryProgramAlarm := TRUE; END_IF; END_REGION END_FUNCTION_BLOCK