); // Set error active if fb has error IF _fbPosolytPumpInlet.xError THEN _xErrorActive := TRUE; END_IF // Set warning if fb has warning IF _fbPosolytPumpInlet.xWarning THEN _xWarningActive := TRUE; END_IF // Set safety interlock flag if fb has safety interlocks active IF NOT stHMIInterface.stPosolytPump.stInterlock.xSafetyINTLKOk THEN xSafetyIntlksOk := FALSE; END_IF // =============================== // Pump negolyt segment inlet // =============================== // Safety Interlocks stHMIInterface.stNegolytPump.stInterlock.asSafetyINTLKName[0] := 'Emergency stop ok'; _stNegolytPumpInletSIntlk.0 := xEmergencyStopOk; // Process interlocks stHMIInterface.stNegolytPump.stInterlock.asProcessINTLKName[0] := 'At least one valve is open'; _stNegolytPumpInletPIntlk.0 := _fbNegolytValveTankOutlet.IsOpen; // Valve fb _fbNegolytPumpInlet( xReleaseManualMode:= _xReleaseManualMode, wProcessINTLK:= _stNegolytPumpInletPIntlk, wProcessINTLKUsed:= _stNegolytPumpInletPIntlkUsed, wSafetyINTLK:= _stNegolytPumpInletSIntlk, wSafetyINTLKUsed:= _stNegolytPumpInletSIntlkUsed, xReleaseErrors:= xReleaseErrors, xConfirmAlarms:= xConfirmAlarms, rSPautomatic:= rSetpointNegolytPumpInlet, xReleaseAnalogInLimitErrors:= xReleaseLimitErrors, stMotorAnalogConfig:= stUnitConfig.stConfigNegolytPump, stHMIInterface:= stHMIInterface.stNegolytPump, xWarning=> ); // Set error active if fb has error IF _fbNegolytPumpInlet.xError THEN _xErrorActive := TRUE; END_IF // Set warning if fb has warning IF _fbNegolytPumpInlet.xWarning THEN _xWarningActive := TRUE; END_IF // Set safety interlock flag if fb has safety interlocks active IF NOT stHMIInterface.stNegolytPump.stInterlock.xSafetyINTLKOk THEN xSafetyIntlksOk := FALSE; END_IF // =============================== // Pressure sensor posolyt segment inlet // =============================== _fbPressurePosolytSegmentInlet( stScalingConfig:= stUnitConfig.stConfigPosolytPressureSegmentInlet, stEWConfig:= stUnitConfig.stEWLPosolytPressureSegmentInlet, stEWDelayConfig:= stUnitConfig.stEWDPosolytPressureSegmentInlet, xReleaseErrors:= xReleaseErrors, xReleaseLimitErrors:= xReleaseLimitErrors AND _fbPosolytPumpInlet.IsRunning AND _fbPosolytPumpInlet.xInTarget, xReleaseHardwareErrors:= xReleaseErrors, xConfirmAlarms:= xConfirmAlarms, stHMIInterface => stHMIInterface.stPosolytPressureSegmentInlet); // Set error active if fb has error IF _fbPressurePosolytSegmentInlet.xError THEN _xErrorActive := TRUE; END_IF // Set warning if fb has warning IF _fbPressurePosolytSegmentInlet.xWarning THEN _xWarningActive := TRUE; END_IF // =============================== // Pressure sensors negolyt segment inlet // =============================== _fbPressureNegolytSegmentInlet( stScalingConfig:= stUnitConfig.stConfigNegolytPressureSegmentInlet, stEWConfig:= stUnitConfig.stEWLNegolytPressureSegmentInlet, stEWDelayConfig:= stUnitConfig.stEWDNegolytPressureSegmentInlet, xReleaseErrors:= xReleaseErrors, xReleaseLimitErrors:= xReleaseLimitErrors AND _fbNegolytPumpInlet.IsRunning AND _fbNegolytPumpInlet.xInTarget, xReleaseHardwareErrors:= xReleaseErrors, xConfirmAlarms:= xConfirmAlarms, stHMIInterface => stHMIInterface.stNegolytPressureSegmentInlet); // Set error active if fb has error IF _fbPressureNegolytSegmentInlet.xError THEN _xErrorActive := TRUE; END_IF // Set warning if fb has warning IF _fbPressureNegolytSegmentInlet.xWarning THEN _xWarningActive := TRUE; END_IF // =============================== // Pressure sensors posolyt tank inlet // =============================== _fbPressurePosolytTankInlet( stScalingConfig:= stUnitConfig.stConfigPosolytPressureTankInlet, stEWConfig:= stUnitConfig.stEWLPosolytPressureTankInlet, stEWDelayConfig:= stUnitConfig.stEWDPosolytPressureTankInlet, xReleaseErrors:= xReleaseErrors, xReleaseLimitErrors:= xReleaseLimitErrors AND _fbPosolytPumpInlet.IsRunning AND _fbPosolytPumpInlet.xInTarget, xReleaseHardwareErrors:= xReleaseErrors, xConfirmAlarms:= xConfirmAlarms, stHMIInterface => stHMIInterface.stPosolytPressureTankInlet); // Set error active if fb has error IF _fbPressurePosolytTankInlet.xError THEN _xErrorActive := TRUE; END_IF // Set warning if fb has warning IF _fbPressurePosolytTankInlet.xWarning THEN _xWarningActive := TRUE; END_IF // =============================== // Pressure sensors negolyt tank inlet // =============================== _fbPressureNegolytTankInlet( stScalingConfig:= stUnitConfig.stConfigNegolytPressureTankInlet, stEWConfig:= stUnitConfig.stEWLNegolytPressureTankInlet, stEWDelayConfig:= stUnitConfig.stEWDNegolytPressureTankInlet, xReleaseErrors:= xReleaseErrors, xReleaseLimitErrors:= xReleaseLimitErrors AND _fbNegolytPumpInlet.IsRunning AND _fbNegolytPumpInlet.xInTarget, xReleaseHardwareErrors:= xReleaseErrors, xConfirmAlarms:= xConfirmAlarms, stHMIInterface => stHMIInterface.stNegolytPressureTankInlet); // Set error active if fb has error IF _fbPressureNegolytTankInlet.xError THEN _xErrorActive := TRUE; END_IF // Set warning if fb has warning IF _fbPressureNegolytTankInlet.xWarning THEN _xWarningActive := TRUE; END_IF // =============================== // Temperature sensor posolyt tank inlet // =============================== _fbTempSensorPosolyt( stScalingConfig:= stUnitConfig.stConfigPosolytTempTankInlet, stEWConfig:= GVL_CONFIG.stUnitConfig.stEWLPosolytTempTankInlet, stEWDelayConfig:= GVL_CONFIG.stUnitConfig.stEWDPosolytTempTankInlet, xReleaseErrors:= xReleaseErrors, xReleaseLimitErrors:= xReleaseLimitErrors, xReleaseHardwareErrors:= xReleaseErrors, xConfirmAlarms:= xConfirmAlarms, stHMIInterface=> stHMIInterface.stPosolytTempTankInlet); IF _fbTempSensorPosolyt.xError THEN _xErrorActive := TRUE; END_IF IF _fbTempSensorPosolyt.xWarning THEN _xWarningActive := TRUE; END_IF // =============================== // Temperature sensor negolyt tank inlet // =============================== _fbTempSensorNegolyt( stScalingConfig:= stUnitConfig.stConfigNegolytTempTankInlet, stEWConfig:= GVL_CONFIG.stUnitConfig.stEWLNegolytTempTankInlet, stEWDelayConfig:= GVL_CONFIG.stUnitConfig.stEWDNegolytTempTankInlet, xReleaseErrors:= xReleaseErrors, xReleaseLimitErrors:= xReleaseLimitErrors, xReleaseHardwareErrors:= xReleaseErrors, xConfirmAlarms:= xConfirmAlarms, stHMIInterface=> stHMIInterface.stNegolytTempTankInlet); IF _fbTempSensorNegolyt.xError THEN _xErrorActive := TRUE; END_IF IF _fbTempSensorNegolyt.xWarning THEN _xWarningActive := TRUE; END_IF // =============================== // Voltage segment // =============================== _fbVoltageSegment( stScalingConfig:= GVL_CONFIG.stUnitConfig.stConfigVoltageSegment, stEWConfig:= GVL_CONFIG.stUnitConfig.stEWLVoltageSegment, stEWDelayConfig:= GVL_CONFIG.stUnitConfig.stEWDVoltageSegment, xReleaseErrors:= xReleaseErrors, xReleaseLimitErrors:= xReleaseLimitErrors AND _xEnableVoltageLimitChecks, xReleaseHardwareErrors:= xReleaseErrors, xConfirmAlarms:= xConfirmAlarms, stHMIInterface=> stHMIInterface.stVoltageSegment, rScaledValue => rCurrentVoltage); // Set error active if fb has error IF _fbVoltageSegment.xError THEN _xErrorActive := TRUE; END_IF // Set warning if fb has warning IF _fbVoltageSegment.xWarning THEN _xWarningActive := TRUE; END_IF // =============================== // Check if all components are in automatic // =============================== _xAllComponentsInAutomatic := _fbPosolytValveTankOutlet.IsInAutomaticMode AND _fbNegolytValveTankOutlet.IsInAutomaticMode AND _fbPosolytPumpInlet.IsInAutomaticMode AND _fbNegolytPumpInlet.IsInAutomaticMode; // Raise warning IF NOT _fbNotAllAutomaticAlarm.bRaised AND (NOT _xAllComponentsInAutomatic) THEN _fbNotAllAutomaticAlarm.Raise(0); END_IF // Clear warning and reset IF _fbNotAllAutomaticAlarm.bRaised AND _xAllComponentsInAutomatic THEN _fbNotAllAutomaticAlarm.Clear(0, TRUE); END_IF // Calculate shutdown discharge threshold _rShutdownDischargeVoltageThreshold := GVL_CONFIG.rMinimumUnitVoltage + GVL_CONFIG.rDeltaUnitVoltageShutdownDischarge; // =============================== // Run state machine for startup and shutdown // =============================== CASE _iState OF 0: // Off IF xEnable AND _xAllComponentsInAutomatic AND (NOT _xErrorActive) THEN _xReleaseManualMode := FALSE; _iState := 10; END_IF 10: // Open all valves _fbPosolytValveTankOutlet.ReqAutomaticOpen(); _fbNegolytValveTankOutlet.ReqAutomaticOpen(); xOff := FALSE; _iState := 15; 15: // Wait for all valves to be open IF _fbPosolytValveTankOutlet.IsOpen AND _fbNegolytValveTankOutlet.IsOpen THEN IF (NOT _fbPosolytValveTankOutlet.xError) AND (NOT _fbNegolytValveTankOutlet.xError) THEN _iState := 20; END_IF END_IF // If enable signal is lost, or there is an error, goto shutdown IF (NOT xEnable) OR _xErrorActive THEN _xReleaseManualMode := TRUE; _iState := 1000; END_IF 20: // Start pumps _fbPosolytPumpInlet.ReqAutomaticStart(); _fbNegolytPumpInlet.ReqAutomaticStart(); _iState := 25; 25: // Wait for all pumps to run IF _fbPosolytPumpInlet.xInTarget AND _fbNegolytPumpInlet.xInTarget THEN _iState := 30; END_IF // If enable signal is lost, goto shutdown IF (NOT xEnable) OR _xErrorActive THEN _iState := 40; END_IF 30: // Wait some time _tonStartupCheck(In := TRUE, PT := GVL_CONFIG.timUnitStartupTime); // After some time, check if all values are ok IF _tonStartupCheck.Q THEN _tonStartupCheck(In := FALSE); // Check for minimum unit voltage IF (_fbVoltageSegment.rScaledValue >= GVL_CONFIG.rMinimumUnitVoltage) AND NOT _xErrorActive AND NOT _xWarningActive THEN xReady := TRUE; _xEnableVoltageLimitChecks := TRUE; _iState := 35; ELSE _iState := 40; END_IF END_IF // If enable signal is lost, goto shutdown IF (NOT xEnable) OR _xErrorActive THEN _iState := 40; END_IF 35: // Unit in enabled state IF (NOT xEnable) AND NOT _xErrorActive THEN _iState := 40; END_IF // Goto error shutdown if an error occured IF _xErrorActive THEN _iState := 1000; END_IF 40: // Close all valves _fbNegolytValveTankOutlet.ReqAutomaticClose(); _fbPosolytValveTankOutlet.ReqAutomaticClose(); _iState := 45; 45: // Wait for valves to be closed IF _fbNegolytValveTankOutlet.IsClosed AND _fbPosolytValveTankOutlet.IsClosed THEN xInShutdownDischargeMode := TRUE; _iState := 50; END_IF // When there is an error trying to close the valves, // dont try to discharge the segment IF _fbNegolytValveTankOutlet.xError OR _fbPosolytValveTankOutlet.xError THEN _xEnableVoltageLimitChecks := FALSE; _iState := 60; END_IF // Check for restart condition IF xEnable AND (NOT _xErrorActive) THEN _iState := 0; END_IF 50: // Wait for unit voltage to drop below a certain threshold IF (_fbVoltageSegment.rScaledValue > _rShutdownDischargeVoltageThreshold) THEN xShutdownDischargeAllowed := TRUE; ELSE xShutdownDischargeAllowed := FALSE; _xEnableVoltageLimitChecks := FALSE; END_IF IF (_fbVoltageSegment.rScaledValue <= GVL_CONFIG.rPumpshutoffThreshold) THEN xShutdownDischargeAllowed := FALSE; xInShutdownDischargeMode := FALSE; _iState := 60; END_IF // Check for restart condition IF xEnable AND (NOT _xErrorActive) THEN xShutdownDischargeAllowed := FALSE; xInShutdownDischargeMode := FALSE; _iState := 0; END_IF 60: // Disable pumps _fbPosolytPumpInlet.ReqAutomaticStop(); _fbNegolytPumpInlet.ReqAutomaticStop(); _iState := 65; 65: // Wait for pumps to be stopped IF _fbPosolytPumpInlet.IsStopped AND _fbNegolytPumpInlet.IsStopped THEN xOff := TRUE; _xReleaseManualMode := TRUE; IF NOT _xErrorActive THEN _iState := 1000; END_IF END_IF // Check for restart condition IF xEnable AND (NOT _xErrorActive) THEN _iState := 0; END_IF // Check for error IF _xErrorActive THEN _iState := 1000; END_IF 1000: // Error shutdown _fbNegolytValveTankOutlet.ReqAutomaticClose(); _fbPosolytValveTankOutlet.ReqAutomaticClose(); _fbPosolytPumpInlet.ReqAutomaticStop(); _fbNegolytPumpInlet.ReqAutomaticStop(); _xEnableVoltageLimitChecks := FALSE; xShutdownDischargeAllowed := FALSE; xInShutdownDischargeMode := FALSE; xReady := FALSE; xOff := TRUE; _iState := 1001; 1001: // Alarm active // Only allow reset when enable is deactivated to avoid an // automatic restart of the unit IF (NOT _xErrorActive) AND (NOT xEnable) THEN _iState := 0; END_IF END_CASE // =============================== // Output error and warning flags // =============================== xError := _xErrorActive; xWarning := _xWarningActive;]]>