Files
BasicComponents/PLC/POUs/Components/Analog/FB_AnalogInput.TcPOU

584 lines
17 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1">
<POU Name="FB_AnalogInput" Id="{532e1013-5a2e-43c7-8863-3ad112d7d7e8}" SpecialFunc="None">
<Declaration><![CDATA[FUNCTION_BLOCK FINAL FB_AnalogInput
VAR_INPUT
// Analog input value
iAnalogValue AT %I* : INT;
// Card has detected an open circuit
xUnderrange AT%I* : BOOL;
// Input is overloaded
xOverrange AT %I* : BOOL;
// Input card has error
// EL30xx also sets this if an underrange or overrange error is present
xErrorCard AT %I* : BOOL;
// IO config data
stAnalogIOConfig : ST_ANALOG_IO_CONFIG;
// Error and warning config data
stAnalogEWConfig : ST_ANALOG_EW_CONFIG;
// Global switch to dissable all errors
xReleaseErrors : BOOL := TRUE;
// Enables or dissables errors from min max values
xReleaseLimitErrors : BOOL := FALSE;
// Enables or dissables hardware errors
xReleaseHardwareErrors : BOOL := TRUE;
// Input to confirm all errors
xConfirmAlarms : BOOL;
// Input to tell the fb thats ist used inside a unit test
// Fb will not throw error messages
{attribute 'hide'}
xInUnitTestMode : BOOL := FALSE;
END_VAR
VAR_OUTPUT
// Optional HMI interface
stHMIInterface : ST_HMI_ANALOG_VALUE;
// Scaled output value
rScaledValue : REAL;
// Error in function block
xError : BOOL;
// Warning active
xWarning : BOOL;
// Low level error
xErrorLow : BOOL;
// Low level warning
xWarningLow : BOOL;
// High level warning
xWarningHigh : BOOL;
//High level error
xErrorHigh : BOOL;
END_VAR
VAR
// Scaling factor for conversion
_rConversionFactor : REAL;
// Base offset for scaling factor
_rBaseOffset : REAL;
// Min warning level
_rMinWarningLevel : REAL;
// Max warning level
_rMaxWarningLevel : REAL;
// Min error level
_rMinErrorLevel : REAL;
// Max error level
_rMaxErrorLevel : REAL;
// Scaling config error
_xConfigError : BOOL := FALSE;
// Limits config error
_xEWConfigError : BOOL := FALSE;
// Helper variables used in reset error flag
_xAlarmsActive : BOOL;
_xInputErrorsActive : BOOL;
// Max process value
_iAIMax : INT;
// Min process value
_iAIMin : INT;
// Clamped analog value
_iClampedAnalogValue : INT;
// Internal scaled value
_rScaledValue : REAL;
// Name of the function block
_sName : STRING;
// Internal warning flags
_xWarningLow : BOOL;
_xWarningHigh : BOOL;
_xWarning : BOOL;
// Internal error flag
_xErrorLow : BOOL;
_xErrorHigh : BOOL;
_xError : BOOL;
// Alarm handlers
_fbAlarmCardError : FB_AlarmMessage(stEventEntry := TC_EVENTS.AnalogInput.AICardFailure, xWithConfirmation := TRUE);
_fbAlarmUnderrange : FB_AlarmMessage(stEventEntry := TC_EVENTS.AnalogInput.AIOpenCircuit, xWithConfirmation := TRUE);
_fbAlarmOverload : FB_AlarmMessage(stEventEntry := TC_EVENTS.AnalogInput.AIShortCircuit, xWithConfirmation := TRUE);
_fbAlarmConfigError : FB_AlarmMessage(stEventEntry := TC_EVENTS.AnalogInput.AIConfigError, xWithConfirmation := FALSE);
_fbAlarmErrorLow : FB_AlarmMessage(stEventEntry := TC_EVENTS.AnalogInput.ErrorLow, xWithConfirmation := TRUE);
_fbAlarmWarningLow : FB_AlarmMessage(stEventEntry := TC_EVENTS.AnalogInput.WarningLow, xWithConfirmation := TRUE);
_fbAlarmWarningHigh : FB_AlarmMessage(stEventEntry := TC_EVENTS.AnalogInput.WarningHigh, xWithConfirmation := TRUE);
_fbAlarmErrorHigh : FB_AlarmMessage(stEventEntry := TC_EVENTS.AnalogInput.ErrorHigh, xWithConfirmation := TRUE);
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[// ===============
// Handle not used
// ===============
IF (NOT stAnalogIOConfig.xUsed) THEN
// Clear all pending alarms if there are any
_fbAlarmCardError(xActive := FALSE, xRelease := FALSE);
_fbAlarmUnderrange(xActive := FALSE, xRelease := FALSE);
_fbAlarmOverload(xActive := FALSE, xRelease := FALSE);
_fbAlarmCardError(xActive := FALSE, xRelease := FALSE);
_fbAlarmErrorHigh(xActive := FALSE, xRelease := FALSE);
_fbAlarmErrorLow(xActive := FALSE, xRelease := FALSE);
_fbAlarmWarningHigh(xActive := FALSE, xRelease := FALSE);
// Clear warning flags
IF xWarning OR xWarningLow OR xWarningHigh THEN
_xWarning := FALSE;
_xWarningLow := FALSE;
_xWarningHigh := FALSE;
xWarning := FALSE;
xWarningLow := FALSE;
xWarningHigh := FALSE;
END_IF
// Clear error flags
IF xError OR xErrorLow OR xErrorHigh THEN
_xError := FALSE;
_xErrorLow := FALSE;
_xErrorHigh := FALSE;
xError := FALSE;
xErrorLow := FALSE;
xErrorHigh := FALSE;
END_IF
// Dont execute anything anymore
RETURN;
END_IF
// =========
// Prechecks
// =========
// Calculate scaling factors,
// scaling will be zero in case
// of invalid scaling parameters.
// Also checks if reference to config data is valid.
CalcScalingFactors();
// Check error and warning levels config
// Will later raise alarms if config is wrong
CheckEWLevels();
// ===========================
// Config error alarm handling
// ===========================
_fbAlarmConfigError(
xActive:= _xConfigError OR (_xEWConfigError AND xReleaseLimitErrors),
xRelease:= xReleaseErrors,
xAcknowledge:= ,
timOnDelay:= ,
timOffDelay:= ,
xInUnitTestMode:= xInUnitTestMode);
IF _fbAlarmConfigError.Triggered THEN
_xError := TRUE;
END_IF
// ========================
// Analog value calculation
// ========================
// Clamp analogue input levels
_iClampedAnalogValue := MAX(_iAIMin, iAnalogValue);
_iClampedAnalogValue := MIN(_iAIMax, _iClampedAnalogValue);
// Calc scaled value
_rScaledValue := _iClampedAnalogValue * _rConversionFactor + _rBaseOffset;
// =========================
// Underrange alarm handling
// =========================
_fbAlarmUnderrange(
xActive:= xUnderrange,
xRelease:= stAnalogIOConfig.xUsed AND xReleaseErrors AND xReleaseHardwareErrors,
xAcknowledge:= xConfirmAlarms,
timOnDelay:= stAnalogEWConfig.stDelays.timHardwareSignalLevelOn,
timOffDelay:= stAnalogEWConfig.stDelays.timHardwareSignalLevelOff,
xInUnitTestMode:= xInUnitTestMode);
// Latch error signal
IF _fbAlarmUnderrange.Triggered THEN
_xError := TRUE;
END_IF
// =========================
// Overload alarm handling
// =========================
_fbAlarmOverload(
xActive:= xOverrange,
xRelease:= stAnalogIOConfig.xUsed AND xReleaseErrors AND xReleaseHardwareErrors,
xAcknowledge:= xConfirmAlarms,
timOnDelay:= stAnalogEWConfig.stDelays.timHardwareSignalLevelOn,
timOffDelay:= stAnalogEWConfig.stDelays.timHardwareSignalLevelOff,
xInUnitTestMode:= xInUnitTestMode);
// Latch error signal
IF _fbAlarmOverload.Triggered THEN
_xError := TRUE;
END_IF
// =========================
// Card alarm handling
// =========================
// Filter overload error signal
// EL30xx also sets this if an underrange or overrange error is present,
// so we filter this out
_fbAlarmCardError(
xActive:= xErrorCard AND (NOT xUnderrange) AND (NOT xOverrange),
xRelease:= stAnalogIOConfig.xUsed AND xReleaseErrors AND xReleaseHardwareErrors,
xAcknowledge:= xConfirmAlarms,
timOnDelay:= stAnalogEWConfig.stDelays.timHardwareSignalLevelOn,
timOffDelay:= stAnalogEWConfig.stDelays.timHardwareSignalLevelOff,
xInUnitTestMode:= xInUnitTestMode);
// Latch error signal
IF _fbAlarmCardError.Triggered THEN
_xError := TRUE;
END_IF
// ===========================
// Error high alarm handling
// ===========================
_fbAlarmErrorHigh(
xActive:= (_rScaledValue >= _rMaxErrorLevel),
xRelease:= stAnalogIOConfig.xUsed AND xReleaseErrors AND xReleaseLimitErrors AND (NOT _xEWConfigError),
xAcknowledge:= xConfirmAlarms,
timOnDelay:= stAnalogEWConfig.stDelays.timErrorHighOn,
timOffDelay:= stAnalogEWConfig.stDelays.timErrorHighOff,
xInUnitTestMode:= xInUnitTestMode);
_xErrorHigh := _fbAlarmErrorHigh.Triggered;
// Latch error
IF _xErrorHigh THEN
_xError := TRUE;
END_IF
// ===========================
// Error low alarm handling
// ===========================
_fbAlarmErrorLow(
xActive:= (_rScaledValue <= _rMinErrorLevel),
xRelease:= stAnalogIOConfig.xUsed AND xReleaseErrors AND xReleaseLimitErrors AND (NOT _xEWConfigError),
xAcknowledge:= xConfirmAlarms,
timOnDelay:= stAnalogEWConfig.stDelays.timErrorLowOn,
timOffDelay:= stAnalogEWConfig.stDelays.timErrorLowOff,
xInUnitTestMode:= xInUnitTestMode);
_xErrorLow := _fbAlarmErrorLow.Triggered;
// Latch error
IF _xErrorLow THEN
_xError := TRUE;
END_IF
// ===========================
// Warning high alarm handling
// ===========================
_fbAlarmWarningHigh(
xActive:= (_rScaledValue >= _rMaxWarningLevel),
xRelease:= stAnalogIOConfig.xUsed AND xReleaseErrors AND xReleaseLimitErrors AND (NOT _xEWConfigError),
xAcknowledge:= xConfirmAlarms,
timOnDelay:= stAnalogEWConfig.stDelays.timWarningHighOn,
timOffDelay:= stAnalogEWConfig.stDelays.timWarningHighOff,
xInUnitTestMode:= xInUnitTestMode);
_xWarningHigh := _fbAlarmWarningHigh.Triggered;
// ===========================
// Warning low alarm handling
// ===========================
_fbAlarmWarningLow(
xActive:= (_rScaledValue <= _rMinWarningLevel),
xRelease:= stAnalogIOConfig.xUsed AND xReleaseErrors AND xReleaseLimitErrors AND (NOT _xEWConfigError),
xAcknowledge:= xConfirmAlarms,
timOnDelay:= stAnalogEWConfig.stDelays.timWarningLowOn,
timOffDelay:= stAnalogEWConfig.stDelays.timWarningLowOff,
xInUnitTestMode:= xInUnitTestMode);
_xWarningLow := _fbAlarmWarningLow.Triggered;
// ============
// Warning flag
// ============
_xWarning := _xWarningLow OR _xWarningHigh;
// ================
// Reset error flag
// ================
_xAlarmsActive := _fbAlarmConfigError.Active
OR _fbAlarmUnderrange.Active
OR _fbAlarmOverload.Active
OR _fbAlarmCardError.Active
OR _fbAlarmErrorHigh.Active
OR _fbAlarmErrorLow.Active;
_xInputErrorsActive := _fbAlarmUnderrange.Triggered
OR _fbAlarmOverload.Triggered
OR _fbAlarmCardError.Triggered;
IF xConfirmAlarms AND _xError AND (NOT _xAlarmsActive) AND (NOT _xInputErrorsActive) AND (NOT _xConfigError) THEN
_xError := FALSE;
END_IF
// ====================
// Handle HMI interface
// ====================
HandleHMIOutput();
// Copy internal signals to outputs
xWarningLow := _xWarningLow;
xWarningHigh := _xWarningHigh;
xWarning := _xWarning;
xErrorLow := _xErrorLow;
xErrorHigh := _xErrorHigh;
xError := _xError;
rScaledValue := _rScaledValue;]]></ST>
</Implementation>
<Method Name="CalcScalingFactors" Id="{e88dfbcd-1a0d-45a0-9d50-5ad8be2479c9}">
<Declaration><![CDATA[{attribute 'analysis' := '-56'}
METHOD PRIVATE CalcScalingFactors
VAR
_rNum : REAL;
_rDenom : REAL;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[// _lrConversionFactor := (lrPVMax - lrPVMin)/(udiAIMax - udiAIMin) + (rPVMin - ((lrPVMax - lrPVMin)/(udiAIMax - udiAIMin)*udiAIMin))
// Splitted in two calculations to catch division by zero
_rNum := (stAnalogIOConfig.rPVMax - stAnalogIOConfig.rPVMin);
_rDenom := INT_TO_REAL(stAnalogIOConfig.iAIMax - stAnalogIOConfig.iAIMin);
// Do not divide by 0 or a negative number
IF _rDenom > 0.0 THEN
_rConversionFactor := _rNum/_rDenom;
_rBaseOffset := stAnalogIOConfig.rPVMin - (_rConversionFactor * INT_TO_REAL(stAnalogIOConfig.iAIMin));
_iAIMax := stAnalogIOConfig.iAIMax;
_iAIMin := stAnalogIOConfig.iAIMin;
_xConfigError := FALSE;
ELSE
// Division by zero happened
// Or denom was negative
// Set scaling to zero
_rConversionFactor := 0.0;
_rBaseOffset := 0.0;
_iAIMax := 0;
_iAIMin := 0;
_xConfigError := TRUE;
END_IF]]></ST>
</Implementation>
</Method>
<Method Name="CheckEWLevels" Id="{6fcb5a6d-e37d-4efd-ad76-02026f476863}">
<Declaration><![CDATA[METHOD PRIVATE CheckEWLevels
VAR
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[// Reset (E)rror (W)arning config error
_xEWConfigError := FALSE;
// Check for EW config error
IF stAnalogEWConfig.stLevels.rWarningMin <= stAnalogEWConfig.stLevels.rErrorMin THEN
_xEWConfigError := TRUE;
END_IF
IF stAnalogEWConfig.stLevels.rWarningMax >= stAnalogEWConfig.stLevels.rErrorMax THEN
_xEWConfigError := TRUE;
END_IF
IF stAnalogEWConfig.stLevels.rWarningMin >= stAnalogEWConfig.stLevels.rWarningMax THEN
_xEWConfigError := TRUE;
END_IF
// Only write error and warning levels when there was no config error
IF (NOT _xEWConfigError) THEN
// Recreate alarm messages with the newly set limits
// if values have been changed
{analysis -54}
IF (_rMinErrorLevel <> stAnalogEWConfig.stLevels.rErrorMin)
OR (_rMinWarningLevel <> stAnalogEWConfig.stLevels.rWarningMin)
OR (_rMaxWarningLevel <> stAnalogEWConfig.stLevels.rWarningMax)
OR (_rMaxErrorLevel <> stAnalogEWConfig.stLevels.rErrorMax) THEN
{analysis +54}
CreateAlarmLimitsMSG();
END_IF
// Set new values
_rMinErrorLevel := stAnalogEWConfig.stLevels.rErrorMin;
_rMinWarningLevel := stAnalogEWConfig.stLevels.rWarningMin;
_rMaxWarningLevel := stAnalogEWConfig.stLevels.rWarningMax;
_rMaxErrorLevel := stAnalogEWConfig.stLevels.rErrorMax;
END_IF
]]></ST>
</Implementation>
</Method>
<Method Name="CreateAlarmLimitsMSG" Id="{d38eb5a5-80eb-4ab2-8c50-97431707ca20}">
<Declaration><![CDATA[{attribute 'analysis' := '-26'}
METHOD PRIVATE CreateAlarmLimitsMSG
VAR_INPUT
END_VAR
VAR
_sTempUnit : STRING;
_sTempErrorMin : STRING;
_sTempWarningMin : STRING;
_sTempWarningMax : STRING;
_sTempErrorMax : STRING;
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[// Check if analog value has unit
IF stAnalogIOConfig.sUnit <> '' THEN
_sTempUnit := CONCAT(' ', stAnalogIOConfig.sUnit);
ELSE
_sTempUnit := '';
END_IF
// Create message parameter strings
_sTempErrorMin := CONCAT(REAL_TO_STRING(stAnalogEWConfig.stLevels.rErrorMin), _sTempUnit);
_sTempWarningMin := CONCAT(REAL_TO_STRING(stAnalogEWConfig.stLevels.rWarningMin), _sTempUnit);
_sTempWarningMax := CONCAT(REAL_TO_STRING(stAnalogEWConfig.stLevels.rWarningMax), _sTempUnit);
_sTempErrorMax := CONCAT(REAL_TO_STRING(stAnalogEWConfig.stLevels.rErrorMax), _sTempUnit);
{analysis -46}
// Inser message parameters
_fbAlarmErrorLow.Arguments.Clear().AddString(_sName).AddString(_sTempErrorMin);
_fbAlarmWarningLow.Arguments.Clear().AddString(_sName).AddString(_sTempWarningMin);
_fbAlarmWarningHigh.Arguments.Clear().AddString(_sName).AddString(_sTempWarningMax);
_fbAlarmErrorHigh.Arguments.Clear().AddString(_sName).AddString(_sTempErrorMax);
{analysis +46}]]></ST>
</Implementation>
</Method>
<Method Name="CreateAlarmMSG" Id="{e4d0fc74-1711-410b-9ec3-4af08afbc236}">
<Declaration><![CDATA[METHOD PRIVATE CreateAlarmMSG
VAR_INPUT
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[{analysis -46}
_fbAlarmCardError.Arguments.Clear().AddString(_sName);
_fbAlarmUnderrange.Arguments.Clear().AddString(_sName);
_fbAlarmOverload.Arguments.Clear().AddString(_sName);
_fbAlarmConfigError.Arguments.Clear().AddString(_sName);
{analysis +46}]]></ST>
</Implementation>
</Method>
<Method Name="FB_init" Id="{27512538-cc2f-4100-8046-022de49f067a}">
<Declaration><![CDATA[//FB_Init ist immer implizit verfügbar und wird primär für die Initialisierung verwendet.
//Der Rückgabewert wird nicht ausgewertet. Für gezielte Einflussnahme können Sie
//die Methoden explizit deklarieren und darin mit dem Standard-Initialisierungscode
//zusätzlichen Code bereitstellen. Sie können den Rückgabewert auswerten.
METHOD FB_Init: BOOL
VAR_INPUT
bInitRetains: BOOL; // TRUE: Die Retain-Variablen werden initialisiert (Reset warm / Reset kalt)
bInCopyCode: BOOL; // TRUE: Die Instanz wird danach in den Kopiercode kopiert (Online-Change)
// Name of analogue io
sName : STRING(80);
END_VAR]]></Declaration>
<Implementation>
<ST><![CDATA[// Save io name
_sName := sName;
// Create alarm messages
CreateAlarmMSG();
CreateAlarmLimitsMSG();]]></ST>
</Implementation>
</Method>
<Method Name="HandleHMIOutput" Id="{1667ccb9-efb6-43f9-9a11-5c208475143f}">
<Declaration><![CDATA[METHOD PRIVATE HandleHMIOutput
VAR_INPUT
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[stHMIInterface.xUsed := stAnalogIOConfig.xUsed;
stHMIInterface.sUnit := stAnalogIOConfig.sUnit;
stHMIInterface.sName := _sName;
stHMIInterface.rValue := _rScaledValue;
stHMIInterface.rMin := stAnalogIOConfig.rPVMin;
stHMIInterface.rMax := stAnalogIOConfig.rPVMax;
IF _xError THEN
stHMIInterface.iStatus := 2;
ELSE
stHMIInterface.iStatus := 1;
END_IF]]></ST>
</Implementation>
</Method>
<Property Name="Name" Id="{103c7177-ef49-4a4b-98b1-06578d5fce31}">
<Declaration><![CDATA[PROPERTY Name : STRING(80)]]></Declaration>
<Get Name="Get" Id="{02e85b3f-9933-4282-a9d2-1ab27eb22499}">
<Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[Name := _sName;]]></ST>
</Implementation>
</Get>
<Set Name="Set" Id="{4215abec-259f-45d7-a31e-437036d4e241}">
<Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
<Implementation>
<ST><![CDATA[_sName := Name;
// After a name change, all error messages have to be changed
CreateAlarmMSG();
CreateAlarmLimitsMSG();]]></ST>
</Implementation>
</Set>
</Property>
</POU>
</TcPlcObject>