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();]]> 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]]>