Added more components
This commit is contained in:
555
PLC/POUs/Components/Analog/FB_AnalogInput.TcPOU
Normal file
555
PLC/POUs/Components/Analog/FB_AnalogInput.TcPOU
Normal file
@@ -0,0 +1,555 @@
|
||||
<?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
|
||||
// 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
|
||||
|
||||
// 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>
|
||||
<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>
|
||||
237
PLC/POUs/Components/Analog/FB_AnalogOutput.TcPOU
Normal file
237
PLC/POUs/Components/Analog/FB_AnalogOutput.TcPOU
Normal file
@@ -0,0 +1,237 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<POU Name="FB_AnalogOutput" Id="{5ea9527b-d363-4c01-ba95-f8c298545979}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FINAL FB_AnalogOutput
|
||||
VAR_INPUT
|
||||
// Setpoint
|
||||
rSetpoint : REAL;
|
||||
|
||||
// config data for analog output scaling
|
||||
stAnalogIOConfig : ST_ANALOG_IO_CONFIG;
|
||||
|
||||
// Global switch to dissable all errors
|
||||
xReleaseErrors : 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
|
||||
iAnalogValue AT %Q* : INT;
|
||||
|
||||
// Error in function block
|
||||
xError : BOOL;
|
||||
END_VAR
|
||||
VAR_IN_OUT
|
||||
// HMI Interface
|
||||
stHMIInterface : ST_HMI_ANALOG_VALUE;
|
||||
END_VAR
|
||||
VAR
|
||||
// Setpoint
|
||||
_rSetpointInternal : REAL;
|
||||
|
||||
// Name of the function block
|
||||
_sName : STRING;
|
||||
|
||||
// Scaling factor for conversion
|
||||
_rConversionFactor : REAL;
|
||||
|
||||
// Base offset for scaling factor
|
||||
_rBaseOffset : REAL;
|
||||
|
||||
// Temporary calculated analog value
|
||||
_rTempAnalogValue : REAL;
|
||||
|
||||
// Config error
|
||||
_xConfigError : BOOL;
|
||||
|
||||
// Max process value
|
||||
_rPVMax : REAL;
|
||||
|
||||
// Min process value
|
||||
_rPVMin : REAL;
|
||||
|
||||
// Config error alarm
|
||||
_fbAlarmConfigError : FB_AlarmMessage(stEventEntry := TC_EVENTS.AnalogOutput.ConfigError, xWithConfirmation := FALSE);
|
||||
|
||||
// Internal error flag
|
||||
_xError : BOOL;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// ===============
|
||||
// Handle not used
|
||||
// ===============
|
||||
|
||||
IF (NOT stAnalogIOConfig.xUsed) THEN
|
||||
// Clear all pending alarms if there are any
|
||||
_fbAlarmConfigError(xActive := FALSE, xRelease := FALSE);
|
||||
|
||||
IF xError THEN
|
||||
_xError := FALSE;
|
||||
xError := FALSE;
|
||||
END_IF
|
||||
|
||||
// Dont execute anything anymore
|
||||
RETURN;
|
||||
END_IF
|
||||
|
||||
// =========
|
||||
// Prechecks
|
||||
// =========
|
||||
|
||||
// Calculate scaling factors,
|
||||
// scaling will be zero in case
|
||||
// of invalid scaling parameters.
|
||||
CalcScalingFactors();
|
||||
|
||||
|
||||
// ===========================
|
||||
// Config error alarm handling
|
||||
// ===========================
|
||||
|
||||
_fbAlarmConfigError(
|
||||
xActive:= _xConfigError,
|
||||
xRelease:= xReleaseErrors,
|
||||
xAcknowledge:= ,
|
||||
timOnDelay:= ,
|
||||
timOffDelay:= ,
|
||||
xInUnitTestMode:= xInUnitTestMode);
|
||||
|
||||
IF _fbAlarmConfigError.Triggered THEN
|
||||
_xError := TRUE;
|
||||
END_IF
|
||||
|
||||
|
||||
// ========================
|
||||
// Analog value calculation
|
||||
// ========================
|
||||
|
||||
// Clamp analogue input levels
|
||||
_rSetpointInternal := MAX(rSetpoint, _rPVMin);
|
||||
_rSetpointInternal := MIN(_rSetpointInternal, _rPVMax);
|
||||
|
||||
// Calc scaled value
|
||||
_rTempAnalogValue := _rSetpointInternal * _rConversionFactor + _rBaseOffset;
|
||||
iAnalogValue := REAL_TO_INT(_rTempAnalogValue);
|
||||
|
||||
|
||||
// ====================
|
||||
// Handle HMI interface
|
||||
// ====================
|
||||
|
||||
stHMIInterface.xUsed := stAnalogIOConfig.xUsed;
|
||||
stHMIInterface.sUnit := stAnalogIOConfig.sUnit;
|
||||
stHMIInterface.rMin := stAnalogIOConfig.rPVMin;
|
||||
stHMIInterface.rMax := stAnalogIOConfig.rPVMax;
|
||||
|
||||
IF _xError THEN
|
||||
stHMIInterface.iStatus := E_HMI_ANALOG_VALUE_STATUS.ERROR;
|
||||
ELSE
|
||||
stHMIInterface.iStatus := E_HMI_ANALOG_VALUE_STATUS.OK;
|
||||
END_IF
|
||||
|
||||
stHMIInterface.sName := _sName;
|
||||
|
||||
|
||||
// ================
|
||||
// Reset error flag
|
||||
// ================
|
||||
|
||||
IF _xError AND xConfirmAlarms AND (NOT _xConfigError) AND (NOT _fbAlarmConfigError.Triggered) THEN
|
||||
_xError := FALSE;
|
||||
END_IF
|
||||
|
||||
|
||||
// Copy internal signals to outputs
|
||||
xError := _xError;]]></ST>
|
||||
</Implementation>
|
||||
<Method Name="CalcScalingFactors" Id="{7d8169fd-cf9b-4df6-b6f9-6740616693c1}">
|
||||
<Declaration><![CDATA[METHOD PRIVATE CalcScalingFactors : BOOL
|
||||
VAR
|
||||
_rNum : REAL;
|
||||
_rDenom : REAL;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// _lrConversionFactor := (udiAIMax - udiAIMin)/(rPVMax - rPVMin) + udiAIMin
|
||||
// Splitted in two calculations to catch division by zero
|
||||
_rNum := INT_TO_REAL(stAnalogIOConfig.iAIMax - stAnalogIOConfig.iAIMin);
|
||||
_rDenom := (stAnalogIOConfig.rPVMax - stAnalogIOConfig.rPVMin);
|
||||
|
||||
// Do not divide by 0 or a negative number
|
||||
IF _rDenom > 0.0 THEN
|
||||
_rConversionFactor := _rNum/_rDenom;
|
||||
_rBaseOffset := INT_TO_REAL(stAnalogIOConfig.iAIMin) - (_rConversionFactor * stAnalogIOConfig.rPVMin);
|
||||
_rPVMax := stAnalogIOConfig.rPVMax;
|
||||
_rPVMin := stAnalogIOConfig.rPVMin;
|
||||
_xConfigError := FALSE;
|
||||
ELSE
|
||||
// Division by zero happened
|
||||
// Or denom was negative
|
||||
// Set scaling to zero
|
||||
_rConversionFactor := 0.0;
|
||||
_rBaseOffset := 0.0;
|
||||
_rPVMax := 0.0;
|
||||
_rPVMin := 0.0;
|
||||
_xConfigError := TRUE;
|
||||
END_IF]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="CreateAlarmMSG" Id="{874f5254-0ec6-4c5e-a9a6-0292ac71a964}">
|
||||
<Declaration><![CDATA[METHOD PRIVATE CreateAlarmMSG
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[{analysis -46}
|
||||
_fbAlarmConfigError.Arguments.Clear().AddString(_sName);
|
||||
{analysis +46}]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="FB_init" Id="{0b8b8fc1-2085-4a85-a9d5-deae06fafe01}">
|
||||
<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)
|
||||
|
||||
sName : STRING;
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[_sName := sName;
|
||||
|
||||
CreateAlarmMSG();]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Property Name="Name" Id="{33bc699d-7760-4934-8e7d-cd24d62ae4d2}">
|
||||
<Declaration><![CDATA[PROPERTY Name : STRING(80)]]></Declaration>
|
||||
<Get Name="Get" Id="{21d4b695-16bc-443c-9b7e-27e6c5e1de73}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[Name := _sName;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
<Set Name="Set" Id="{c423a761-157c-4651-9a9a-3e5b0e891e86}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[_sName := Name;
|
||||
|
||||
// After a name change, all error messages have to be changed
|
||||
CreateAlarmMSG();]]></ST>
|
||||
</Implementation>
|
||||
</Set>
|
||||
</Property>
|
||||
</POU>
|
||||
</TcPlcObject>
|
||||
12
PLC/POUs/Components/Analog/Types/ST_ANALOG_EW_CONFIG.TcDUT
Normal file
12
PLC/POUs/Components/Analog/Types/ST_ANALOG_EW_CONFIG.TcDUT
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<DUT Name="ST_ANALOG_EW_CONFIG" Id="{6f3ed88d-28a0-4a7f-a26a-6b822e47799e}">
|
||||
<Declaration><![CDATA[TYPE ST_ANALOG_EW_CONFIG :
|
||||
STRUCT
|
||||
stLevels : ST_ANALOG_EW_LEVELS;
|
||||
stDelays : ST_ANALOG_EW_DELAYS;
|
||||
END_STRUCT
|
||||
END_TYPE
|
||||
]]></Declaration>
|
||||
</DUT>
|
||||
</TcPlcObject>
|
||||
31
PLC/POUs/Components/Analog/Types/ST_ANALOG_EW_DELAYS.TcDUT
Normal file
31
PLC/POUs/Components/Analog/Types/ST_ANALOG_EW_DELAYS.TcDUT
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<DUT Name="ST_ANALOG_EW_DELAYS" Id="{8b5ae408-253c-4618-ab64-5d8c4935716b}">
|
||||
<Declaration><![CDATA[TYPE ST_ANALOG_EW_DELAYS :
|
||||
STRUCT
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
timHardwareSignalLevelOn : TIME;
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
timHardwareSignalLevelOff : TIME;
|
||||
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
timErrorLowOn : TIME;
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
timErrorLowOff : TIME;
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
timWarningLowOn : TIME;
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
timWarningLowOff : TIME;
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
timWarningHighOn : TIME;
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
timWarningHighOff : TIME;
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
timErrorHighOn : TIME;
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
timErrorHighOff : TIME;
|
||||
END_STRUCT
|
||||
END_TYPE
|
||||
]]></Declaration>
|
||||
</DUT>
|
||||
</TcPlcObject>
|
||||
18
PLC/POUs/Components/Analog/Types/ST_ANALOG_EW_LEVELS.TcDUT
Normal file
18
PLC/POUs/Components/Analog/Types/ST_ANALOG_EW_LEVELS.TcDUT
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<DUT Name="ST_ANALOG_EW_LEVELS" Id="{40734543-a4f6-4336-bcfe-ac65f034a277}">
|
||||
<Declaration><![CDATA[TYPE ST_ANALOG_EW_LEVELS :
|
||||
STRUCT
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
rErrorMin : REAL;
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
rWarningMin : REAL;
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
rWarningMax : REAL;
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
rErrorMax : REAL;
|
||||
END_STRUCT
|
||||
END_TYPE
|
||||
]]></Declaration>
|
||||
</DUT>
|
||||
</TcPlcObject>
|
||||
33
PLC/POUs/Components/Analog/Types/ST_ANALOG_IO_CONFIG.TcDUT
Normal file
33
PLC/POUs/Components/Analog/Types/ST_ANALOG_IO_CONFIG.TcDUT
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<DUT Name="ST_ANALOG_IO_CONFIG" Id="{ee57b40d-d65d-438f-80f9-912bc67bff84}">
|
||||
<Declaration><![CDATA[TYPE ST_ANALOG_IO_CONFIG :
|
||||
STRUCT
|
||||
// Maximum analog value
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
iAIMax : INT;
|
||||
|
||||
// Minimum analog value
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
iAIMin : INT;
|
||||
|
||||
// Maximum process value
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
rPVMax : REAL;
|
||||
|
||||
// Minimum process value
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
rPVMin : REAL;
|
||||
|
||||
// Process unit (V, A, P, U/min, %, rpm etc)
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
sUnit : STRING;
|
||||
|
||||
// Analog IO is used
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
xUsed : BOOL := TRUE;
|
||||
END_STRUCT
|
||||
END_TYPE
|
||||
]]></Declaration>
|
||||
</DUT>
|
||||
</TcPlcObject>
|
||||
334
PLC/POUs/Components/EventListener/FB_EventListener.TcPOU
Normal file
334
PLC/POUs/Components/EventListener/FB_EventListener.TcPOU
Normal file
@@ -0,0 +1,334 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<POU Name="FB_EventListener" Id="{f2b95750-ccda-4cd6-a03a-c64e3d2c4751}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[{attribute 'no_assign'}
|
||||
FUNCTION_BLOCK FB_EventListener EXTENDS FB_ListenerBase2
|
||||
VAR_INPUT
|
||||
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
END_VAR
|
||||
VAR
|
||||
_fbEventLogger : FB_TcEventLogger;
|
||||
|
||||
_fbEventFilter : FB_TcEventFilter;
|
||||
|
||||
_fbMqttClient : FB_IotMqtt5Client;
|
||||
|
||||
_fbBuffer : FB_MemRingBuffer;
|
||||
_abAlarmBuffer : ARRAY[0..1000] OF BYTE;
|
||||
|
||||
_fbJson : FB_JsonSaxWriter;
|
||||
|
||||
_sTopic : STRING(255);
|
||||
_stBufferEventEntryToBuffer : ST_BufferEventEntry;
|
||||
_stBufferEventEntryFromBuffer : ST_BufferEventEntry;
|
||||
|
||||
{attribute 'TcEncoding':='UTF-8'}
|
||||
_sLastMessageText : STRING;
|
||||
|
||||
_udiCurrentEntries : UDINT;
|
||||
|
||||
_uiState : UINT := 0;
|
||||
|
||||
// Result from read buffer head
|
||||
_xSuccess : BOOL;
|
||||
|
||||
// Results from read event message
|
||||
_xGetTextDone : BOOL;
|
||||
_xGetTextError : BOOL;
|
||||
|
||||
// Internal signal to connect to mqtt broker
|
||||
_xConnect : BOOL := TRUE;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Needs to be called to get alarms and events
|
||||
SUPER^.Execute();
|
||||
|
||||
// Call mqtt client
|
||||
_fbMqttClient.Execute(bConnect := _xConnect);
|
||||
|
||||
// Check if we have alarms to send
|
||||
IF _udiCurrentEntries > 0 THEN
|
||||
{analysis -19}
|
||||
_fbBuffer.A_RemoveHead(pRead:= ADR(_stBufferEventEntryFromBuffer),
|
||||
cbRead:= SIZEOF(_stBufferEventEntryFromBuffer),
|
||||
pBuffer:= ADR(_abAlarmBuffer),
|
||||
cbBuffer:= SIZEOF(_abAlarmBuffer),
|
||||
bOk=> _xSuccess,
|
||||
nCount => _udiCurrentEntries);
|
||||
{analysis +19}
|
||||
IF _xSuccess THEN
|
||||
_uiState := 10;
|
||||
END_IF
|
||||
END_IF
|
||||
|
||||
CASE _uiState OF
|
||||
0: // Idle
|
||||
|
||||
10: // Get alarm text
|
||||
_xGetTextDone := _stBufferEventEntryFromBuffer.fbAlarm.RequestEventText(
|
||||
nLangId := 1033,
|
||||
sResult := _sLastMessageText,
|
||||
nResultSize := SIZEOF(_sLastMessageText),
|
||||
bError => _xGetTextError);
|
||||
|
||||
IF _xGetTextError THEN
|
||||
_sLastMessageText := '';
|
||||
_uiState := 20;
|
||||
ELSIF _xGetTextDone THEN
|
||||
_uiState := 20;
|
||||
END_IF
|
||||
|
||||
20: // Create mqtt message
|
||||
CreateMessage();
|
||||
_uiState := 0;
|
||||
|
||||
ELSE
|
||||
// Do nothing
|
||||
;
|
||||
END_CASE]]></ST>
|
||||
</Implementation>
|
||||
<Method Name="AddAlarmToQueue" Id="{21a4a6af-4b8a-455f-b344-9cb0224cbfab}">
|
||||
<Declaration><![CDATA[METHOD PRIVATE AddAlarmToQueue : BOOL
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
VAR
|
||||
_xOk : BOOL;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[{analysis -19}
|
||||
_fbBuffer.A_AddTail( pWrite:= ADR( _stBufferEventEntryToBuffer ),
|
||||
cbWrite:= SIZEOF( _stBufferEventEntryToBuffer ),
|
||||
pBuffer:= ADR( _abAlarmBuffer ),
|
||||
cbBuffer:= SIZEOF( _abAlarmBuffer ),
|
||||
bOk=> _xOk,
|
||||
nCount => _udiCurrentEntries);
|
||||
{analysis +19}
|
||||
|
||||
AddAlarmToQueue := _xOk;
|
||||
]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="CreateMessage" Id="{d6f40ec8-01e1-47a8-a5b0-10322e1b0d10}">
|
||||
<Declaration><![CDATA[METHOD PRIVATE CreateMessage
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
VAR
|
||||
_sTemp : STRING;
|
||||
_sJsonDocument : STRING(255);
|
||||
_fbArguments : I_TcArguments;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[_fbJson.ResetDocument();
|
||||
_fbJson.StartObject();
|
||||
|
||||
// id todo test hashing
|
||||
_fbJson.AddKey('id');
|
||||
_fbJson.AddUdint(_stBufferEventEntryFromBuffer.fbAlarm.nUniqueId);
|
||||
|
||||
// Skip parent
|
||||
|
||||
// ack
|
||||
_fbJson.AddKey('ack');
|
||||
CASE _stBufferEventEntryFromBuffer.fbAlarm.eConfirmationState OF
|
||||
TcEventConfirmationState.WaitForConfirmation:
|
||||
_fbJson.AddUdint(1);
|
||||
|
||||
TcEventConfirmationState.Confirmed:
|
||||
_fbJson.AddUdint(2);
|
||||
|
||||
ELSE
|
||||
_fbJson.AddUdint(0);
|
||||
END_CASE
|
||||
|
||||
|
||||
// state
|
||||
_fbJson.AddKey('state');
|
||||
IF _stBufferEventEntryFromBuffer.fbAlarm.bActive THEN
|
||||
_fbJson.AddUdint(1);
|
||||
ELSE
|
||||
_fbJson.AddUdint(0);
|
||||
END_IF
|
||||
|
||||
|
||||
// t0
|
||||
_fbJson.AddKey('t0');
|
||||
// In case of a reraise this will be updated!!!
|
||||
_fbJson.AddUlint(_stBufferEventEntryFromBuffer.fbAlarm.nTimeRaised);
|
||||
|
||||
|
||||
// t1
|
||||
_fbJson.AddKey('t1');
|
||||
|
||||
CASE _stBufferEventEntryFromBuffer.eEventType OF
|
||||
E_EventType.RAISED:
|
||||
_fbJson.AddUlint(_stBufferEventEntryFromBuffer.fbAlarm.nTimeRaised);
|
||||
|
||||
E_EventType.CLEARED:
|
||||
_fbJson.AddUlint(_stBufferEventEntryFromBuffer.fbAlarm.nTimeCleared);
|
||||
|
||||
E_EventType.CONFIRMED:
|
||||
_fbJson.AddUlint(_stBufferEventEntryFromBuffer.fbAlarm.nTimeConfirmed);
|
||||
|
||||
ELSE
|
||||
_fbJson.AddUlint(0);
|
||||
END_CASE
|
||||
|
||||
|
||||
// Skipp access rights
|
||||
|
||||
// Skipp origin id use origin name instead
|
||||
|
||||
// origin
|
||||
_fbJson.AddKey('origin');
|
||||
{analysis -46}
|
||||
_sTemp := _stBufferEventEntryFromBuffer.fbAlarm.ipSourceInfo.sName;
|
||||
{analysis +46}
|
||||
_fbJson.AddString(_sTemp);
|
||||
|
||||
// Skipp message id because there is no catalogue
|
||||
|
||||
// msg
|
||||
_fbJson.AddKey('msg');
|
||||
_fbJson.AddString(_sLastMessageText);
|
||||
|
||||
// s
|
||||
_fbJson.AddKey('s');
|
||||
CASE _stBufferEventEntryFromBuffer.fbAlarm.eSeverity OF
|
||||
TcEventSeverity.Info:
|
||||
_fbJson.AddUdint(96);
|
||||
|
||||
TcEventSeverity.Warning:
|
||||
_fbJson.AddUdint(160);
|
||||
|
||||
TcEventSeverity.Error:
|
||||
_fbJson.AddUdint(224);
|
||||
|
||||
TcEventSeverity.Critical:
|
||||
_fbJson.AddUdint(255);
|
||||
|
||||
ELSE
|
||||
_fbJson.AddUdint(32);
|
||||
END_CASE
|
||||
|
||||
// Skip message parameters
|
||||
|
||||
_fbArguments := _stBufferEventEntryFromBuffer.fbAlarm.ipArguments;
|
||||
_fbJson.EndObject();
|
||||
{analysis -26}
|
||||
_fbJson.CopyDocument(_sJsonDocument, SIZEOF(_sJsonDocument));
|
||||
{analysis +26}
|
||||
|
||||
// Send topic
|
||||
_fbMqttClient.Publish(
|
||||
sTopic:= 'SlmMachine/Notifications/NAMESPACE/Detail',
|
||||
pPayload:= ADR(_sTemp),
|
||||
nPayloadSize:= LEN2(ADR(_sTemp))+1,
|
||||
eQoS:= TcIotMqttQos.AtLeastOnceDelivery,
|
||||
bRetain:= FALSE,
|
||||
bQueue:= FALSE);]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="FB_Init" Id="{a946d52f-a0e6-4aac-9d4c-5dd8aba5f5d2}">
|
||||
<Declaration><![CDATA[//FB_Init is always available implicitly and it is used primarily for initialization.
|
||||
//The return value is not evaluated. For a specific influence, you can also declare the
|
||||
//methods explicitly and provide additional code there with the standard initialization
|
||||
//code. You can evaluate the return value.
|
||||
METHOD FB_Init: BOOL
|
||||
VAR_INPUT
|
||||
bInitRetains: BOOL; // TRUE: the retain variables are initialized (reset warm / reset cold)
|
||||
bInCopyCode: BOOL; // TRUE: the instance will be copied to the copy code afterward (online change)
|
||||
|
||||
sHostName : STRING := 'localhost';
|
||||
uiHostPort : UINT := 1883;
|
||||
sTopic : STRING(255);
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Register alarms and messages
|
||||
_fbEventFilter.Clear().IsAlarm().OR_OP().IsMessage();
|
||||
Subscribe2(ipEventFilter := _fbEventFilter);
|
||||
|
||||
// Setup mqtt client parameters
|
||||
_fbMqttClient.sHostName := sHostName;
|
||||
_fbMqttClient.nHostPort := uiHostPort;
|
||||
_sTopic := sTopic;
|
||||
|
||||
// Reset buffer
|
||||
_fbBuffer.A_Reset();]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="OnAlarmCleared" Id="{00aefa2e-a70c-4880-b7a7-760d0051e0ee}">
|
||||
<Declaration><![CDATA[METHOD OnAlarmCleared : Tc3_EventLogger.HRESULT
|
||||
VAR_INPUT
|
||||
{attribute 'naming' := 'off'}
|
||||
fbEvent : REFERENCE TO Tc3_EventLogger.FB_TcEvent;
|
||||
{attribute 'naming' := 'on'}
|
||||
END_VAR
|
||||
VAR
|
||||
_xSuccess : BOOL;
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[IF __ISVALIDREF(fbEvent) THEN
|
||||
_fbEventLogger.GetAlarmEx(stEventEntry := fbEvent.stEventEntry, ipSourceInfo := fbEvent.ipSourceInfo, fbAlarm := _stBufferEventEntryToBuffer.fbAlarm);
|
||||
_stBufferEventEntryToBuffer.eEventType := E_EventType.CLEARED;
|
||||
_xSuccess := AddAlarmToQueue();
|
||||
END_IF
|
||||
|
||||
]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="OnAlarmConfirmed" Id="{4f33c838-6809-4051-9524-d88e2cf6713c}">
|
||||
<Declaration><![CDATA[METHOD OnAlarmConfirmed : Tc3_EventLogger.HRESULT
|
||||
VAR_INPUT
|
||||
{attribute 'naming' := 'off'}
|
||||
fbEvent : REFERENCE TO Tc3_EventLogger.FB_TcEvent;
|
||||
{attribute 'naming' := 'on'}
|
||||
END_VAR
|
||||
VAR
|
||||
_xSuccess : BOOL;
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[IF __ISVALIDREF(fbEvent) THEN
|
||||
_fbEventLogger.GetAlarmEx(stEventEntry := fbEvent.stEventEntry, ipSourceInfo := fbEvent.ipSourceInfo, fbAlarm := _stBufferEventEntryToBuffer.fbAlarm);
|
||||
_stBufferEventEntryToBuffer.eEventType := E_EventType.CONFIRMED;
|
||||
_xSuccess := AddAlarmToQueue();
|
||||
END_IF]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="OnAlarmRaised" Id="{2454a94e-91c5-4b90-9762-eaee63119c3b}">
|
||||
<Declaration><![CDATA[METHOD OnAlarmRaised : Tc3_EventLogger.HRESULT
|
||||
VAR_INPUT
|
||||
{attribute 'naming' := 'off'}
|
||||
fbEvent : REFERENCE TO Tc3_EventLogger.FB_TcEvent;
|
||||
{attribute 'naming' := 'on'}
|
||||
END_VAR
|
||||
VAR
|
||||
_xSuccess : BOOL;
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[IF __ISVALIDREF(fbEvent) THEN
|
||||
_fbEventLogger.GetAlarmEx(stEventEntry := fbEvent.stEventEntry, ipSourceInfo := fbEvent.ipSourceInfo, fbAlarm := _stBufferEventEntryToBuffer.fbAlarm);
|
||||
_stBufferEventEntryToBuffer.eEventType := E_EventType.RAISED;
|
||||
_xSuccess := AddAlarmToQueue();
|
||||
END_IF
|
||||
]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="OnMessageSent" Id="{13d5d489-4166-4664-bd09-265b3b8bc14f}">
|
||||
<Declaration><![CDATA[METHOD OnMessageSent : Tc3_EventLogger.HRESULT
|
||||
VAR_INPUT
|
||||
{attribute 'naming' := 'off'}
|
||||
fbEvent : REFERENCE TO Tc3_EventLogger.FB_TcEvent;
|
||||
{attribute 'naming' := 'on'}
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
</POU>
|
||||
</TcPlcObject>
|
||||
17
PLC/POUs/Components/EventListener/Types/E_EventType.TcDUT
Normal file
17
PLC/POUs/Components/EventListener/Types/E_EventType.TcDUT
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<DUT Name="E_EventType" Id="{c41c8e8d-56af-4514-8482-2c521e403b96}">
|
||||
<Declaration><![CDATA[{attribute 'qualified_only'}
|
||||
{attribute 'strict'}
|
||||
{attribute 'to_string'}
|
||||
TYPE E_EventType :
|
||||
(
|
||||
RAISED := 0,
|
||||
CLEARED,
|
||||
CONFIRMED,
|
||||
MESSAGE
|
||||
);
|
||||
END_TYPE
|
||||
]]></Declaration>
|
||||
</DUT>
|
||||
</TcPlcObject>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<DUT Name="ST_BufferEventEntry" Id="{95daccce-6c97-4afa-b8a3-fb60fb3847c5}">
|
||||
<Declaration><![CDATA[TYPE ST_BufferEventEntry :
|
||||
STRUCT
|
||||
fbAlarm : FB_TcAlarm;
|
||||
eEventType : E_EventType;
|
||||
END_STRUCT
|
||||
END_TYPE
|
||||
]]></Declaration>
|
||||
</DUT>
|
||||
</TcPlcObject>
|
||||
497
PLC/POUs/Components/Motor/FB_MotorBecker.TcPOU
Normal file
497
PLC/POUs/Components/Motor/FB_MotorBecker.TcPOU
Normal file
@@ -0,0 +1,497 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<POU Name="FB_MotorBecker" Id="{6ad1d5ad-7633-46cc-9d09-24bf8179e070}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FINAL FB_MotorBecker
|
||||
VAR_INPUT
|
||||
// Start motor from automatic
|
||||
xAutomaticStart : BOOL;
|
||||
|
||||
// Automatic setpoint
|
||||
rSPAutomatic : REAL;
|
||||
|
||||
// Analog motor config data
|
||||
stMotorConfig : ST_MOTOR_BECKER_CONFIG;
|
||||
|
||||
// Inverter statusword
|
||||
udiStatusword AT %I* : UDINT;
|
||||
|
||||
// Motor speed process value
|
||||
rProcessValue AT %I* : REAL;
|
||||
|
||||
// Errorword 1
|
||||
udiErrorword1 AT %I* : UDINT;
|
||||
|
||||
// Errorword 2
|
||||
udiErrorword2 AT %I* : UDINT;
|
||||
|
||||
// Release or block change to manual mode
|
||||
xReleaseManualMode : BOOL;
|
||||
|
||||
// Process interlocks
|
||||
wProcessINTLK : T_INTERLOCK;
|
||||
|
||||
// Used process interlocks
|
||||
wProcessINTLKUsed: T_INTERLOCK;
|
||||
|
||||
// Safety interlocks
|
||||
wSafetyINTLK : T_INTERLOCK;
|
||||
|
||||
// Used safety interlocks
|
||||
wSafetyINTLKUsed: T_INTERLOCK;
|
||||
|
||||
// Motor circuit breaker ok
|
||||
xMCBOk AT %I* : BOOL;
|
||||
|
||||
// Repair switch ok
|
||||
xRepairSwitchOk AT %I* : BOOL;
|
||||
|
||||
// Global switch to dissable all errors
|
||||
xReleaseErrors : 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
|
||||
// Controlword
|
||||
udiControlword AT %Q* : UDINT;
|
||||
|
||||
// Motor frequency setpoint
|
||||
rMotorFrequency AT %Q* : REAL;
|
||||
|
||||
// Motor in target speed
|
||||
xInTarget : BOOL;
|
||||
|
||||
// Warning output
|
||||
xWarning : BOOL;
|
||||
|
||||
// Error output
|
||||
xError : BOOL;
|
||||
END_VAR
|
||||
VAR_IN_OUT
|
||||
stHMIInterface : ST_HMI_ANALOG_MOTOR_DATA;
|
||||
END_VAR
|
||||
VAR
|
||||
// Internal command for manual mode start request
|
||||
_xManualStart : BOOL := FALSE;
|
||||
|
||||
// Manual mode active
|
||||
_xManualModeActive : BOOL := FALSE;
|
||||
|
||||
// Automatic mode active
|
||||
_xAutomaticModeActive : BOOL := TRUE;
|
||||
|
||||
// Internal start command
|
||||
_xStart : BOOL;
|
||||
|
||||
// Internal setpoint
|
||||
_rSetpoint : REAL;
|
||||
|
||||
// Setpoint from ramp generator in target range
|
||||
_xRampGenInTarget : BOOL;
|
||||
|
||||
// Calculated allowed window for process value
|
||||
_rPVTargetMax : REAL;
|
||||
_rPVTargetMin : REAL;
|
||||
|
||||
// Ramp generator for start and stop ramp
|
||||
_fbRamp : FB_RampGenerator;
|
||||
|
||||
// Motor MCB tripped
|
||||
_xMCBTripped : BOOL;
|
||||
|
||||
// Motor repair switch tripped
|
||||
_xRepairSwitchOpenLatched : BOOL;
|
||||
|
||||
// Sum of all activated process interlocks latched
|
||||
_xSafetyINTLKOk : BOOL;
|
||||
|
||||
// Sum of all activated process interlocks
|
||||
_xProcessINTLKOk : BOOL;
|
||||
|
||||
// Motor running internal state
|
||||
_xMotorRunning : BOOL;
|
||||
|
||||
// Motor stopped internal state
|
||||
_xMotorStopped : BOOL;
|
||||
|
||||
// Alarm handler for MCB tripped
|
||||
_fbAlarmMCBTripped : FB_TcAlarm;
|
||||
_fbMCBTrippedDelayedSignal : FB_ReleaseSignal;
|
||||
|
||||
// Alarm handler for repair switch not closed
|
||||
_fbAlarmRepairSwitchOpen : FB_TcAlarm;
|
||||
|
||||
// Error handlers
|
||||
_fbAlarmNotInTarget : FB_TcAlarm;
|
||||
_fbNotInRange : FB_ReleaseSignal;
|
||||
|
||||
// Helper for statusword
|
||||
_dwStatusword : DWORD;
|
||||
|
||||
// Helper for control word
|
||||
_dwControlword : DWORD;
|
||||
|
||||
// Motor error active
|
||||
_xError : BOOL;
|
||||
|
||||
// Name of the motor
|
||||
_sName : STRING;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// ===============
|
||||
// Handle not used
|
||||
// ===============
|
||||
|
||||
IF (NOT stMotorConfig.xUsed) THEN
|
||||
// Clear all pending alarms if there are any
|
||||
IF _fbAlarmMCBTripped.bRaised THEN
|
||||
_fbAlarmMCBTripped.Clear(0, TRUE);
|
||||
END_IF
|
||||
|
||||
IF _fbAlarmRepairSwitchOpen.bRaised THEN
|
||||
_fbAlarmRepairSwitchOpen.Clear(0, TRUE);
|
||||
END_IF
|
||||
|
||||
IF _fbAlarmNotInTarget.bRaised THEN
|
||||
_fbAlarmNotInTarget.Clear(0, TRUE);
|
||||
END_IF
|
||||
|
||||
RETURN;
|
||||
END_IF
|
||||
|
||||
// ===========================
|
||||
// Reset safetyinterlocks flag
|
||||
// ===========================
|
||||
|
||||
IF xConfirmAlarms AND (NOT _xSafetyINTLKOk) THEN
|
||||
_xSafetyINTLKOk := TRUE;
|
||||
END_IF
|
||||
|
||||
|
||||
// Check interlocks
|
||||
CheckInterlocks();
|
||||
|
||||
// =================
|
||||
// Handle HMI inputs
|
||||
// =================
|
||||
|
||||
HandleHMIInput();
|
||||
|
||||
|
||||
// ==============================
|
||||
// Check if all interlocks are ok
|
||||
// ==============================
|
||||
|
||||
// Only reset manual command if safetyinterlocks are not ok
|
||||
IF (NOT _xSafetyINTLKOk) AND _xManualStart THEN
|
||||
// Also reset manual open command if safetyinterlocks are set
|
||||
_xManualStart := FALSE;
|
||||
END_IF
|
||||
|
||||
|
||||
// =====================================
|
||||
// Handle starting and stopping of motor
|
||||
// =====================================
|
||||
|
||||
_xStart := _xProcessINTLKOk AND _xSafetyINTLKOk AND ((_xManualStart AND _xManualModeActive AND (NOT _xAutomaticModeActive)) OR ( xAutomaticStart AND _xAutomaticModeActive AND (NOT _xManualModeActive)));
|
||||
|
||||
IF _xStart THEN
|
||||
IF _xManualModeActive AND (NOT _xAutomaticModeActive) THEN
|
||||
_rSetpoint := stHMIInterface.stSetpoint.rValue;
|
||||
ELSIF _xAutomaticModeActive AND (NOT _xManualModeActive) THEN
|
||||
_rSetpoint := rSPAutomatic;
|
||||
ELSE
|
||||
_rSetpoint := 0.0;
|
||||
END_IF
|
||||
ELSE
|
||||
_rSetpoint := 0.0;
|
||||
END_IF
|
||||
|
||||
// Clamp setpoint
|
||||
_rSetpoint := MAX(stMotorConfig.rTargetMin, _rSetpoint);
|
||||
_rSetpoint := MIN(stMotorConfig.rTargetMax, _rSetpoint);
|
||||
|
||||
|
||||
// Start stop motor
|
||||
IF _xStart THEN
|
||||
// Enable 1
|
||||
_dwControlword.0 := 1;
|
||||
// Enable PWM (austrudeln)
|
||||
_dwControlword.1 := 1;
|
||||
// Disable fast stop
|
||||
_dwControlword.2 := 1;
|
||||
// Seems to be the same as bit 1 and 2
|
||||
_dwControlword.3 := 1;
|
||||
_dwControlword.4 := 1;
|
||||
// Release setpoint
|
||||
_dwControlword.6 := 1;
|
||||
// Control via ethercat
|
||||
_dwControlword.10 := 1;
|
||||
ELSE
|
||||
// Enable 1
|
||||
_dwControlword.0 := 0;
|
||||
// Enable PWM (austrudeln)
|
||||
_dwControlword.1 := 1;
|
||||
// Disable fast stop
|
||||
_dwControlword.2 := 1;
|
||||
// Seems to be the same as bit 1 and 2
|
||||
_dwControlword.3 := 1;
|
||||
_dwControlword.4 := 1;
|
||||
// Release setpoint
|
||||
_dwControlword.6 := 0;
|
||||
// Control via ethercat
|
||||
_dwControlword.10 := 1;
|
||||
END_IF
|
||||
|
||||
_dwStatusword := UDINT_TO_DWORD(udiControlword);
|
||||
|
||||
// Wait for frequency converter to be enabled when we should start the motor
|
||||
// before starting the ramp
|
||||
IF _dwStatusword.0 // Ready to switch on
|
||||
AND _dwStatusword.1 // Ready for operation
|
||||
AND _dwStatusword.2 // Operational
|
||||
AND _dwStatusword.4 // No off 2
|
||||
AND _dwStatusword.5 // No off 3
|
||||
AND (NOT _dwStatusword.6) // PWM blocked
|
||||
AND (NOT _dwStatusword.3) THEN // No error active
|
||||
|
||||
|
||||
END_IF
|
||||
|
||||
_fbRamp(
|
||||
rTarget:= _rSetpoint,
|
||||
rTargetMin:= stMotorConfig.rTargetMin,
|
||||
rTargetMax:= stMotorConfig.rTargetMax,
|
||||
timRampUp:= stMotorConfig.timRampUpTime,
|
||||
timRampDown:= stMotorConfig.timRampDownTime,
|
||||
rSetpoint=> _rSetpoint,
|
||||
xInTarget=> _xRampGenInTarget);
|
||||
|
||||
// Calculate target tolerance
|
||||
_rPVTargetMax := _rSetpoint + stMotorConfig.rTargetTolerance;
|
||||
_rPVTargetMin := _rSetpoint - stMotorConfig.rTargetTolerance;
|
||||
|
||||
|
||||
// =============
|
||||
// Handle alarms
|
||||
// =============
|
||||
|
||||
_fbMCBTrippedDelayedSignal(
|
||||
xSignal:= (NOT xMCBOk),
|
||||
xRelease:= stMotorConfig.xHasMCBFeedback AND xReleaseErrors,
|
||||
timOnDelay:= ,
|
||||
timOffDelay:= ,
|
||||
xReleaseSignal=> );
|
||||
|
||||
|
||||
// ================
|
||||
// Reset error flag
|
||||
// ================
|
||||
|
||||
|
||||
// ================================
|
||||
// Copy internal signals to outputs
|
||||
// ================================
|
||||
|
||||
udiControlword := DWORD_TO_UDINT(_dwControlword);
|
||||
xError := _xError;
|
||||
|
||||
// ==================
|
||||
// Handle HMI outputs
|
||||
// ==================]]></ST>
|
||||
</Implementation>
|
||||
<Method Name="CheckInterlocks" Id="{df278299-6ae1-4de0-a0dd-2a6c6fe155af}">
|
||||
<Declaration><![CDATA[METHOD PRIVATE FINAL CheckInterlocks
|
||||
VAR
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Set interlocks ok
|
||||
_xProcessINTLKOk := TRUE;
|
||||
|
||||
// Check if all active interlocks are ok
|
||||
IF ((wProcessINTLK AND wProcessINTLKUsed) XOR wProcessINTLKUsed) > 0 THEN
|
||||
_xProcessINTLKOk := FALSE;
|
||||
END_IF
|
||||
|
||||
// Check safety interlocks
|
||||
// Safety interlocks will not automatically reset
|
||||
// They need to be reset via the xConfirmAlarms input
|
||||
IF ((wSafetyINTLK AND wSafetyINTLKUsed) XOR wSafetyINTLKUsed) > 0 THEN
|
||||
_xSafetyINTLKOk := FALSE;
|
||||
END_IF]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="CreateAlarmMSG" Id="{51bd55f4-6ff2-43af-9b06-6b00c317590c}">
|
||||
<Declaration><![CDATA[METHOD PRIVATE CreateAlarmMSG
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Reset MCB tripped parameter
|
||||
_fbAlarmMCBTripped.ipArguments.Clear().AddString(_sName);
|
||||
|
||||
// Reset Repair switch open parameter
|
||||
_fbAlarmRepairSwitchOpen.ipArguments.Clear().AddString(_sName);
|
||||
_fbAlarmNotInTarget.ipArguments.Clear().AddString(_sName);
|
||||
]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="FB_init" Id="{f631cde4-5e68-41ff-9cf4-981cfb26ac03}">
|
||||
<Declaration><![CDATA[METHOD FB_init : BOOL
|
||||
VAR_INPUT
|
||||
bInitRetains : BOOL; // if TRUE, the retain variables are initialized (warm start / cold start)
|
||||
bInCopyCode : BOOL; // if TRUE, the instance afterwards gets moved into the copy code (online change)
|
||||
|
||||
sName : STRING;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Name of the function block
|
||||
_sName := sName;
|
||||
|
||||
// Create MCB tripped error
|
||||
_fbAlarmMCBTripped.CreateEx(stEventEntry := TC_EVENTS.Motor.MCBTripped, TRUE, 0);
|
||||
|
||||
// Create repair switch error
|
||||
_fbAlarmRepairSwitchOpen.CreateEx(stEventEntry := TC_EVENTS.Motor.RepairSwitchOpen, TRUE, 0);
|
||||
|
||||
// Create not in target range alarm message
|
||||
_fbAlarmNotInTarget.CreateEx(stEventEntry := TC_EVENTS.Motor.NotInTarget, bWithConfirmation := TRUE, 0);
|
||||
|
||||
// Create alarm messages
|
||||
CreateAlarmMSG();]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="HandleHMIInput" Id="{faa08927-4f54-4ff8-952d-185a586720f8}">
|
||||
<Declaration><![CDATA[METHOD PRIVATE HandleHMIInput
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[{warning disable C0371}
|
||||
// Handle automatic mode request
|
||||
IF stHMIInterface.stAutomaticButton.xRequest AND (NOT _xAutomaticModeActive) THEN
|
||||
_xAutomaticModeActive := TRUE;
|
||||
_xManualModeActive := FALSE;
|
||||
END_IF
|
||||
|
||||
IF stHMIInterface.stAutomaticButton.xRequest THEN
|
||||
stHMIInterface.stAutomaticButton.xRequest := FALSE;
|
||||
END_IF
|
||||
|
||||
// Handle manual mode request
|
||||
IF stHMIInterface.stManualButton.xRequest AND (NOT _xManualModeActive) AND xReleaseManualMode THEN
|
||||
_xAutomaticModeActive := FALSE;
|
||||
_xManualModeActive := TRUE;
|
||||
|
||||
// Copy last requested valve state into manual
|
||||
_xManualStart := xAutomaticStart;
|
||||
stHMIInterface.stSetpoint.rValue := rSPautomatic;
|
||||
END_IF
|
||||
|
||||
IF stHMIInterface.stManualButton.xRequest THEN
|
||||
stHMIInterface.stManualButton.xRequest := FALSE;
|
||||
END_IF
|
||||
|
||||
// Handle start request
|
||||
IF stHMIInterface.stStartButton.xRequest AND _xManualModeActive AND _xProcessINTLKOk AND _xSafetyINTLKOk THEN
|
||||
_xManualStart := TRUE;
|
||||
END_IF
|
||||
|
||||
IF stHMIInterface.stStartButton.xRequest THEN
|
||||
stHMIInterface.stStartButton.xRequest := FALSE;
|
||||
END_IF
|
||||
|
||||
// Handle stop request
|
||||
IF stHMIInterface.stStopButton.xRequest AND _xManualModeActive THEN
|
||||
_xManualStart := FALSE;
|
||||
END_IF
|
||||
|
||||
IF stHMIInterface.stStopButton.xRequest THEN
|
||||
stHMIInterface.stStopButton.xRequest := FALSE;
|
||||
END_IF]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="HandleHMIOutputs" Id="{94e6a928-a0fe-415b-a749-82ef7bb664cb}">
|
||||
<Declaration><![CDATA[METHOD PRIVATE HandleHMIOutputs
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Copy setpoint min max
|
||||
stHMIInterface.stSetpoint.rMin := stMotorConfig.rTargetMin;
|
||||
stHMIInterface.stSetpoint.rMax := stMotorConfig.rTargetMax;]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Property Name="Name" Id="{df07aafd-aaef-4848-9ad0-67f926a1c07c}">
|
||||
<Declaration><![CDATA[{attribute 'analysis' := '-23'}
|
||||
PROPERTY Name : STRING]]></Declaration>
|
||||
<Get Name="Get" Id="{bad90e91-d5f6-49f1-bb66-233ae84af444}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[Name := _sName;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
<Set Name="Set" Id="{995fbf14-9a6c-4644-8204-b1aafcfead5f}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[_sName := Name;
|
||||
|
||||
]]></ST>
|
||||
</Implementation>
|
||||
</Set>
|
||||
</Property>
|
||||
<Property Name="ProcessInterlocksOK" Id="{666a9de5-5207-4562-a6d4-843121e8555a}">
|
||||
<Declaration><![CDATA[PROPERTY ProcessInterlocksOK : BOOL
|
||||
]]></Declaration>
|
||||
<Get Name="Get" Id="{b4c317e2-b02e-4348-87b1-407f40fbb27b}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[ProcessInterlocksOK := _xProcessINTLKOk;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
<Method Name="ReqAutomaticMode" Id="{7c1e32af-c936-48bc-92a2-a5719444ed8b}">
|
||||
<Declaration><![CDATA[METHOD ReqAutomaticMode
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[_xAutomaticModeActive := TRUE;
|
||||
_xManualModeActive := FALSE;]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="ReqManualMode" Id="{9b47097e-7518-44f6-8350-29161ed7891b}">
|
||||
<Declaration><![CDATA[METHOD ReqManualMode
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[IF xReleaseManualMode THEN
|
||||
_xManualModeActive := TRUE;
|
||||
_xAutomaticModeActive := FALSE;
|
||||
END_IF]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Property Name="SafetyInterlocksOK" Id="{197ebc7f-6847-4ed2-abf6-761b78adf519}">
|
||||
<Declaration><![CDATA[{attribute 'analysis' := '-31'}
|
||||
PROPERTY SafetyInterlocksOK : BOOL]]></Declaration>
|
||||
<Get Name="Get" Id="{b8f43bb8-2d37-40c1-b6a0-879caa30f816}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[SafetyInterlocksOK := _xSafetyINTLKOk;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
</POU>
|
||||
</TcPlcObject>
|
||||
50
PLC/POUs/Components/Motor/Types/ST_MOTOR_BECKER_CONFIG.TcDUT
Normal file
50
PLC/POUs/Components/Motor/Types/ST_MOTOR_BECKER_CONFIG.TcDUT
Normal file
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<DUT Name="ST_MOTOR_BECKER_CONFIG" Id="{4a385713-810a-4687-90a2-0bc7d0a40c62}">
|
||||
<Declaration><![CDATA[TYPE ST_MOTOR_BECKER_CONFIG :
|
||||
STRUCT
|
||||
// Minimum speed
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
rTargetMin : REAL := 0.0;
|
||||
|
||||
// Maximum speed
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
rTargetMax : REAL := 100.0;
|
||||
|
||||
// Maximum allowable difference between setpoint and process value
|
||||
// Defaults to +-5 units
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
rTargetTolerance : REAL := 5.0;
|
||||
|
||||
// Minimum process value when the motor should be seen as running
|
||||
// Defaults to 1 unit
|
||||
rPVMotorStopped : REAL := 1.0;
|
||||
|
||||
// Time for the valve to get to the requested setpoint
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
timNotInRange : TIME := T#30S;
|
||||
|
||||
// Startup time from 0% - 100%
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
timRampUpTime : TIME;
|
||||
|
||||
// Stop time from 100% - 0%
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
timRampDownTime : TIME;
|
||||
|
||||
// Has motor circuit breaker feedback signal
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
xHasMCBFeedback : BOOL;
|
||||
|
||||
// Has repair switch feedback signal
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
xHasRepairSwitchFeedback : BOOL;
|
||||
|
||||
// Motor is used
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
xUsed : BOOL := TRUE;
|
||||
END_STRUCT
|
||||
END_TYPE
|
||||
]]></Declaration>
|
||||
</DUT>
|
||||
</TcPlcObject>
|
||||
106
PLC/POUs/Components/Utilities/FB_AlarmMessage.TcPOU
Normal file
106
PLC/POUs/Components/Utilities/FB_AlarmMessage.TcPOU
Normal file
@@ -0,0 +1,106 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<POU Name="FB_AlarmMessage" Id="{4e628f13-10b9-47d9-8d26-ceb4bcb9bf43}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FINAL FB_AlarmMessage
|
||||
VAR_INPUT
|
||||
xActive : BOOL;
|
||||
xRelease : BOOL;
|
||||
xAcknowledge : BOOL;
|
||||
timOnDelay : TIME := T#0S;
|
||||
timOffDelay : TIME := T#0S;
|
||||
xInUnitTestMode : BOOL := FALSE;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
END_VAR
|
||||
VAR
|
||||
_fbReleaseAlarm : FB_ReleaseSignal;
|
||||
_fbAlarmMessage : FB_TcAlarm;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Filter alarm signal
|
||||
_fbReleaseAlarm(
|
||||
xSignal:= xActive,
|
||||
xRelease:= xRelease,
|
||||
timOnDelay:= timOnDelay,
|
||||
timOffDelay:= timOffDelay);
|
||||
|
||||
// Raise alarm
|
||||
IF _fbReleaseAlarm.xReleaseSignal AND (NOT xInUnitTestMode) AND (NOT _fbAlarmMessage.bRaised) THEN
|
||||
_fbAlarmMessage.Raise(0);
|
||||
END_IF
|
||||
|
||||
// Clear alarm
|
||||
IF ((NOT _fbReleaseAlarm.xReleaseSignal) OR (NOT xRelease)) AND (_fbAlarmMessage.bRaised) THEN
|
||||
_fbAlarmMessage.Clear(0, FALSE);
|
||||
END_IF
|
||||
|
||||
// Confirm alarm
|
||||
IF _fbAlarmMessage.eConfirmationState = TcEventConfirmationState.WaitForConfirmation AND (xAcknowledge OR (NOT xRelease)) THEN
|
||||
_fbAlarmMessage.Confirm(0);
|
||||
END_IF]]></ST>
|
||||
</Implementation>
|
||||
<Property Name="Active" Id="{4e7fa79e-e44f-42ff-ab45-0e14a9921a12}">
|
||||
<Declaration><![CDATA[PROPERTY Active : BOOL]]></Declaration>
|
||||
<Get Name="Get" Id="{70df159d-fc9d-44c5-ae42-7d731a5dae12}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[Active := _fbAlarmMessage.bActive;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
<Property Name="Arguments" Id="{f40c819a-ad71-4e81-830e-67d02b4e9e2f}">
|
||||
<Declaration><![CDATA[PROPERTY PUBLIC Arguments : I_TcArguments]]></Declaration>
|
||||
<Get Name="Get" Id="{c1b8ca1b-cb6c-4841-8282-61423914cb4e}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[Arguments := _fbAlarmMessage.ipArguments;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
<Method Name="FB_init" Id="{59e606ca-879e-463e-9089-6aa9e1011af6}">
|
||||
<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)
|
||||
|
||||
stEventEntry : TcEventEntry;
|
||||
xWithConfirmation : BOOL;
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Create alarm
|
||||
_fbAlarmMessage.CreateEx(stEventEntry := stEventEntry, bWithConfirmation := xWithConfirmation);]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Property Name="Raised" Id="{6c8f10b8-0c5e-4665-b985-30ac574d84e9}">
|
||||
<Declaration><![CDATA[PROPERTY Raised : BOOL]]></Declaration>
|
||||
<Get Name="Get" Id="{0ef44270-1843-4da0-932f-31f831130a1d}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[Raised := _fbAlarmMessage.bRaised;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
<Property Name="Triggered" Id="{84255a39-f5bd-41ec-9bb9-56c375350a5b}">
|
||||
<Declaration><![CDATA[PROPERTY Triggered : BOOL]]></Declaration>
|
||||
<Get Name="Get" Id="{1df049dd-1509-4300-b01e-e32eececdb86}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[Triggered := _fbReleaseAlarm.xReleaseSignal;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
</POU>
|
||||
</TcPlcObject>
|
||||
35
PLC/POUs/Components/Utilities/FB_Blinker.TcPOU
Normal file
35
PLC/POUs/Components/Utilities/FB_Blinker.TcPOU
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<POU Name="FB_Blinker" Id="{84dea953-e299-4743-83b2-332727c2009e}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[{attribute 'analysis' := '-56, -37'}
|
||||
FUNCTION_BLOCK FINAL FB_Blinker
|
||||
VAR_INPUT
|
||||
rFrequency : REAL;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
xOut : BOOL;
|
||||
END_VAR
|
||||
VAR
|
||||
_fbTON1 : TON;
|
||||
_fbTON2 : TON;
|
||||
|
||||
_timTime : TIME;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Calculate wait time
|
||||
IF rFrequency = 0.0 THEN
|
||||
rFrequency := 1.0;
|
||||
END_IF
|
||||
|
||||
_timTime := REAL_TO_TIME((1.0/rFrequency)*0.5*1000.0);
|
||||
|
||||
// Blinker base
|
||||
_fbTON1(IN := NOT _fbTON2.Q, PT := _timTime);
|
||||
_fbTON2(IN := _fbTON1.Q, PT := _timTime);
|
||||
|
||||
// Output
|
||||
xOut := _fbTON1.Q;]]></ST>
|
||||
</Implementation>
|
||||
</POU>
|
||||
</TcPlcObject>
|
||||
132
PLC/POUs/Components/Utilities/FB_RampGenerator.TcPOU
Normal file
132
PLC/POUs/Components/Utilities/FB_RampGenerator.TcPOU
Normal file
@@ -0,0 +1,132 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<POU Name="FB_RampGenerator" Id="{eab75824-fb3c-460a-af65-da2b006c5dc1}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[// Must only be called once per cycle!
|
||||
// Otherwise the Interpolation is wrong
|
||||
{attribute 'analysis' := '-56'}
|
||||
FUNCTION_BLOCK FB_RampGenerator
|
||||
VAR_INPUT
|
||||
// Current target value
|
||||
rTarget : REAL;
|
||||
|
||||
// Minimum target value
|
||||
rTargetMin : REAL;
|
||||
|
||||
// Maximum target value
|
||||
rTargetMax : REAL;
|
||||
|
||||
// Ramp up time (min to max)
|
||||
timRampUp : TIME;
|
||||
|
||||
// Ramp down time (max to min)
|
||||
timRampDown : TIME;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
rSetpoint : REAL := 0;
|
||||
|
||||
// Indicates that the target value has been reached
|
||||
xInTarget : BOOL;
|
||||
END_VAR
|
||||
VAR
|
||||
// Cycle time in ms
|
||||
_rCycleTime : REAL;
|
||||
|
||||
// Ramp up speed per cycle
|
||||
// Units per ms
|
||||
_rRampUpSpeed : REAL;
|
||||
|
||||
// Ramp down speed per cycle
|
||||
// Units per ms
|
||||
_rRampDownSpeed : REAL;
|
||||
|
||||
// Distance left to go
|
||||
_rDistanceToGo : REAL;
|
||||
|
||||
// First cycle
|
||||
_xFirstCycle : BOOL := TRUE;
|
||||
|
||||
_fbGetCurTaskIdx : GETCURTASKINDEX;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Get task cycle time during first cycle
|
||||
// Does not work in FB_init and also not with {attribute 'call_after_init'}
|
||||
IF _xFirstCycle THEN
|
||||
_xFirstCycle := FALSE;
|
||||
// Get current task cycle time
|
||||
_fbGetCurTaskIdx();
|
||||
// Convert 100ns to 1ms
|
||||
_rCycleTime := UDINT_TO_REAL(TwinCAT_SystemInfoVarList._TASKInfo[_fbGetCurTaskIdx.index].CycleTime) * 10E-5;
|
||||
END_IF
|
||||
|
||||
// Clamp setpoint to min max values
|
||||
{analysis -37}
|
||||
rTarget := MAX(rTarget, rTargetMin);
|
||||
rTarget := MIN(rTarget, rTargetMax);
|
||||
{analysis +37}
|
||||
|
||||
// Calculate change rates
|
||||
// TIME datatype is handled internally like a UDINT (32-bit). This leads to a resolution in milliseconds.
|
||||
// [_rRampUpSpeed] = units per cycle
|
||||
IF timRampUp <> T#0S THEN
|
||||
_rRampUpSpeed := (rTargetMax - rTargetMin) * (_rCycleTime / TIME_TO_REAL(timRampUp));
|
||||
ELSE
|
||||
_rRampUpSpeed := rTargetMax;
|
||||
END_IF
|
||||
IF timRampDown <> T#0S THEN
|
||||
_rRampDownSpeed := -(rTargetMax - rTargetMin) * (_rCycleTime / TIME_TO_REAL(timRampDown));
|
||||
ELSE
|
||||
_rRampDownSpeed := -rTargetMax;
|
||||
END_IF
|
||||
|
||||
|
||||
// Calculate distance left to go
|
||||
_rDistanceToGo := rTarget - rSetpoint;
|
||||
|
||||
// Calculate new setpoint
|
||||
IF (_rDistanceToGo > 0.0) THEN
|
||||
IF (_rDistanceToGo > _rRampUpSpeed) THEN
|
||||
rSetpoint := rSetpoint + _rRampUpSpeed;
|
||||
ELSE
|
||||
rSetpoint := rTarget;
|
||||
END_IF
|
||||
ELSIF (_rDistanceToGo < 0.0) THEN
|
||||
IF (_rDistanceToGo < _rRampDownSpeed) THEN
|
||||
rSetpoint := rSetpoint + _rRampDownSpeed;
|
||||
ELSE
|
||||
rSetpoint := rTarget;
|
||||
END_IF
|
||||
ELSE
|
||||
rSetpoint := rTarget;
|
||||
END_IF
|
||||
|
||||
// Check if we are in range of target range
|
||||
IF ABS(rSetpoint-rTarget) <= 0.001 THEN
|
||||
xInTarget := TRUE;
|
||||
ELSE
|
||||
xInTarget := FALSE;
|
||||
END_IF ]]></ST>
|
||||
</Implementation>
|
||||
<Property Name="CycleTime" Id="{12c00f80-a9cf-4d1b-ac68-3c3e59228015}">
|
||||
<Declaration><![CDATA[PROPERTY CycleTime : REAL]]></Declaration>
|
||||
<Get Name="Get" Id="{06853e5f-48e3-4643-ae4f-e23a07d71695}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[CycleTime := _rCycleTime;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
<Method Name="SetStart" Id="{06f2b416-7cfb-4f46-94e3-4002d92fc703}">
|
||||
<Declaration><![CDATA[METHOD SetStart
|
||||
VAR_INPUT
|
||||
rStartpoint : REAL;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[rSetpoint := rStartpoint;]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
</POU>
|
||||
</TcPlcObject>
|
||||
44
PLC/POUs/Components/Utilities/FB_ReleaseSignal.TcPOU
Normal file
44
PLC/POUs/Components/Utilities/FB_ReleaseSignal.TcPOU
Normal file
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<POU Name="FB_ReleaseSignal" Id="{95131698-43c9-4438-8f9f-0d910656ef66}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FINAL FB_ReleaseSignal
|
||||
VAR_INPUT
|
||||
// Signal to filter
|
||||
xSignal : BOOL := FALSE;
|
||||
|
||||
// Release signal output
|
||||
xRelease : BOOL := TRUE;
|
||||
|
||||
// Time for xSignal to be true before setting xReleaseSignal to true
|
||||
timOnDelay : TIME := T#0MS;
|
||||
|
||||
// Time for xSignal to be false before setting xReleaseSignal to false
|
||||
timOffDelay : TIME := T#0MS;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
// Filtered signal
|
||||
xReleaseSignal : BOOL;
|
||||
END_VAR
|
||||
VAR
|
||||
// Timer for on filtering
|
||||
_fbOnDelayTimer : TON;
|
||||
|
||||
// Timer for off filtering
|
||||
_fbOffDelayTimer : TON;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Delay on signal if signal is released
|
||||
_fbOnDelayTimer(IN:= xSignal AND xRelease, PT:= timOnDelay);
|
||||
IF _fbOnDelayTimer.Q THEN
|
||||
xReleaseSignal := TRUE;
|
||||
END_IF
|
||||
|
||||
// Delay off signal, return false even if off timer is still active
|
||||
_fbOffDelayTimer(IN:= (NOT xSignal), PT:= timOffDelay);
|
||||
IF _fbOffDelayTimer.Q OR (NOT xRelease) THEN
|
||||
xReleaseSignal := FALSE;
|
||||
END_IF]]></ST>
|
||||
</Implementation>
|
||||
</POU>
|
||||
</TcPlcObject>
|
||||
34
PLC/POUs/Components/Utilities/FC_HashFNV1a_32Bit.TcPOU
Normal file
34
PLC/POUs/Components/Utilities/FC_HashFNV1a_32Bit.TcPOU
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<POU Name="FC_HashFNV1a_32Bit" Id="{59a77c23-437d-4f1e-ae71-d5303ce54b27}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[FUNCTION FC_HashFNV1a_32Bit : UDINT
|
||||
VAR_INPUT
|
||||
psKey : POINTER TO STRING;
|
||||
END_VAR
|
||||
VAR
|
||||
// FNV-1a Hash value, seeded with starting value
|
||||
_udiHash : UDINT := 16#811C9DC5;
|
||||
|
||||
_uiCounter : UINT;
|
||||
END_VAR
|
||||
|
||||
VAR CONSTANT
|
||||
// FNV-1a prime number for a 32bit hash
|
||||
udiPrime : UDINT := 16#01000193;
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Version 1.2
|
||||
IF psKey = 0 THEN
|
||||
FC_HashFNV1a_32Bit := 0;
|
||||
RETURN;
|
||||
END_IF
|
||||
WHILE psKey^[_uiCounter] <> 0 DO
|
||||
_udiHash := (_udiHash XOR BYTE_TO_UDINT(psKey^[_uiCounter])) * udiPrime;
|
||||
_uiCounter := _uiCounter + 1;
|
||||
END_WHILE
|
||||
|
||||
// Return calculated Hash
|
||||
FC_HashFNV1a_32Bit := _udiHash;]]></ST>
|
||||
</Implementation>
|
||||
</POU>
|
||||
</TcPlcObject>
|
||||
520
PLC/POUs/Components/Valves/FB_Valve.TcPOU
Normal file
520
PLC/POUs/Components/Valves/FB_Valve.TcPOU
Normal file
@@ -0,0 +1,520 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<POU Name="FB_Valve" Id="{658f8bac-5e87-43a2-9b4c-a425a60acda2}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[FUNCTION_BLOCK FINAL FB_Valve
|
||||
VAR_INPUT
|
||||
xOpenFeedback AT %I* : BOOL;
|
||||
xCloseFeedback AT %I* : BOOL;
|
||||
|
||||
// Open and close the valve
|
||||
xAutomaticOpen : BOOL;
|
||||
|
||||
// Global switch to dissable all errors
|
||||
xReleaseErrors : BOOL := TRUE;
|
||||
|
||||
// Config input
|
||||
// Valve configuration parameters
|
||||
stValveConfig : ST_ValveConfig;
|
||||
|
||||
// Release or block change to manual mode
|
||||
xReleaseManualMode : BOOL;
|
||||
|
||||
// Process interlocks
|
||||
wProcessINTLK : T_INTERLOCK;
|
||||
wProcessINTLKUsed: T_INTERLOCK;
|
||||
|
||||
// Safety interlocks
|
||||
wSafetyINTLK : T_INTERLOCK;
|
||||
|
||||
// Used safety interlocks
|
||||
wSafetyINTLKUsed: T_INTERLOCK;
|
||||
|
||||
// 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
|
||||
// Use xOpenValve for normally closed valves
|
||||
xOpenValve AT %Q* : BOOL := FALSE;
|
||||
|
||||
// Use xCloseValve for normally open valves
|
||||
xCloseValve AT %Q* : BOOL := TRUE;
|
||||
|
||||
// Error in valve active
|
||||
xError : BOOL;
|
||||
END_VAR
|
||||
VAR_IN_OUT
|
||||
// HMI interface
|
||||
stHMIInterface : ST_HMI_VALVE_DATA;
|
||||
END_VAR
|
||||
VAR
|
||||
// Internal command for manual mode open request
|
||||
_xManualOpen : BOOL := FALSE;
|
||||
|
||||
// Manual mode active
|
||||
_xManualModeActive : BOOL := FALSE;
|
||||
|
||||
// Automatic mode active
|
||||
_xAutomaticModeActive : BOOL := TRUE;
|
||||
|
||||
// Sum of all activated interlocks
|
||||
_xProcessINTLKOk : BOOL;
|
||||
|
||||
// Sum of all activated process interlocks
|
||||
_xSafetyINTLKOk : BOOL := TRUE;
|
||||
|
||||
// Internal open state of the valve
|
||||
_xIsOpen : BOOL;
|
||||
|
||||
// Internal closed state of the valve
|
||||
_xIsClosed : BOOL;
|
||||
|
||||
// Name of valve
|
||||
// Will be set in constructor and can be changed with the name property
|
||||
_sName : STRING;
|
||||
|
||||
// Alarm handler for valve did not open
|
||||
_fbAlarmDidNotOpen : FB_AlarmMessage(stEventEntry := TC_EVENTS.Valve.DidNotOpen, xWithConfirmation := TRUE);
|
||||
|
||||
// Alarm handler for valve did not close
|
||||
_fbAlarmDidNotClose : FB_AlarmMessage(stEventEntry := TC_EVENTS.Valve.DidNotClose, xWithConfirmation := TRUE);
|
||||
|
||||
// Internal open command
|
||||
_xOpenValve : BOOL;
|
||||
|
||||
// Helper variables used in reset error flag
|
||||
_xAlarmsActive : BOOL;
|
||||
_xInputErrorsActive : BOOL;
|
||||
|
||||
// Internal error flags
|
||||
_xError : BOOL;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// ===============
|
||||
// Handle not used
|
||||
// ===============
|
||||
|
||||
IF (NOT stValveConfig.xUsed) THEN
|
||||
// Clear all pending alarms if there are any
|
||||
_fbAlarmDidNotOpen(xActive := FALSE, xRelease := FALSE);
|
||||
_fbAlarmDidNotClose(xActive := FALSE, xRelease := FALSE);
|
||||
|
||||
_xError := FALSE;
|
||||
xError := FALSE;
|
||||
|
||||
RETURN;
|
||||
END_IF
|
||||
|
||||
|
||||
// ===========================
|
||||
// Reset safetyinterlocks flag
|
||||
// ===========================
|
||||
|
||||
IF xConfirmAlarms AND (NOT _xSafetyINTLKOk) THEN
|
||||
_xSafetyINTLKOk := TRUE;
|
||||
END_IF
|
||||
|
||||
|
||||
// =========
|
||||
// Prechecks
|
||||
// =========
|
||||
|
||||
CheckInterlocks();
|
||||
|
||||
|
||||
// =================
|
||||
// Handle HMI inputs
|
||||
// =================
|
||||
|
||||
HandleHMIInput();
|
||||
|
||||
|
||||
// ===================================
|
||||
// Handle opening and closing of valve
|
||||
// ===================================
|
||||
|
||||
_xOpenValve := ((_xManualOpen AND _xManualModeActive AND (NOT _xAutomaticModeActive))
|
||||
OR ( xAutomaticOpen AND _xAutomaticModeActive AND (NOT _xManualModeActive)));
|
||||
|
||||
// Check for interlocks
|
||||
// If not, use valve state from settings
|
||||
IF (NOT _xProcessINTLKOk) OR (NOT _xSafetyINTLKOk) THEN
|
||||
_xOpenValve := stValveConfig.xOpenWhenInterlocksActive;
|
||||
|
||||
// Also reset manual open command if safetyinterlocks are set
|
||||
IF (NOT _xSafetyINTLKOk) AND (_xManualOpen <> stValveConfig.xOpenWhenInterlocksActive) THEN
|
||||
_xManualOpen := stValveConfig.xOpenWhenInterlocksActive;
|
||||
END_IF
|
||||
END_IF
|
||||
|
||||
// Handle open close feedback
|
||||
_xIsOpen := (stValveConfig.xHasOpenFeedback AND xOpenFeedback AND (NOT xCloseFeedback)) OR ((NOT stValveConfig.xHasOpenFeedback) AND _xOpenValve);
|
||||
_xIsClosed := (stValveConfig.xHasClosedFeedback AND xCloseFeedback AND (NOT xOpenFeedback)) OR ((NOT stValveConfig.xHasClosedFeedback) AND (NOT _xOpenValve));
|
||||
|
||||
|
||||
// ===========================
|
||||
// Valve did not open in time
|
||||
// ===========================
|
||||
|
||||
_fbAlarmDidNotOpen(
|
||||
xActive:= _xOpenValve AND (NOT _xIsOpen),
|
||||
xRelease:= xReleaseErrors,
|
||||
xAcknowledge:= xConfirmAlarms,
|
||||
timOnDelay:= stValveConfig.timTimeoutOpen,
|
||||
timOffDelay:= T#0S,
|
||||
xInUnitTestMode:= xInUnitTestMode);
|
||||
|
||||
// Latch error signal
|
||||
IF _fbAlarmDidNotOpen.Triggered THEN
|
||||
_xError := TRUE;
|
||||
END_IF
|
||||
|
||||
|
||||
// ===========================
|
||||
// Valve did not close in time
|
||||
// ===========================
|
||||
|
||||
_fbAlarmDidNotClose(
|
||||
xActive:= (NOT _xOpenValve) AND (NOT _xIsClosed),
|
||||
xRelease:= xReleaseErrors,
|
||||
xAcknowledge:= xConfirmAlarms,
|
||||
timOnDelay:= stValveConfig.timTimeoutClose,
|
||||
timOffDelay:= T#0S,
|
||||
xInUnitTestMode:= xInUnitTestMode);
|
||||
|
||||
// Latch error signal
|
||||
IF _fbAlarmDidNotClose.Triggered THEN
|
||||
_xError := TRUE;
|
||||
END_IF
|
||||
|
||||
|
||||
// ================
|
||||
// Reset error flag
|
||||
// ================
|
||||
|
||||
_xAlarmsActive := _fbAlarmDidNotOpen.Active OR _fbAlarmDidNotClose.Active;
|
||||
_xInputErrorsActive := _fbAlarmDidNotOpen.Triggered OR _fbAlarmDidNotClose.Triggered;
|
||||
|
||||
IF xConfirmAlarms AND _xError AND (NOT _xAlarmsActive) AND (NOT _xInputErrorsActive) THEN
|
||||
_xError := FALSE;
|
||||
END_IF
|
||||
|
||||
|
||||
// ================================
|
||||
// Copy internal signals to outputs
|
||||
// ================================
|
||||
|
||||
xOpenValve := _xOpenValve;
|
||||
xCloseValve := (NOT _xOpenValve);
|
||||
|
||||
xError := _xError;
|
||||
|
||||
|
||||
// ==================
|
||||
// Handle HMI outputs
|
||||
// ==================
|
||||
|
||||
HandleHMIOutput();]]></ST>
|
||||
</Implementation>
|
||||
<Method Name="CheckInterlocks" Id="{30a74d3e-2b2c-4675-9a57-4f19eacc7578}">
|
||||
<Declaration><![CDATA[METHOD PRIVATE FINAL CheckInterlocks
|
||||
VAR
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Set interlocks ok
|
||||
_xProcessINTLKOk := TRUE;
|
||||
|
||||
// Check if all active interlocks are ok
|
||||
IF ((wProcessINTLK AND wProcessINTLKUsed) XOR wProcessINTLKUsed) > 0 THEN
|
||||
_xProcessINTLKOk := FALSE;
|
||||
END_IF
|
||||
|
||||
// Check safety interlocks
|
||||
// Safety interlocks will not automatically reset
|
||||
// They need to be reset via the xConfirmAlarms input
|
||||
IF ((wSafetyINTLK AND wSafetyINTLKUsed) XOR wSafetyINTLKUsed) > 0 THEN
|
||||
_xSafetyINTLKOk := FALSE;
|
||||
END_IF]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="CreateAlarmMSG" Id="{afc73f4f-5060-43b3-9def-13568c293122}">
|
||||
<Declaration><![CDATA[METHOD PRIVATE CreateAlarmMSG
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Create did not in open alarm
|
||||
_fbAlarmDidNotOpen.Arguments.Clear().AddString(_sName);
|
||||
|
||||
// Create did not close alarm
|
||||
_fbAlarmDidNotClose.Arguments.Clear().AddString(_sName);]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="FB_init" Id="{0feef5ff-7efd-4523-9e63-83898cab15b4}">
|
||||
<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)
|
||||
|
||||
sName : STRING(80);
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[_sName := sName;
|
||||
|
||||
// Create alarm messages
|
||||
CreateAlarmMSG();]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="HandleHMIInput" Id="{daeab2cd-6c5b-4055-97d1-f9300c25c2a5}">
|
||||
<Declaration><![CDATA[METHOD PRIVATE HandleHMIInput
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[{warning disable C0371}
|
||||
// Handle automatic mode request
|
||||
IF stHMIInterface.stAutomaticButton.xRequest AND (NOT _xAutomaticModeActive) THEN
|
||||
_xAutomaticModeActive := TRUE;
|
||||
_xManualModeActive := FALSE;
|
||||
END_IF
|
||||
|
||||
IF stHMIInterface.stAutomaticButton.xRequest THEN
|
||||
stHMIInterface.stAutomaticButton.xRequest := FALSE;
|
||||
END_IF
|
||||
|
||||
// Handle manual mode request
|
||||
IF stHMIInterface.stManualButton.xRequest AND (NOT _xManualModeActive) AND xReleaseManualMode THEN
|
||||
_xAutomaticModeActive := FALSE;
|
||||
_xManualModeActive := TRUE;
|
||||
|
||||
// Copy last requested valve state into manual
|
||||
_xManualOpen := xAutomaticOpen;
|
||||
END_IF
|
||||
|
||||
IF stHMIInterface.stManualButton.xRequest THEN
|
||||
stHMIInterface.stManualButton.xRequest := FALSE;
|
||||
END_IF
|
||||
|
||||
// Handle open request
|
||||
IF stHMIInterface.stOpenButton.xRequest AND _xManualModeActive AND _xProcessINTLKOk AND _xSafetyINTLKOk THEN
|
||||
_xManualOpen := TRUE;
|
||||
END_IF
|
||||
|
||||
IF stHMIInterface.stOpenButton.xRequest THEN
|
||||
stHMIInterface.stOpenButton.xRequest := FALSE;
|
||||
END_IF
|
||||
|
||||
// Handle close request
|
||||
IF stHMIInterface.stCloseButton.xRequest AND _xManualModeActive THEN
|
||||
_xManualOpen := FALSE;
|
||||
END_IF
|
||||
|
||||
IF stHMIInterface.stCloseButton.xRequest THEN
|
||||
stHMIInterface.stCloseButton.xRequest := FALSE;
|
||||
END_IF]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="HandleHMIOutput" Id="{89ada59a-03b1-4917-880c-76f3bba59ef0}">
|
||||
<Declaration><![CDATA[METHOD PRIVATE HandleHMIOutput : BOOL
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[{warning disable C0371}
|
||||
// Handle open closed feedbacks
|
||||
IF (NOT _xIsOpen) AND (NOT _xIsClosed) AND (NOT _xError) THEN
|
||||
stHMIInterface.iStatus := E_HMI_VALVE_STATUS.TRANSITIONING;
|
||||
END_IF
|
||||
|
||||
IF _xIsOpen AND (NOT _xIsClosed) AND (NOT _xError) THEN
|
||||
stHMIInterface.iStatus := E_HMI_VALVE_STATUS.OPENED;
|
||||
END_IF
|
||||
|
||||
IF _xIsClosed AND (NOT _xIsOpen) AND (NOT _xError) THEN
|
||||
stHMIInterface.iStatus := E_HMI_VALVE_STATUS.CLOSED;
|
||||
END_IF
|
||||
|
||||
IF _xError THEN
|
||||
stHMIInterface.iStatus := E_HMI_VALVE_STATUS.ERROR;
|
||||
END_IF
|
||||
|
||||
// Copy config data to hmi interface
|
||||
stHMIInterface.xUsed := stValveConfig.xUsed;
|
||||
stHMIInterface.sName := _sName;
|
||||
|
||||
// Handle mode button feedback
|
||||
IF _xManualModeActive THEN
|
||||
stHMIInterface.stManualButton.eFeedback := E_HMI_BUTTON_FEEDBACK.ACTIVE;
|
||||
ELSE
|
||||
stHMIInterface.stManualButton.eFeedback := E_HMI_BUTTON_FEEDBACK.NONE;
|
||||
END_IF
|
||||
|
||||
IF _xAutomaticModeActive THEN
|
||||
stHMIInterface.stAutomaticButton.eFeedback := E_HMI_BUTTON_FEEDBACK.ACTIVE;
|
||||
ELSE
|
||||
stHMIInterface.stAutomaticButton.eFeedback := E_HMI_BUTTON_FEEDBACK.NONE;
|
||||
END_IF
|
||||
|
||||
// Handle open close button feedback
|
||||
IF _xIsOpen THEN
|
||||
stHMIInterface.stOpenButton.eFeedback := E_HMI_BUTTON_FEEDBACK.ACTIVE;
|
||||
ELSE
|
||||
stHMIInterface.stOpenButton.eFeedback := E_HMI_BUTTON_FEEDBACK.NONE;
|
||||
END_IF
|
||||
|
||||
IF _xIsClosed THEN
|
||||
stHMIInterface.stCloseButton.eFeedback := E_HMI_BUTTON_FEEDBACK.ACTIVE;
|
||||
ELSE
|
||||
stHMIInterface.stCloseButton.eFeedback := E_HMI_BUTTON_FEEDBACK.NONE;
|
||||
END_IF
|
||||
|
||||
// Handle release button signals
|
||||
stHMIInterface.stManualButton.xRelease := xReleaseManualMode AND (NOT _xManualModeActive);
|
||||
stHMIInterface.stAutomaticButton.xRelease := (NOT _xAutomaticModeActive);
|
||||
|
||||
stHMIInterface.stOpenButton.xRelease := _xManualModeActive AND _xProcessINTLKOk AND _xSafetyINTLKOk;
|
||||
stHMIInterface.stCloseButton.xRelease := _xManualModeActive;
|
||||
|
||||
// Handle current mode
|
||||
IF _xManualModeActive AND (NOT _xAutomaticModeActive) THEN
|
||||
stHMIInterface.iCurrentMode := E_HMI_MODE.MANUAL;
|
||||
END_IF
|
||||
|
||||
IF _xAutomaticModeActive AND (NOT _xManualModeActive) THEN
|
||||
stHMIInterface.iCurrentMode := E_HMI_MODE.AUTOMATIC;
|
||||
END_IF
|
||||
|
||||
// Handle interlock status
|
||||
stHMIInterface.stInterlock.wProcessINTLKStatus := wProcessINTLK;
|
||||
stHMIInterface.stInterlock.wProcessINTLKUsed := wProcessINTLKUsed;
|
||||
stHMIInterface.stInterlock.xProcessINTLKOk := _xProcessINTLKOk;
|
||||
|
||||
stHMIInterface.stInterlock.wSafetyINTLKStatus := wSafetyINTLK;
|
||||
stHMIInterface.stInterlock.wSafetyINTLKUsed := wSafetyINTLKUsed;
|
||||
stHMIInterface.stInterlock.xSafetyINTLKOk := _xSafetyINTLKOk;]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Property Name="IsClosed" Id="{1f4ebe6c-a98f-48b1-8a5f-f4c1debefa5c}">
|
||||
<Declaration><![CDATA[PROPERTY IsClosed : BOOL
|
||||
]]></Declaration>
|
||||
<Get Name="Get" Id="{ef140b66-3db4-4eb7-87ae-680649452cd3}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[IsClosed := _xIsClosed;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
<Property Name="IsInAutomaticMode" Id="{d767111f-e137-4db5-8520-de2e239783bd}">
|
||||
<Declaration><![CDATA[PROPERTY IsInAutomaticMode : BOOL
|
||||
]]></Declaration>
|
||||
<Get Name="Get" Id="{203d88c3-1caf-4d92-8292-06e60d21d256}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[IsInAutomaticMode := _xAutomaticModeActive AND (NOT _xManualModeActive);
|
||||
]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
<Property Name="IsInManualMode" Id="{ddd53775-56a5-419a-a26e-07865c412725}">
|
||||
<Declaration><![CDATA[PROPERTY IsInManualMode : BOOL
|
||||
]]></Declaration>
|
||||
<Get Name="Get" Id="{93872f82-0dd1-4fc7-bfb1-ae593ff57248}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[IsInManualMode := _xManualModeActive AND (NOT _xAutomaticModeActive);]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
<Property Name="IsOpen" Id="{6afdd2c7-3934-4136-a18f-ea14a935f5ef}">
|
||||
<Declaration><![CDATA[PROPERTY IsOpen : BOOL
|
||||
]]></Declaration>
|
||||
<Get Name="Get" Id="{3d3206fd-7dcd-4c1d-a91d-4513ff154aa6}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[IsOpen := _xIsOpen;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
<Property Name="Name" Id="{6475e552-32d7-4dcc-b692-9b5c114c6e55}">
|
||||
<Declaration><![CDATA[PROPERTY Name : STRING(80)]]></Declaration>
|
||||
<Get Name="Get" Id="{3c945911-435e-4362-80a0-23de08a8aa01}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[Name := _sName;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
<Set Name="Set" Id="{e21a3263-d456-45aa-b72b-78833f59308c}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[_sName := Name;
|
||||
|
||||
// Recreate alarm messages after name change
|
||||
CreateAlarmMSG();]]></ST>
|
||||
</Implementation>
|
||||
</Set>
|
||||
</Property>
|
||||
<Property Name="ProcessInterlocksOK" Id="{5304af5f-5f38-41ac-bae3-41072677ae5b}">
|
||||
<Declaration><![CDATA[PROPERTY ProcessInterlocksOK : BOOL
|
||||
]]></Declaration>
|
||||
<Get Name="Get" Id="{c7a36fe9-16d1-4e6a-840a-95721198ae41}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[ProcessInterlocksOK := _xProcessINTLKOk;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
<Method Name="ReqAutomaticMode" Id="{8d7ea6da-e5b9-4d22-89bf-8b742e336da8}">
|
||||
<Declaration><![CDATA[METHOD ReqAutomaticMode
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[_xAutomaticModeActive := TRUE;
|
||||
_xManualModeActive := FALSE;]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="ReqManualMode" Id="{3b374714-1bdd-4b5e-a971-5605e320e287}">
|
||||
<Declaration><![CDATA[METHOD ReqManualMode
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[IF xReleaseManualMode THEN
|
||||
_xManualModeActive := TRUE;
|
||||
_xAutomaticModeActive := FALSE;
|
||||
END_IF]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Property Name="SafetyInterlocksOK" Id="{cfa4b65a-d169-4f4b-ad4b-6e2d8e24ce3a}">
|
||||
<Declaration><![CDATA[{attribute 'analysis' := '-31'}
|
||||
PROPERTY SafetyInterlocksOK : BOOL]]></Declaration>
|
||||
<Get Name="Get" Id="{fa7d25b7-22e3-4e23-afcd-0ace84239f31}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[SafetyInterlocksOK := _xSafetyINTLKOk;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
</POU>
|
||||
</TcPlcObject>
|
||||
689
PLC/POUs/Components/Valves/FB_ValveAnalog.TcPOU
Normal file
689
PLC/POUs/Components/Valves/FB_ValveAnalog.TcPOU
Normal file
@@ -0,0 +1,689 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<POU Name="FB_ValveAnalog" Id="{54d19eca-c234-46d9-92a2-1587aba4973c}" SpecialFunc="None">
|
||||
<Declaration><![CDATA[{attribute 'reflection'}
|
||||
FUNCTION_BLOCK FINAL FB_ValveAnalog
|
||||
VAR_INPUT
|
||||
rSPAutomatic : REAL;
|
||||
|
||||
iFeedbackValue AT %I* : INT;
|
||||
xFeedbackUnderrange AT %I* : BOOL;
|
||||
xFeedbackOverrange AT %I* : BOOL;
|
||||
xErrorCard AT %I* : BOOL;
|
||||
|
||||
xOpenFeedback AT %I* : BOOL;
|
||||
xCloseFeedback AT %I* : BOOL;
|
||||
|
||||
// Open and close the valve
|
||||
xAutomaticOpen : BOOL;
|
||||
|
||||
// Global switch to dissable all errors
|
||||
xReleaseErrors : BOOL := TRUE;
|
||||
|
||||
// Config input
|
||||
// Valve configuration parameters
|
||||
stValveConfig : ST_ValveAnalogConfig;
|
||||
|
||||
// Release or block change to manual mode
|
||||
xReleaseManualMode : BOOL;
|
||||
|
||||
// Process interlocks
|
||||
wProcessINTLK : T_INTERLOCK;
|
||||
wProcessINTLKUsed: T_INTERLOCK;
|
||||
|
||||
// Safety interlocks
|
||||
wSafetyINTLK : T_INTERLOCK;
|
||||
|
||||
// Used safety interlocks
|
||||
wSafetyINTLKUsed: T_INTERLOCK;
|
||||
|
||||
// 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
|
||||
// Ouput setpoint
|
||||
iSetpoint AT %Q* : INT;
|
||||
|
||||
// Error in valve active
|
||||
xError : BOOL;
|
||||
END_VAR
|
||||
VAR_IN_OUT
|
||||
// HMI interface
|
||||
stHMIInterface : ST_HMI_ANALOG_VALVE_DATA;
|
||||
END_VAR
|
||||
VAR
|
||||
// Internal command for manual mode open request
|
||||
_xManualOpen : BOOL := FALSE;
|
||||
|
||||
// Manual mode active
|
||||
_xManualModeActive : BOOL := FALSE;
|
||||
|
||||
// Automatic mode active
|
||||
_xAutomaticModeActive : BOOL := TRUE;
|
||||
|
||||
// Sum of all activated interlocks
|
||||
_xProcessINTLKOk : BOOL;
|
||||
|
||||
// Sum of all activated process interlocks
|
||||
_xSafetyINTLKOk : BOOL := TRUE;
|
||||
|
||||
// Internal open state of the valve
|
||||
_xIsOpen : BOOL;
|
||||
|
||||
// Internal closed state of the valve
|
||||
_xIsClosed : BOOL;
|
||||
|
||||
// Name of valve
|
||||
// Will be set in constructor and can be changed with the name property
|
||||
_sName : STRING;
|
||||
|
||||
// Analog input
|
||||
{attribute 'hide'}
|
||||
_fbAnalogInput : FB_AnalogInput('');
|
||||
|
||||
// analog output
|
||||
{attribute 'hide'}
|
||||
_fbAnalogOutput : FB_AnalogOutput('');
|
||||
|
||||
// Internal setpoint
|
||||
_rSetpoint : REAL;
|
||||
|
||||
{attribute 'is_connected' := 'xFeedbackUnderrange'}
|
||||
_xHasUnderrangeFeedback : BOOL;
|
||||
|
||||
{attribute 'is_connected' := 'xFeedbackOverrange'}
|
||||
_xHasOverrangeFeedback : BOOL;
|
||||
|
||||
{attribute 'is_connected' := 'xErrorCard'}
|
||||
_xHasCardError : BOOL;
|
||||
|
||||
// Current valve position
|
||||
_rCurrentValvePosition : REAL;
|
||||
|
||||
// Alarm handler for valve did not open
|
||||
_fbAlarmDidNotOpen : FB_AlarmMessage(stEventEntry := TC_EVENTS.Valve.DidNotOpen, xWithConfirmation := TRUE);
|
||||
|
||||
// Alarm handler for valve did not close
|
||||
_fbAlarmDidNotClose : FB_AlarmMessage(stEventEntry := TC_EVENTS.Valve.DidNotClose, xWithConfirmation := TRUE);
|
||||
|
||||
// Alarm handler for not in range
|
||||
_fbAlarmNotInRange : FB_AlarmMessage(stEventEntry := TC_EVENTS.Valve.NotInRange, xWithConfirmation := TRUE);
|
||||
|
||||
// Analog input error
|
||||
_xAnalogInputError : BOOL;
|
||||
|
||||
// analog output error
|
||||
_xAnalogOutputError : BOOL;
|
||||
|
||||
// Analog input warning active
|
||||
_xWarningAnalogInput : BOOL;
|
||||
|
||||
// Calculated allowed window for process value
|
||||
_rPVTargetMax : REAL;
|
||||
_rPVTargetMin : REAL;
|
||||
|
||||
// Error for not beeing in range
|
||||
_xNotInRange : BOOL;
|
||||
|
||||
// Internal open command
|
||||
_xOpenValve : BOOL;
|
||||
|
||||
// Helper variables used in reset error flag
|
||||
_xAlarmsActive : BOOL;
|
||||
_xInputErrorsActive : BOOL;
|
||||
|
||||
// Internal error flags
|
||||
_xError : BOOL;
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// ===============
|
||||
// Handle not used
|
||||
// ===============
|
||||
|
||||
IF (NOT stValveConfig.xUsed) THEN
|
||||
// Clear all pending alarms if there are any
|
||||
_fbAlarmDidNotOpen(xActive := FALSE, xRelease := FALSE);
|
||||
_fbAlarmDidNotClose(xActive := FALSE, xRelease := FALSE);
|
||||
_fbAlarmNotInRange(xActive := FALSE, xRelease := FALSE);
|
||||
|
||||
_xAnalogOutputError := FALSE;
|
||||
_xAnalogInputError := FALSE;
|
||||
|
||||
_xWarningAnalogInput := FALSE;
|
||||
|
||||
_xError := FALSE;
|
||||
xError := FALSE;
|
||||
|
||||
RETURN;
|
||||
END_IF
|
||||
|
||||
|
||||
// ===========================
|
||||
// Reset safetyinterlocks flag
|
||||
// ===========================
|
||||
|
||||
IF xConfirmAlarms AND (NOT _xSafetyINTLKOk) THEN
|
||||
_xSafetyINTLKOk := TRUE;
|
||||
END_IF
|
||||
|
||||
|
||||
// =========
|
||||
// Prechecks
|
||||
// =========
|
||||
|
||||
CheckInterlocks();
|
||||
|
||||
|
||||
// =================
|
||||
// Handle HMI inputs
|
||||
// =================
|
||||
|
||||
HandleHMIInput();
|
||||
|
||||
|
||||
// ==============================
|
||||
// Check if all interlocks are ok
|
||||
// ==============================
|
||||
|
||||
// Only reset manual command if safetyinterlocks are not ok
|
||||
IF (NOT _xSafetyINTLKOk) AND _xManualOpen THEN
|
||||
// Also reset manual open command if safetyinterlocks are set
|
||||
_xManualOpen := FALSE;
|
||||
END_IF
|
||||
|
||||
|
||||
// ===================================
|
||||
// Handle opening and closing of valve
|
||||
// ===================================
|
||||
|
||||
_xOpenValve := _xProcessINTLKOk AND _xSafetyINTLKOk AND ((_xManualOpen AND _xManualModeActive AND (NOT _xAutomaticModeActive)) OR ( xAutomaticOpen AND _xAutomaticModeActive AND (NOT _xManualModeActive)));
|
||||
|
||||
IF _xOpenValve THEN
|
||||
IF _xManualModeActive AND (NOT _xAutomaticModeActive) THEN
|
||||
_rSetpoint := stHMIInterface.stSetpoint.rValue;
|
||||
ELSIF _xAutomaticModeActive AND (NOT _xManualModeActive) THEN
|
||||
_rSetpoint := rSPAutomatic;
|
||||
ELSE
|
||||
_rSetpoint := 0.0;
|
||||
END_IF
|
||||
ELSE
|
||||
IF (NOT _xProcessINTLKOk) OR (NOT _xSafetyINTLKOk) THEN
|
||||
_rSetpoint := stValveConfig.rSetpointWhenInterlocksActive;
|
||||
ELSE
|
||||
_rSetpoint := 0.0;
|
||||
END_IF
|
||||
END_IF
|
||||
|
||||
|
||||
// ====================
|
||||
// Handle analog output
|
||||
// ====================
|
||||
|
||||
_fbAnalogOutput(
|
||||
rSetpoint:= _rSetpoint,
|
||||
stAnalogIOConfig:= stValveConfig.stAnalogOutputConfig,
|
||||
xReleaseErrors:= xReleaseErrors,
|
||||
xConfirmAlarms:= xConfirmAlarms,
|
||||
xInUnitTestMode := xInUnitTestMode,
|
||||
iAnalogValue=> iSetpoint,
|
||||
xError => _xAnalogOutputError,
|
||||
stHMIInterface:= stHMIInterface.stSetpoint);
|
||||
|
||||
IF _fbAnalogOutput.xError THEN
|
||||
_xError := TRUE;
|
||||
END_IF
|
||||
|
||||
// ===================
|
||||
// Handle analog input
|
||||
// ===================
|
||||
|
||||
IF stValveConfig.xHasAnalogFeedback THEN
|
||||
stValveConfig.stAnalogInputConfig.xUsed := TRUE;
|
||||
ELSE
|
||||
stValveConfig.stAnalogInputConfig.xUsed := FALSE;
|
||||
END_IF
|
||||
|
||||
_fbAnalogInput(
|
||||
iAnalogValue:= iFeedbackValue,
|
||||
xUnderrange:= _xHasUnderrangeFeedback AND xFeedbackUnderrange,
|
||||
xOverrange:= _xHasOverrangeFeedback AND xFeedbackOverrange,
|
||||
xErrorCard:= _xHasCardError AND xErrorCard,
|
||||
stAnalogIOConfig:= stValveConfig.stAnalogInputConfig,
|
||||
stAnalogEWConfig:= stValveConfig.stAnalogInputEWConfig,
|
||||
xReleaseErrors:= xReleaseErrors,
|
||||
xReleaseLimitErrors:= FALSE,
|
||||
xReleaseHardwareErrors:= TRUE,
|
||||
xInUnitTestMode := xInUnitTestMode,
|
||||
xConfirmAlarms:= xConfirmAlarms,
|
||||
rScaledValue=> _rCurrentValvePosition,
|
||||
xError=> _xAnalogInputError,
|
||||
xWarning=> _xWarningAnalogInput,
|
||||
xErrorLow=> ,
|
||||
xWarningLow=> ,
|
||||
xWarningHigh=> ,
|
||||
xErrorHigh=> );
|
||||
|
||||
IF _fbAnalogInput.xError THEN
|
||||
_xError := TRUE;
|
||||
END_IF
|
||||
|
||||
IF NOT stValveConfig.xHasAnalogFeedback THEN
|
||||
_rCurrentValvePosition := _rSetpoint;
|
||||
END_IF
|
||||
|
||||
|
||||
// Handle open close feedback
|
||||
_xIsOpen := (stValveConfig.xHasOpenFeedback AND xOpenFeedback AND (NOT xCloseFeedback)) OR ((NOT stValveConfig.xHasOpenFeedback) AND (_rCurrentValvePosition >= stValveConfig.rPVIsOpen));
|
||||
_xIsClosed := (stValveConfig.xHasClosedFeedback AND xCloseFeedback AND (NOT xOpenFeedback)) OR ((NOT stValveConfig.xHasClosedFeedback) AND (_rCurrentValvePosition <= stValveConfig.rPVIsOpen));
|
||||
|
||||
|
||||
// Calculate target tolerance
|
||||
_rPVTargetMax := _rSetpoint + stValveConfig.rTargetTolerance;
|
||||
_rPVTargetMin := _rSetpoint - stValveConfig.rTargetTolerance;
|
||||
|
||||
// Check if valve position is in target
|
||||
_xNotInRange := stValveConfig.xHasAnalogFeedback AND ((_rCurrentValvePosition < _rPVTargetMin) OR (_rCurrentValvePosition > _rPVTargetMax));
|
||||
|
||||
// ==================
|
||||
// Not in range alarm
|
||||
// ==================
|
||||
|
||||
_fbAlarmNotInRange(
|
||||
xActive:= _xNotInRange,
|
||||
xRelease:= xReleaseErrors,
|
||||
xAcknowledge:= xConfirmAlarms,
|
||||
timOnDelay:= stValveConfig.timNotInRange,
|
||||
timOffDelay:= T#0S,
|
||||
xInUnitTestMode:= xInUnitTestMode);
|
||||
|
||||
// Latch error signal
|
||||
IF _fbAlarmNotInRange.Triggered THEN
|
||||
_xError := TRUE;
|
||||
END_IF
|
||||
|
||||
|
||||
// ===========================
|
||||
// Valve did not open in time
|
||||
// ===========================
|
||||
|
||||
_fbAlarmDidNotOpen(
|
||||
xActive:= _xOpenValve AND (NOT _xIsOpen),
|
||||
xRelease:= xReleaseErrors,
|
||||
xAcknowledge:= xConfirmAlarms,
|
||||
timOnDelay:= stValveConfig.timTimeoutOpen,
|
||||
timOffDelay:= T#0S,
|
||||
xInUnitTestMode:= xInUnitTestMode);
|
||||
|
||||
// Latch error signal
|
||||
IF _fbAlarmDidNotOpen.Triggered THEN
|
||||
_xError := TRUE;
|
||||
END_IF
|
||||
|
||||
|
||||
// ===========================
|
||||
// Valve did not close in time
|
||||
// ===========================
|
||||
|
||||
_fbAlarmDidNotClose(
|
||||
xActive:= (NOT _xOpenValve) AND (NOT _xIsClosed),
|
||||
xRelease:= xReleaseErrors,
|
||||
xAcknowledge:= xConfirmAlarms,
|
||||
timOnDelay:= stValveConfig.timTimeoutClose,
|
||||
timOffDelay:= T#0S,
|
||||
xInUnitTestMode:= xInUnitTestMode);
|
||||
|
||||
// Latch error signal
|
||||
IF _fbAlarmDidNotClose.Triggered THEN
|
||||
_xError := TRUE;
|
||||
END_IF
|
||||
|
||||
|
||||
// ================
|
||||
// Reset error flag
|
||||
// ================
|
||||
|
||||
_xAlarmsActive := _fbAlarmDidNotOpen.Active OR _fbAlarmDidNotClose.Active OR _fbAlarmNotInRange.Raised OR _xAnalogInputError OR _xAnalogOutputError;
|
||||
_xInputErrorsActive := _fbAlarmDidNotOpen.Triggered OR _fbAlarmDidNotClose.Triggered OR _fbAlarmNotInRange.Triggered;
|
||||
|
||||
IF xConfirmAlarms AND _xError AND (NOT _xAlarmsActive) AND (NOT _xInputErrorsActive) THEN
|
||||
_xError := FALSE;
|
||||
END_IF
|
||||
|
||||
|
||||
// ================================
|
||||
// Copy internal signals to outputs
|
||||
// ================================
|
||||
|
||||
xError := _xError;
|
||||
|
||||
|
||||
// ==================
|
||||
// Handle HMI outputs
|
||||
// ==================
|
||||
|
||||
HandleHMIOutput();]]></ST>
|
||||
</Implementation>
|
||||
<Method Name="CheckInterlocks" Id="{8b1816d5-ab17-471a-8a0b-10f53aacd0e5}">
|
||||
<Declaration><![CDATA[METHOD PRIVATE FINAL CheckInterlocks
|
||||
VAR
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Set interlocks ok
|
||||
_xProcessINTLKOk := TRUE;
|
||||
|
||||
// Check if all active interlocks are ok
|
||||
IF ((wProcessINTLK AND wProcessINTLKUsed) XOR wProcessINTLKUsed) > 0 THEN
|
||||
_xProcessINTLKOk := FALSE;
|
||||
END_IF
|
||||
|
||||
// Check safety interlocks
|
||||
// Safety interlocks will not automatically reset
|
||||
// They need to be reset via the xConfirmAlarms input
|
||||
IF ((wSafetyINTLK AND wSafetyINTLKUsed) XOR wSafetyINTLKUsed) > 0 THEN
|
||||
_xSafetyINTLKOk := FALSE;
|
||||
END_IF]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="CreateAlarmMSG" Id="{c81e16aa-3869-4b2a-9f6c-7c975920c18f}">
|
||||
<Declaration><![CDATA[METHOD PRIVATE CreateAlarmMSG
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[// Create did not in open alarm
|
||||
_fbAlarmDidNotOpen.Arguments.Clear().AddString(_sName);
|
||||
|
||||
// Create did not close alarm
|
||||
_fbAlarmDidNotClose.Arguments.Clear().AddString(_sName);
|
||||
|
||||
// Create did not in range alarm
|
||||
_fbAlarmNotInRange.Arguments.Clear().AddString(_sName);]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="FB_init" Id="{c1ee06ac-eaad-41e8-80a7-e09a4d61cbeb}">
|
||||
<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)
|
||||
|
||||
sName : STRING(80);
|
||||
END_VAR]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[_sName := sName;
|
||||
|
||||
// Name the analog input and output
|
||||
_fbAnalogInput.Name := CONCAT(_sName, '.AnalogInput');
|
||||
_fbAnalogOutput.Name := CONCAT(_sName, '.AnalogOutput');
|
||||
|
||||
// Create alarm messages
|
||||
CreateAlarmMSG();]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="HandleHMIInput" Id="{5eccb8ad-99f3-45d0-9d3c-03af7601217d}">
|
||||
<Declaration><![CDATA[METHOD PRIVATE HandleHMIInput
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[{warning disable C0371}
|
||||
// Handle automatic mode request
|
||||
IF stHMIInterface.stAutomaticButton.xRequest AND (NOT _xAutomaticModeActive) THEN
|
||||
_xAutomaticModeActive := TRUE;
|
||||
_xManualModeActive := FALSE;
|
||||
END_IF
|
||||
|
||||
IF stHMIInterface.stAutomaticButton.xRequest THEN
|
||||
stHMIInterface.stAutomaticButton.xRequest := FALSE;
|
||||
END_IF
|
||||
|
||||
// Handle manual mode request
|
||||
IF stHMIInterface.stManualButton.xRequest AND (NOT _xManualModeActive) AND xReleaseManualMode THEN
|
||||
_xAutomaticModeActive := FALSE;
|
||||
_xManualModeActive := TRUE;
|
||||
|
||||
// Copy last requested valve state into manual
|
||||
_xManualOpen := xAutomaticOpen;
|
||||
stHMIInterface.stSetpoint.rValue := rSPAutomatic;
|
||||
END_IF
|
||||
|
||||
IF stHMIInterface.stManualButton.xRequest THEN
|
||||
stHMIInterface.stManualButton.xRequest := FALSE;
|
||||
END_IF
|
||||
|
||||
// Handle open request
|
||||
IF stHMIInterface.stOpenButton.xRequest AND _xManualModeActive AND _xProcessINTLKOk AND _xSafetyINTLKOk THEN
|
||||
_xManualOpen := TRUE;
|
||||
END_IF
|
||||
|
||||
IF stHMIInterface.stOpenButton.xRequest THEN
|
||||
stHMIInterface.stOpenButton.xRequest := FALSE;
|
||||
END_IF
|
||||
|
||||
// Handle close request
|
||||
IF stHMIInterface.stCloseButton.xRequest AND _xManualModeActive THEN
|
||||
_xManualOpen := FALSE;
|
||||
END_IF
|
||||
|
||||
IF stHMIInterface.stCloseButton.xRequest THEN
|
||||
stHMIInterface.stCloseButton.xRequest := FALSE;
|
||||
END_IF]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="HandleHMIOutput" Id="{78e41bf5-d7d4-4955-92e5-e51e67c4444d}">
|
||||
<Declaration><![CDATA[METHOD PRIVATE HandleHMIOutput : BOOL
|
||||
VAR_INPUT
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[{warning disable C0371}
|
||||
// Handle open closed feedbacks
|
||||
IF (NOT _xIsOpen) AND (NOT _xIsClosed) AND (NOT _xError) THEN
|
||||
stHMIInterface.iStatus := E_HMI_VALVE_STATUS.TRANSITIONING;
|
||||
END_IF
|
||||
|
||||
IF _xIsOpen AND (NOT _xIsClosed) AND (NOT _xError) THEN
|
||||
stHMIInterface.iStatus := E_HMI_VALVE_STATUS.OPENED;
|
||||
END_IF
|
||||
|
||||
IF _xIsClosed AND (NOT _xIsOpen) AND (NOT _xError) THEN
|
||||
stHMIInterface.iStatus := E_HMI_VALVE_STATUS.CLOSED;
|
||||
END_IF
|
||||
|
||||
IF _xError THEN
|
||||
stHMIInterface.iStatus := E_HMI_VALVE_STATUS.ERROR;
|
||||
END_IF
|
||||
|
||||
// Copy analog in_out data
|
||||
stHMIInterface.stProcessValue.sName := 'Actual position';
|
||||
stHMIInterface.stProcessValue.rValue := _rCurrentValvePosition;
|
||||
|
||||
stHMIInterface.stSetpoint.sName := 'Target position';
|
||||
stHMIInterface.stSetpoint.rMin := stHMIInterface.stProcessValue.rMin;
|
||||
stHMIInterface.stSetpoint.rMax := stHMIInterface.stProcessValue.rMax;
|
||||
stHMIInterface.stSetpoint.sUnit := stHMIInterface.stProcessValue.sUnit;
|
||||
|
||||
// Copy config data to hmi interface
|
||||
stHMIInterface.xUsed := stValveConfig.xUsed;
|
||||
stHMIInterface.sName := _sName;
|
||||
|
||||
// Handle mode button feedback
|
||||
IF _xManualModeActive THEN
|
||||
stHMIInterface.stManualButton.eFeedback := E_HMI_BUTTON_FEEDBACK.ACTIVE;
|
||||
ELSE
|
||||
stHMIInterface.stManualButton.eFeedback := E_HMI_BUTTON_FEEDBACK.NONE;
|
||||
END_IF
|
||||
|
||||
IF _xAutomaticModeActive THEN
|
||||
stHMIInterface.stAutomaticButton.eFeedback := E_HMI_BUTTON_FEEDBACK.ACTIVE;
|
||||
ELSE
|
||||
stHMIInterface.stAutomaticButton.eFeedback := E_HMI_BUTTON_FEEDBACK.NONE;
|
||||
END_IF
|
||||
|
||||
// Handle open close button feedback
|
||||
IF _xIsOpen THEN
|
||||
stHMIInterface.stOpenButton.eFeedback := E_HMI_BUTTON_FEEDBACK.ACTIVE;
|
||||
ELSE
|
||||
stHMIInterface.stOpenButton.eFeedback := E_HMI_BUTTON_FEEDBACK.NONE;
|
||||
END_IF
|
||||
|
||||
IF _xIsClosed THEN
|
||||
stHMIInterface.stCloseButton.eFeedback := E_HMI_BUTTON_FEEDBACK.ACTIVE;
|
||||
ELSE
|
||||
stHMIInterface.stCloseButton.eFeedback := E_HMI_BUTTON_FEEDBACK.NONE;
|
||||
END_IF
|
||||
|
||||
// Handle release button signals
|
||||
stHMIInterface.stManualButton.xRelease := xReleaseManualMode AND (NOT _xManualModeActive);
|
||||
stHMIInterface.stAutomaticButton.xRelease := (NOT _xAutomaticModeActive);
|
||||
|
||||
stHMIInterface.stOpenButton.xRelease := _xManualModeActive AND _xProcessINTLKOk AND _xSafetyINTLKOk;
|
||||
stHMIInterface.stCloseButton.xRelease := _xManualModeActive;
|
||||
|
||||
// Handle current mode
|
||||
IF _xManualModeActive AND (NOT _xAutomaticModeActive) THEN
|
||||
stHMIInterface.iCurrentMode := E_HMI_MODE.MANUAL;
|
||||
END_IF
|
||||
|
||||
IF _xAutomaticModeActive AND (NOT _xManualModeActive) THEN
|
||||
stHMIInterface.iCurrentMode := E_HMI_MODE.AUTOMATIC;
|
||||
END_IF
|
||||
|
||||
// Handle interlock status
|
||||
stHMIInterface.stInterlock.wProcessINTLKStatus := wProcessINTLK;
|
||||
stHMIInterface.stInterlock.wProcessINTLKUsed := wProcessINTLKUsed;
|
||||
stHMIInterface.stInterlock.xProcessINTLKOk := _xProcessINTLKOk;
|
||||
|
||||
stHMIInterface.stInterlock.wSafetyINTLKStatus := wSafetyINTLK;
|
||||
stHMIInterface.stInterlock.wSafetyINTLKUsed := wSafetyINTLKUsed;
|
||||
stHMIInterface.stInterlock.xSafetyINTLKOk := _xSafetyINTLKOk;]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Property Name="IsClosed" Id="{b6c1710c-9aab-4569-b47e-788596401de5}">
|
||||
<Declaration><![CDATA[PROPERTY IsClosed : BOOL
|
||||
]]></Declaration>
|
||||
<Get Name="Get" Id="{6a0b898d-b4dd-42f2-8af5-0cbc0b739a53}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[IsClosed := _xIsClosed;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
<Property Name="IsInAutomaticMode" Id="{c23f1e57-d41d-447f-ba1b-ef6a2091e1ee}">
|
||||
<Declaration><![CDATA[PROPERTY IsInAutomaticMode : BOOL
|
||||
]]></Declaration>
|
||||
<Get Name="Get" Id="{7da816e7-e04c-4f70-b8a6-974fe4187b1c}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[IsInAutomaticMode := _xAutomaticModeActive AND (NOT _xManualModeActive);
|
||||
]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
<Property Name="IsInManualMode" Id="{cb02ea4c-34fb-4c1c-bc05-be290f13e9cc}">
|
||||
<Declaration><![CDATA[PROPERTY IsInManualMode : BOOL
|
||||
]]></Declaration>
|
||||
<Get Name="Get" Id="{b9145693-63b3-4bde-b741-a96047fb952a}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[IsInManualMode := _xManualModeActive AND (NOT _xAutomaticModeActive);]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
<Property Name="IsOpen" Id="{14c8ecb1-93c0-4640-a72a-37068aa931c0}">
|
||||
<Declaration><![CDATA[PROPERTY IsOpen : BOOL
|
||||
]]></Declaration>
|
||||
<Get Name="Get" Id="{9f1a9fc3-9760-4f2d-977c-2b77a4848604}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[IsOpen := _xIsOpen;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
<Property Name="Name" Id="{a9acd029-3ab7-4f0b-866d-4e5e120b76d7}">
|
||||
<Declaration><![CDATA[PROPERTY Name : STRING(80)]]></Declaration>
|
||||
<Get Name="Get" Id="{2a298056-2f0c-40dd-93f1-0193ef39b177}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[Name := _sName;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
<Set Name="Set" Id="{4439378f-18e8-4038-8e1b-e9c4c0e99771}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[_sName := Name;
|
||||
|
||||
// Rename the analog input and output
|
||||
_fbAnalogInput.Name := CONCAT(_sName, '.AnalogInput');
|
||||
_fbAnalogOutput.Name := CONCAT(_sName, '.AnalogOutput');
|
||||
|
||||
// Recreate alarm messages after name change
|
||||
CreateAlarmMSG();]]></ST>
|
||||
</Implementation>
|
||||
</Set>
|
||||
</Property>
|
||||
<Property Name="ProcessInterlocksOK" Id="{6eca8eb7-6785-41bf-a07d-24fa126ee630}">
|
||||
<Declaration><![CDATA[PROPERTY ProcessInterlocksOK : BOOL
|
||||
]]></Declaration>
|
||||
<Get Name="Get" Id="{063a0fc0-f2e2-4438-82b9-93ba2a524eb0}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[ProcessInterlocksOK := _xProcessINTLKOk;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
<Method Name="ReqAutomaticMode" Id="{dc5b5371-d320-47c3-9450-5d2ea8274952}">
|
||||
<Declaration><![CDATA[METHOD ReqAutomaticMode
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[_xAutomaticModeActive := TRUE;
|
||||
_xManualModeActive := FALSE;]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Method Name="ReqManualMode" Id="{e9adf596-9367-4445-83ca-794c5fdbc5db}">
|
||||
<Declaration><![CDATA[METHOD ReqManualMode
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[IF xReleaseManualMode THEN
|
||||
_xManualModeActive := TRUE;
|
||||
_xAutomaticModeActive := FALSE;
|
||||
END_IF]]></ST>
|
||||
</Implementation>
|
||||
</Method>
|
||||
<Property Name="SafetyInterlocksOK" Id="{4a127995-0516-47b5-bd54-a8856404b497}">
|
||||
<Declaration><![CDATA[{attribute 'analysis' := '-31'}
|
||||
PROPERTY SafetyInterlocksOK : BOOL]]></Declaration>
|
||||
<Get Name="Get" Id="{74eb6ffc-1090-4dcc-bb8f-03a5108315f7}">
|
||||
<Declaration><![CDATA[VAR
|
||||
END_VAR
|
||||
]]></Declaration>
|
||||
<Implementation>
|
||||
<ST><![CDATA[SafetyInterlocksOK := _xSafetyINTLKOk;]]></ST>
|
||||
</Implementation>
|
||||
</Get>
|
||||
</Property>
|
||||
</POU>
|
||||
</TcPlcObject>
|
||||
60
PLC/POUs/Components/Valves/Types/ST_ValveAnalogConfig.TcDUT
Normal file
60
PLC/POUs/Components/Valves/Types/ST_ValveAnalogConfig.TcDUT
Normal file
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<DUT Name="ST_ValveAnalogConfig" Id="{8ae10abc-4856-40f8-b7e0-08933552acd7}">
|
||||
<Declaration><![CDATA[TYPE ST_ValveAnalogConfig :
|
||||
STRUCT
|
||||
// Analog value when valve is considered open
|
||||
// defaults to >=5%
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
rPVIsOpen : REAL := 5.0;
|
||||
|
||||
// Maximum allowable difference between setpoint and process value
|
||||
// Defaults to +-5
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
rTargetTolerance : REAL := 5.0;
|
||||
|
||||
// Time for the valve to get to the requested setpoint
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
timNotInRange : TIME := T#30S;
|
||||
|
||||
// Config parameters for the analog input
|
||||
stAnalogInputConfig : ST_ANALOG_IO_CONFIG := (iAIMax := 32767, iAIMin := 0, rPVMax := 100, rPVMin := 0);
|
||||
stAnalogInputEWConfig : ST_ANALOG_EW_CONFIG;
|
||||
|
||||
// Config parameters for the analog output
|
||||
stAnalogOutputConfig : ST_ANALOG_IO_CONFIG := (iAIMax := 32767, iAIMin := 0, rPVMax := 100, rPVMin := 0);
|
||||
|
||||
// Timeout for the valve to open
|
||||
// 0 = deactivated
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
timTimeoutOpen : TIME := T#0S;
|
||||
|
||||
// Timeout for the valve to close
|
||||
// 0 = deactivated
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
timTimeoutClose : TIME := T#0S;
|
||||
|
||||
// Valve has open feedback signal
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
xHasOpenFeedback : BOOL;
|
||||
|
||||
// Valve has close feedback signal
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
xHasClosedFeedback : BOOL;
|
||||
|
||||
// Valve has analog feedback signal
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
xHasAnalogFeedback : BOOL;
|
||||
|
||||
// Set setpoint to use if interlocks are active
|
||||
// defaults to 0
|
||||
rSetpointWhenInterlocksActive : REAL := 0;
|
||||
|
||||
// Valve is used
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
xUsed : BOOL := TRUE;
|
||||
END_STRUCT
|
||||
END_TYPE
|
||||
]]></Declaration>
|
||||
</DUT>
|
||||
</TcPlcObject>
|
||||
35
PLC/POUs/Components/Valves/Types/ST_ValveConfig.TcDUT
Normal file
35
PLC/POUs/Components/Valves/Types/ST_ValveConfig.TcDUT
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TcPlcObject Version="1.1.0.1">
|
||||
<DUT Name="ST_ValveConfig" Id="{cfeab4f5-40b4-416d-92f9-378624bedcc4}">
|
||||
<Declaration><![CDATA[TYPE ST_ValveConfig :
|
||||
STRUCT
|
||||
// Timeout for the valve to open
|
||||
// 0 = deactivated
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
timTimeoutOpen : TIME := T#0S;
|
||||
|
||||
// Timeout for the valve to close
|
||||
// 0 = deactivated
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
timTimeoutClose : TIME := T#0S;
|
||||
|
||||
// Valve has open feedback signal
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
xHasOpenFeedback : BOOL;
|
||||
|
||||
// Valve has close feedback signal
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
xHasClosedFeedback : BOOL;
|
||||
|
||||
// Set to TRUE if valve should be open instead
|
||||
// of closed with activated interlocks
|
||||
xOpenWhenInterlocksActive : BOOL := FALSE;
|
||||
|
||||
// Valve is used
|
||||
{attribute 'OPC.UA.DA' := '1'}
|
||||
xUsed : BOOL := TRUE;
|
||||
END_STRUCT
|
||||
END_TYPE
|
||||
]]></Declaration>
|
||||
</DUT>
|
||||
</TcPlcObject>
|
||||
Reference in New Issue
Block a user