
使用举例。如果只是最普通的电磁阀(线圈得电到工作位,断电回原点)怎么使用?
setOutputWorkContinous 设为true

goToWorkposition 绑定输出,goToHomeposition悬空即可。

=====================================
简介:
使用两个或一个控制命令控制两种状态(例如阀门的位置)之间的执行器。适用于双稳态设备。

Input参数
Identifier | Data Type | DefaultValue | Description |
|---|---|---|---|
enable | Bool | FALSE | TRUE:Enable functionalityofFB |
commandHomePos | Bool | FALSE | Risingedge:Moveactuatortohomeposition |
commandWorkPos | Bool | FALSE | Risingedge:Move actuatortoworkposition |
feedbackHomePos | Bool | FALSE | TRUE:Feedbackactuatorisinhomeposition |
feedbackWorkPos | Bool | FALSE | TRUE:Feedbackactuatorisinwork position |
acknowledge | Bool | FALSE | Acknowledgementofthe alarms |
Identifier | Data Type | Description |
|---|---|---|
valid | Bool | TRUE:Valid setofoutput values availableattheFB |
busy | Bool | TRUE:FBisnotfinishedandnewoutput valuescanbeexpected |
error | Bool | FALSE:NoerrorTRUE:AnerroroccurredduringtheexecutionoftheFB |
status | Word | 16#0000-16#7FFF:Status oftheFB16#8000-16#FFFF:Error identification(seefollowingTable) |
goToHomePos | Bool | TRUE:Controloutput tomovetoactuatortohomeposition |
|---|---|---|
goToWorkPos | Bool | TRUE:Controloutput tomovetoactuatortoworkposition |
inHomePos | Bool | TRUE:Actuatorisinhomeposition |
inWorkPos | Bool | TRUE:Actuatorisinwork position |
diagnostics | LBC_typeDiagnostics | Modulerelateddiagnosticinformation |

Identifier | Data Type | Description |
|---|---|---|
configuration | LBC_typeTwoWayActuatorConfiguration | Modulerelatedconfigurationparameters |
moduleInterface | LBC_typeTwoWayActuatorInterface | Moduleinterfaceforexternalsystems |
状态和错误代码
代码/值 | 标识符/描述 |
|---|---|
16#0000 | STATUS_NO_ERROR_OCCURRED状态:执行期间未发生错误 |
16#7000 | STATUS_NO_CALL状态:当前未处理任何作业 |
16#7001 | STATUS_FIRST_CALL状态:传入新作业后的第一个呼叫(上升沿“启用”) |
16#7002 | STATUS_SUBSEQUENT_CALL状态:在活动处理期间进行后续调用,没有更多详细信息 |
16#7003 | STATUS_POSITION_NOT_DEFINED状态:执行器位置不确定 |
16#7004 | STATUS_IN_HOME_POSITION状态:执行器处于原位 |
16#7005 | STATUS_MOVE_TO_WORK_POSITION状态:执行器正在向工作位置移动 |
16#7006 | STATUS_IN_WORK_POSITION状态:执行器处于工作位置 |
16#7007 | STATUS_MOVE_TO_HOME_POSITION状态:执行器正在向原位移动 |
16#8201 | ERR_CONFIGURATION_LEAVE_FEEDBACK_TIME_NEGATIVE错误:离开位置反馈时间的负值 |
16#8202 | ERR_CONFIGURATION_REACH_FEEDBACK_TIME_NEGATIVE错误:达到位置反馈时间的负值 |
16#8400 | ERR_MORE_THAN_ONE_CMD_PRESENT_AT_SAME_TIME错误:同时显示家庭和工作位置的命令 |
16#8401 | ERR_MORE_THAN_ONE_FEEDBACK_PRESENT_AT_SAME_TIME错误:中立和工作职位的反馈同时存在 |
16#8402 | ERR_TIMEOUT_HOME_POSITION错误:监控超时,缺少反馈到主位置 |
16#8403 | ERR_TIMEOUT_WORK_POSITION错误:监控超时,错过反馈工作位置 |
16#8404 | ERR_INCORRECT_FEEDBACK_WORK_POSITION错误:未预料到反馈工作位置的外观 |
代码/值 | 标识符/描述 |
|---|---|
16#8405 | ERR_INCORRECT_FEEDBACK_HOME_POSITION错误:未预料到反馈原点位置的外观 |
16#8406 | ERR_MISSING_FEEDBACK_WORK_POSITION错误:缺少反馈工作位置 |
16#8407 | ERR_MISSING_FEEDBACK_HOME_POSITION错误:缺少反馈主页位置 |
16#8408 | ERR_NOT_LEAVING_HOME_POSITION错误:未离开主位置 |
16#8409 | ERR_NOT_LEAVING_WORK_POSITION错误:未离开工作位置 |
16#8600 | ERR_UNDEFINED_STATE错误:由于状态机中未定义状态 |
模块相关诊断信息
Identifier | Data Type | DefaultValue | Description |
|---|---|---|---|
status | Word | 16#0000 | 16#0000-16#7FFF: Status of the FB16#8000-16#FFFF:Error identification |
subfunctionStatus | Word | 16#0000 | Statusorreturnvalue ofcalledFB's, FCs,systemblocksor otherstatus information |
stateNumber | DInt | 0 | Stateinthestate machineoftheblockwhere theerroroccurred |
模块相关配置参数
标识符 | 数据类型 | 默认值 | 描述 |
|---|---|---|---|
referenceDesignator | String[20] | 'TwoWayAct.' | 设备名称或设备ID |
monitoringLeavingFeedback | 时间 | T#5s | 离开“运动开始”位置的控制时间 |
monitoringReachingFeedback | Time | T#5s | Control time for reaching the "end ofmovement"position |
setOutputHomeContinuously | Bool | TRUE | TRUE: Output home is set as long ascommand home is present. FALSE: Outputhas just an impulse as long as the actuatorhasnotreachedthepositionandismoving |
setOutputWorkContinuously | Bool | TRUE | TRUE: Output work is set as long ascommand work is present. FALSE: Outputhasjust impulseaslong astheactuatorhasnotreachedthe positionandismoving |
disableHomeCommand | Bool | FALSE | TRUE:Disablecommandforhome position.Actuator starts moving to home positionwhen`commandWorkPos`issettoFALSE |
disableFeedbackHomePos | Bool | FALSE | TRUE: Disable the monitoring of the Homeposition feedback. FALSE: Home position isreachedafter`monitoringReachingFeedback`timeexpires. |
disableFeedbackWorkPos | Bool | FALSE | TRUE: Disable the monitoring of the Workpositionfeedback.FALSE:Work positionisreachedafter`monitoringReachingFeedback`timeexpires. |
disableAlarms | Bool | FALSE | TRUE:Disablethealarmsoftheblock |
resetOutputsOnError | Bool | FALSE | TRUE: in case of an error the outputs are bereset and the error has to be acknowledgedbeforefurther processingispossible |
Moduleinterfaceforexternalsystems
Identifier | Data Type | DefaultValue | Description |
|---|---|---|---|
commands | LBC_typeInterfaceCommands | default | Modulerelatedcommandsfromexternalsystems |
configuration | LBC_typeTwoWayActuatorConfiguration | default | Modulerelated configurationparameters |
monitoring | LBC_typeTwoWayActuatorProcessValues | default | Modulerelated monitoringinformation |
diagnostics | LBC_typeDiagnostics | default | Modulerelated diagnosticinformation |
功能描述

如果输入使能为 TRUE,则将模块置于操作状态。
执行器由 commandWorkPos 和 commandHomePos 两个输入控制,任何时候只能设置一个。
如果 commandWorkPos 为 TRUE,则该块设置输出 goToWorkPos,
如果CommandHomePos 是正确的,然后该块设置输出 goToHomePos。
一旦模块开始从一个位置移动到另一个位置,两个控制时间被启动-离开位置和到达位置的控制时间。
这些定时器的用途是监测执行器是否离开实际位置,并监测执行器到达新的位置,它正在向前移动-到达反馈。

这些定时器可以通过模块接口中的参数进行配置。如果执行器是从Home移动到工作位置,离开的位置是home位置(反馈home位置) ,到达的位置是工作位置(反馈工作位置)。
如果执行器是从工作位置移动到home位置,离开位置是工作位置(反馈工作位置) ,到达位置是home位置(反馈家庭位置)。相同的时间设置(离开反馈和达到反馈)是独立使用.
当执行器完成向工作位置或home位置移动时,各自的输出被复位(FALSE)。这是为了控制执行器,不需要额外的力量,一旦他们到达他们的最终位置。
如果需要在到达目的地时保留 goToWorkposition 或 goToHomeposition 的输出设置(TRUE) ,则可以通过 setOutputHomeContinous 和 setOutputWorkContinous 配置它。
在其中一个反馈或两个反馈都不可用的情况下,可以从块的参数中禁用它们的监视。
在这种情况下,将一个状态转换为另一个状态(Home to Work 和 Work to Home)的转换和持续时间完全在 monitor ingReachingFeeback 参数上完成。
如果时间过期,反馈没有被禁用,模块将引发一个错误。根据配置 resetOutputsOnError,如果参数设置为 FALSE (默认值) ,它将保持实际状态,或者通过重置输出跳入错误状态。
如果模块处于错误状态,则必须通过输入确认来确认错误,一旦确认错误,就可以重新启动操作。
以下为SCL源代码,可以直接copy使用。不copy代码就不用往下看了。
TYPE "LBC_typeTwoWayActuatorProcessValues"
VERSION : 0.1
STRUCT
enable { ExternalWritable := 'False'} : Bool;
commandHomePos { ExternalWritable := 'False'} : Bool;
commandWorkPos { ExternalWritable := 'False'} : Bool;
feedbackHomePos { ExternalWritable := 'False'} : Bool;
feedbackWorkPos { ExternalWritable := 'False'} : Bool;
goToHomePos { ExternalWritable := 'False'} : Bool;
goToWorkPos { ExternalWritable := 'False'} : Bool;
inHomePos { ExternalWritable := 'False'} : Bool;
inWorkPos { ExternalWritable := 'False'} : Bool;
error { ExternalWritable := 'False'} : Bool;
END_STRUCT;
END_TYPE
TYPE "LBC_typeTwoWayActuatorConfiguration"
VERSION : 0.1
STRUCT
referenceDesignator { S7_SetPoint := 'True'} : String[20] := 'TwoWayAct.';
monitoringLeavingFeedback { S7_SetPoint := 'True'} : Time := T#5s;
monitoringReachingFeedback { S7_SetPoint := 'True'} : Time := T#5s;
setOutputHomeContinuously { S7_SetPoint := 'True'} : Bool := TRUE;
setOutputWorkContinuously { S7_SetPoint := 'True'} : Bool := TRUE;
disableHomeCommand { S7_SetPoint := 'True'} : Bool;
disableFeedbackHomePos { S7_SetPoint := 'True'} : Bool;
disableFeedbackWorkPos { S7_SetPoint := 'True'} : Bool;
disableAlarms { S7_SetPoint := 'True'} : Bool;
resetOutputsOnError { S7_SetPoint := 'True'} : Bool;
END_STRUCT;
END_TYPE
TYPE "LBC_typeDiagnostics"
VERSION : 0.1
STRUCT
status { ExternalWritable := 'False'} : Word;
subfunctionStatus { ExternalWritable := 'False'} : Word;
stateNumber { ExternalWritable := 'False'} : DInt;
END_STRUCT;
END_TYPE
TYPE "LBC_typeInterfaceCommands"
VERSION : 0.1
STRUCT
refreshConfiguration : Bool;
editConfiguration : Bool;
saveConfiguration : Bool;
acknowledge : Bool;
END_STRUCT;
END_TYPE
TYPE "LBC_typeTwoWayActuatorInterface"
VERSION : 0.1
STRUCT
commands { S7_SetPoint := 'False'} : "LBC_typeInterfaceCommands";
configuration { S7_SetPoint := 'False'} : "LBC_typeTwoWayActuatorConfiguration";
monitoring { ExternalWritable := 'False'; S7_SetPoint := 'False'} : "LBC_typeTwoWayActuatorProcessValues";
diagnostics { ExternalWritable := 'False'; S7_SetPoint := 'False'} : "LBC_typeDiagnostics";
END_STRUCT;
END_TYPE
FUNCTION_BLOCK "LBC_TwoWayActuator"
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : Siemens_Digital_Industry
FAMILY : LBC
NAME : LBC_TwoWayActuator
VAR_INPUT
enable : Bool;
commandHomePos : Bool;
commandWorkPos : Bool;
feedbackHomePos : Bool;
feedbackWorkPos : Bool;
acknowledge : Bool;
END_VAR
VAR_OUTPUT
valid { ExternalWritable := 'False'} : Bool;
busy { ExternalWritable := 'False'} : Bool;
error { ExternalWritable := 'False'} : Bool;
status { ExternalWritable := 'False'} : Word := #STATUS_NO_CALL;
goToHomePos { ExternalWritable := 'False'; S7_HiddenAssignment := 'Show'} : Bool;
goToWorkPos { ExternalWritable := 'False'} : Bool;
inHomePos { ExternalWritable := 'False'; S7_HiddenAssignment := 'HideIfNoParamAssigned'} : Bool;
inWorkPos { ExternalWritable := 'False'; S7_HiddenAssignment := 'HideIfNoParamAssigned'} : Bool;
diagnostics { ExternalWritable := 'False'} : "LBC_typeDiagnostics";
END_VAR
VAR_IN_OUT
configuration : "LBC_typeTwoWayActuatorConfiguration";
moduleInterface : "LBC_typeTwoWayActuatorInterface";
END_VAR
VAR
statProcessValues { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'; S7_SetPoint := 'False'} : "LBC_typeTwoWayActuatorProcessValues";
statDiagnostics { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'; S7_SetPoint := 'False'} : "LBC_typeDiagnostics" := (#STATUS_NO_CALL, (), ());
statEmptyDiagnostics { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'; S7_SetPoint := 'False'} : "LBC_typeDiagnostics";
instTimerReachPos {InstructionName := 'IEC_TIMER'; LibVersion := '1.0'; ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'; S7_SetPoint := 'False'} : IEC_TIMER;
instTimerLeavePos {InstructionName := 'IEC_TIMER'; LibVersion := '1.0'; ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'; S7_SetPoint := 'False'} : IEC_TIMER;
statReferenceDesignator { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : String[20];
statDisableAlarms { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statEnablePrevious { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statAckPrevious { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statCmdHomePrevious { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statCmdWorkPrevious { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statValid { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statBusy { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statError { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statFbState { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : DInt := #FB_STATE_NO_PROCESSING;
statFbStatePrevious { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : DInt := #FB_STATE_NO_PROCESSING;
statErrorUserCleared { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statErrorAutoCleared { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
statDisablingCompleted { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Bool;
END_VAR
VAR_TEMP
tempCmdHomeRisingEdge : Bool;
tempCmdWorkRisingEdge : Bool;
tempMoreThanOneCommandPresent : Bool;
END_VAR
VAR CONSTANT
FB_STATE_NO_PROCESSING : Int := 0;
FB_STATE_POSITION_NOT_DEFINED : Int := 50;
FB_STATE_IN_HOME_POSITION : Int := 51;
FB_STATE_TO_WORK_POSITION : Int := 52;
FB_STATE_IN_WORK_POSITION : Int := 53;
FB_STATE_TO_HOME_POSITION : Int := 54;
FB_STATE_ERROR_HANDLER : Int := 80;
FB_STATE_DISABLING : Int := 90;
STATUS_NO_ERROR_OCCURRED : Word := 16#0000;
STATUS_NO_CALL : Word := 16#7000;
STATUS_FIRST_CALL : Word := 16#7001;
STATUS_SUBSEQUENT_CALL : Word := 16#7002;
STATUS_POSITION_NOT_DEFINED : Word := 16#7003;
STATUS_IN_HOME_POSITION : Word := 16#7004;
STATUS_MOVE_TO_WORK_POSITION : Word := 16#7005;
STATUS_IN_WORK_POSITION : Word := 16#7006;
STATUS_MOVE_TO_HOME_POSITION : Word := 16#7007;
SUB_STATUS_NO_ERROR : Word := 16#0000;
ERR_CONFIGURATION_LEAVE_FEEDBACK_TIME_NEGATIVE : Word := 16#8201;
ERR_CONFIGURATION_REACH_FEEDBACK_TIME_NEGATIVE : Word := 16#8202;
ERR_MORE_THAN_ONE_CMD_PRESENT_AT_SAME_TIME : Word := 16#8400;
ERR_MORE_THAN_ONE_FEEDBACK_PRESENT_AT_SAME_TIME : Word := 16#8401;
ERR_TIMEOUT_HOME_POSITION : Word := 16#8402;
ERR_TIMEOUT_WORK_POSITION : Word := 16#8403;
ERR_INCORRECT_FEEDBACK_WORK_POSITION : Word := 16#8404;
ERR_INCORRECT_FEEDBACK_HOME_POSITION : Word := 16#8405;
ERR_MISSING_FEEDBACK_WORK_POSITION : Word := 16#8406;
ERR_MISSING_FEEDBACK_HOME_POSITION : Word := 16#8407;
ERR_NOT_LEAVING_HOME_POSITION : Word := 16#8408;
ERR_NOT_LEAVING_WORK_POSITION : Word := 16#8409;
ERR_UNDEFINED_STATE : Word := 16#8600;
NEGATIVE_TIME_NOT_ALLOWED : Time := T#0s;
END_VAR
BEGIN
REGION BLOCK INFO HEADER
//===============================================================================
// Siemens AG / (c)Copyright 2020
//-------------------------------------------------------------------------------
// Title: LBC_TwoWayActuator_TwoCmd
// Comment/Function: Controls an actuator between two states (e.g. positions of a valve) with two or one control commands.
// For bi stable state devices.
// Library/Family: LBC - Library of Basic Control modules
// Author: Siemens Digital Industries
// Tested with: S7-PLCSIM Advanced 3.0
// Engineering: TIA Portal V16
// Restrictions: ENO mechanism is not used - forced to TRUE.
// Requirements: PLC (S7-1200 / S7-1500)
//-------------------------------------------------------------------------------
// Change log table:
// Version | Date | Expert in charge | Changes applied
//----------|------------|-------------------------|-----------------------------
// 01.00.00 | 15.02.2021 | SIMATIC Systems Support | First released version
//===============================================================================
END_REGION BLOCK INFO HEADER
REGION DESCRIPTION
(/**/)
END_REGION DESCRIPTION
REGION PROCESS INPUT SIGNALS
// Assign and initialize internal variables
#statProcessValues.enable := #enable;
#statProcessValues.commandHomePos := #commandHomePos;
#statProcessValues.commandWorkPos := #commandWorkPos;
#statProcessValues.feedbackHomePos := #feedbackHomePos;
#statProcessValues.feedbackWorkPos := #feedbackWorkPos;
// Positive edges
#tempCmdHomeRisingEdge := #statProcessValues.commandHomePos AND NOT #statCmdHomePrevious;
#tempCmdWorkRisingEdge := #statProcessValues.commandWorkPos AND NOT #statCmdWorkPrevious;
// Save old values
#statCmdHomePrevious := #statProcessValues.commandHomePos;
#statCmdWorkPrevious := #statProcessValues.commandWorkPos;
// Set temp tag to TRUE if more than one command is present
#tempMoreThanOneCommandPresent := #statProcessValues.commandWorkPos AND (#statProcessValues.commandHomePos AND NOT #configuration.disableHomeCommand);
// Copy configuration to static for usage in supervision
#statDisableAlarms := #configuration.disableAlarms;
END_REGION PROCESS INPUT SIGNALS
REGION ALARM ACK
// Resetting alarms on positive edge of the "ack" bit
IF (#acknowledge OR #moduleInterface.commands.acknowledge) AND NOT #statAckPrevious AND #statErrorAutoCleared THEN
#statDiagnostics := #statEmptyDiagnostics;
#diagnostics := #statEmptyDiagnostics;
#statFbState := #FB_STATE_POSITION_NOT_DEFINED;
#statErrorAutoCleared := FALSE;
END_IF;
#statAckPrevious := (#acknowledge OR #moduleInterface.commands.acknowledge);
END_REGION ALARM ACK
REGION PARAMETER CHECK
// Check parameter if block is enabled
IF #statProcessValues.enable THEN
IF #configuration.monitoringLeavingFeedback < #NEGATIVE_TIME_NOT_ALLOWED THEN
#statDiagnostics.status := #ERR_CONFIGURATION_LEAVE_FEEDBACK_TIME_NEGATIVE;
#statDiagnostics.stateNumber := #statFbState;
#statErrorAutoCleared := TRUE;
#statFbState := #FB_STATE_ERROR_HANDLER;
ELSIF #configuration.monitoringReachingFeedback < #NEGATIVE_TIME_NOT_ALLOWED THEN
#statDiagnostics.status := #ERR_CONFIGURATION_REACH_FEEDBACK_TIME_NEGATIVE;
#statDiagnostics.stateNumber := #statFbState;
#statErrorAutoCleared := TRUE;
#statFbState := #FB_STATE_ERROR_HANDLER;
END_IF;
END_IF;
END_REGION PARAMETER CHECK
REGION ENABLING/DISABLING
IF #statProcessValues.enable AND #statDiagnostics.status = #STATUS_NO_CALL THEN // Enable FB
// First call; initialize FB
#statValid := TRUE;
#statBusy := TRUE;
#statError := FALSE;
#statErrorUserCleared := FALSE;
#statErrorAutoCleared := FALSE;
#statDiagnostics.status := #STATUS_FIRST_CALL;
#statDiagnostics.subfunctionStatus := #SUB_STATUS_NO_ERROR;
#statDiagnostics.stateNumber := 0;
#diagnostics := #statEmptyDiagnostics;
#statDisablingCompleted := FALSE;
// Copy configuration to static for usage in associated value of supervision
#statReferenceDesignator := #configuration.referenceDesignator;
// Initializes moduleInterface configuration with process configuration
#moduleInterface.configuration := #configuration;
// Reset timers
#instTimerLeavePos.TON(IN := FALSE,
PT := #configuration.monitoringLeavingFeedback);
#instTimerReachPos.TON(IN := FALSE,
PT := #configuration.monitoringReachingFeedback);
// State machine - start functionality
#statFbState := #FB_STATE_POSITION_NOT_DEFINED;
ELSIF NOT #statProcessValues.enable AND #statEnablePrevious THEN // Disable FB
#statFbState := #FB_STATE_DISABLING;
ELSIF #statDiagnostics.status = #STATUS_FIRST_CALL THEN // Set status identifier of subsequent call
#statDiagnostics.status := #STATUS_SUBSEQUENT_CALL;
END_IF;
// Edge detection 'enable' input
#statEnablePrevious := #statProcessValues.enable;
END_REGION ENABLING/DISABLING
REGION STATE MACHINE
REPEAT
#statFbStatePrevious := #statFbState;
CASE #statFbState OF // State machine of FB
#FB_STATE_NO_PROCESSING: // No processing active
REGION No Processing
; // No processing active (Note: this state must always be present and left empty)
END_REGION No Processing
#FB_STATE_POSITION_NOT_DEFINED: // If block is enabled move to valid state
REGION Position/State of the actuator not defined
// Evaluate commands - only one allowed to be present at the same time
IF #tempMoreThanOneCommandPresent THEN
// Write message and stay here - no progress
#statDiagnostics.status := #ERR_MORE_THAN_ONE_CMD_PRESENT_AT_SAME_TIME;
#statDiagnostics.stateNumber := #statFbState;
#statErrorAutoCleared := TRUE;
// Only one of n can be checked by using XOR for all of them together
ELSIF ((#statProcessValues.feedbackHomePos AND NOT #configuration.disableFeedbackHomePos)
AND (#statProcessValues.feedbackWorkPos AND NOT #configuration.disableFeedbackWorkPos))
THEN
// Write message and stay here - no progress
#statDiagnostics.status := #ERR_MORE_THAN_ONE_FEEDBACK_PRESENT_AT_SAME_TIME;
#statDiagnostics.stateNumber := #statFbState;
#statErrorAutoCleared := TRUE;
// Checking aa first step the feedbacks
ELSIF #statProcessValues.feedbackHomePos AND NOT #configuration.disableFeedbackHomePos THEN
// Set next state
#statFbState := #FB_STATE_IN_HOME_POSITION;
ELSIF #statProcessValues.feedbackWorkPos AND NOT #configuration.disableFeedbackWorkPos THEN
// Set next state
#statFbState := #FB_STATE_IN_WORK_POSITION;
// Checking for control commands or position feedback
ELSIF (#statProcessValues.commandHomePos OR #configuration.disableHomeCommand)
AND NOT #statProcessValues.commandWorkPos
THEN
// Set next state
#statFbState := #FB_STATE_TO_HOME_POSITION;
ELSIF #statProcessValues.commandWorkPos
AND (NOT #statProcessValues.commandHomePos OR #configuration.disableHomeCommand)
THEN
// Set next state
#statFbState := #FB_STATE_TO_WORK_POSITION;
ELSE // Stay in state and set message
#statDiagnostics.status := #STATUS_POSITION_NOT_DEFINED;
END_IF;
END_REGION Position/State of the actuator not defined
#FB_STATE_IN_HOME_POSITION: // Actuator is at home position
REGION In home pos
#statErrorAutoCleared := FALSE;
// Set output commands
#statProcessValues.goToHomePos := #configuration.setOutputHomeContinuously;
#statProcessValues.goToWorkPos := FALSE;
// Evaluate commands - only one allowed to be present at the same time
IF #tempMoreThanOneCommandPresent THEN
// Write message and stay here - no progress
#statDiagnostics.status := #ERR_MORE_THAN_ONE_CMD_PRESENT_AT_SAME_TIME;
#statDiagnostics.stateNumber := #statFbState;
#statErrorAutoCleared := TRUE;
// Go to Work position - rising edge on command
ELSIF #tempCmdWorkRisingEdge AND (NOT #statProcessValues.commandHomePos OR #configuration.disableHomeCommand) THEN
// Set next state
#statFbState := #FB_STATE_TO_WORK_POSITION;
// Missing feedback for home position
ELSIF NOT #statProcessValues.feedbackHomePos AND NOT #configuration.disableFeedbackHomePos THEN
#statDiagnostics.status := #ERR_MISSING_FEEDBACK_HOME_POSITION;
#statDiagnostics.stateNumber := #statFbState;
#statErrorAutoCleared := TRUE;
// Opposite feedback work appeared
ELSIF #statProcessValues.feedbackWorkPos AND NOT #configuration.disableFeedbackWorkPos THEN
#statDiagnostics.status := #ERR_INCORRECT_FEEDBACK_WORK_POSITION;
#statDiagnostics.stateNumber := #statFbState;
#statErrorAutoCleared := TRUE;
ELSE // Stay in state and set message
#statDiagnostics.status := #STATUS_IN_HOME_POSITION;
END_IF;
END_REGION In home pos
#FB_STATE_TO_WORK_POSITION: // Moving the actuator towards "work" position
REGION To work pos
#statErrorAutoCleared := FALSE;
// Set output commands
#statProcessValues.goToHomePos := FALSE;
#statProcessValues.goToWorkPos := TRUE;
// Start monitoring leaving home position
#instTimerLeavePos.TON(IN := NOT #configuration.disableFeedbackHomePos,
PT := #configuration.monitoringLeavingFeedback);
// Start monitoring reaching work position
#instTimerReachPos.TON(IN := TRUE,
PT := #configuration.monitoringReachingFeedback);
// Arriving at Work position - feedback present OR feedback disabled and time has expired
IF (#statProcessValues.feedbackWorkPos AND NOT #configuration.disableFeedbackWorkPos) OR
(#instTimerReachPos.Q AND #configuration.disableFeedbackWorkPos)
THEN
// Set next state
#statFbState := #FB_STATE_IN_WORK_POSITION;
// Evaluate commands - only one allowed to be present at the same time
ELSIF #tempMoreThanOneCommandPresent THEN
// Write message and stay here - no progress
#statDiagnostics.status := #ERR_MORE_THAN_ONE_CMD_PRESENT_AT_SAME_TIME;
#statDiagnostics.stateNumber := #statFbState;
#statErrorAutoCleared := TRUE;
// Cancel of go to work position command
// Program goes back to home position if home command is deactivated
ELSIF NOT #statProcessValues.commandWorkPos
AND (#tempCmdHomeRisingEdge OR #configuration.disableHomeCommand)
THEN
// Set next state
#statFbState := #FB_STATE_TO_HOME_POSITION;
// Time expired for leaving Home position
ELSIF #statProcessValues.feedbackHomePos AND #instTimerLeavePos.Q THEN
// Set state and status
#statDiagnostics.status := #ERR_NOT_LEAVING_HOME_POSITION;
#statDiagnostics.stateNumber := #statFbState;
#statErrorAutoCleared := TRUE;
// Time expired for reaching Work position
ELSIF NOT #statProcessValues.feedbackWorkPos AND #instTimerReachPos.Q THEN
// Set state and status
#statDiagnostics.status := #ERR_TIMEOUT_WORK_POSITION;
#statDiagnostics.stateNumber := #statFbState;
#statErrorAutoCleared := TRUE;
ELSE // Stay in state and set message
#statDiagnostics.status := #STATUS_MOVE_TO_WORK_POSITION;
END_IF;
END_REGION To work pos
#FB_STATE_IN_WORK_POSITION: // Actuator is at work position
REGION In work pos
#statErrorAutoCleared := FALSE;
// Set output commands
#statProcessValues.goToHomePos := FALSE;
#statProcessValues.goToWorkPos := #configuration.setOutputWorkContinuously;
// Evaluate commands - both can't be present at the same time
IF #tempMoreThanOneCommandPresent THEN
// Write message and stay here - no progress
#statDiagnostics.status := #ERR_MORE_THAN_ONE_CMD_PRESENT_AT_SAME_TIME;
#statDiagnostics.stateNumber := #statFbState;
#statErrorAutoCleared := TRUE;
// Go to Home position command
ELSIF (NOT #statProcessValues.commandWorkPos AND (#tempCmdHomeRisingEdge OR #configuration.disableHomeCommand)) THEN
// Set next state
#statFbState := #FB_STATE_TO_HOME_POSITION;
// Missing feedback for work position
ELSIF NOT #statProcessValues.feedbackWorkPos AND NOT #configuration.disableFeedbackWorkPos THEN
#statDiagnostics.status := #ERR_MISSING_FEEDBACK_WORK_POSITION;
#statDiagnostics.stateNumber := #statFbState;
#statErrorAutoCleared := TRUE;
// Opposite feedback home appeared
ELSIF #statProcessValues.feedbackHomePos AND NOT #configuration.disableFeedbackHomePos THEN
#statDiagnostics.status := #ERR_INCORRECT_FEEDBACK_HOME_POSITION;
#statDiagnostics.stateNumber := #statFbState;
#statErrorAutoCleared := TRUE;
ELSE // Stay in state and set message
#statDiagnostics.status := #STATUS_IN_WORK_POSITION;
END_IF;
END_REGION In work pos
#FB_STATE_TO_HOME_POSITION: // Moving the actuator towards home position
REGION To home pos
#statErrorAutoCleared := FALSE;
// Set output commands
#statProcessValues.goToHomePos := TRUE;
#statProcessValues.goToWorkPos := FALSE;
// Start monitoring leaving home position
#instTimerLeavePos.TON(IN := NOT #configuration.disableFeedbackWorkPos,
PT := #configuration.monitoringLeavingFeedback);
// Start monitoring reaching work position
#instTimerReachPos.TON(IN := TRUE,
PT := #configuration.monitoringReachingFeedback);
// Arriving at Home position - feedback present -OR feedback disabled and Time has expired
IF (#statProcessValues.feedbackHomePos AND NOT #configuration.disableFeedbackHomePos) OR
(#instTimerReachPos.Q AND #configuration.disableFeedbackHomePos)
THEN
// Set next state
#statFbState := #FB_STATE_IN_HOME_POSITION;
// Evaluate commands - only one allowed to be present at the same time
ELSIF #tempMoreThanOneCommandPresent THEN
// Write message and stay here - no progress
#statDiagnostics.status := #ERR_MORE_THAN_ONE_CMD_PRESENT_AT_SAME_TIME;
#statDiagnostics.stateNumber := #statFbState;
#statErrorAutoCleared := TRUE;
// Command work position has rising edge
ELSIF #tempCmdWorkRisingEdge
AND (NOT #statProcessValues.commandHomePos OR #configuration.disableHomeCommand) THEN
// Set next state
#statFbState := #FB_STATE_TO_WORK_POSITION;
// Time expired for leaving Work position
ELSIF #statProcessValues.feedbackWorkPos AND #instTimerLeavePos.Q THEN
// Set state and status
#statDiagnostics.status := #ERR_NOT_LEAVING_WORK_POSITION;
#statDiagnostics.stateNumber := #statFbState;
#statErrorAutoCleared := TRUE;
// Time expired for reaching Home position
ELSIF NOT #statProcessValues.feedbackHomePos AND #instTimerReachPos.Q THEN
// Set state and status
#statDiagnostics.status := #ERR_TIMEOUT_HOME_POSITION;
#statDiagnostics.stateNumber := #statFbState;
#statErrorAutoCleared := TRUE;
ELSE // Stay in state and set message
#statDiagnostics.status := #STATUS_MOVE_TO_HOME_POSITION;
END_IF;
END_REGION To home pos
#FB_STATE_ERROR_HANDLER: // Error handling state
REGION Error handling
// Stay here until error is acknowledged
#statErrorAutoCleared := TRUE;
// Reset the outputs
#statProcessValues.goToHomePos := FALSE;
#statProcessValues.goToWorkPos := FALSE;
END_REGION Error handling
#FB_STATE_DISABLING: // Disabling active
REGION Disabling
// Switch off control outputs
#statProcessValues.goToHomePos := FALSE;
#statProcessValues.goToWorkPos := FALSE;
#statDisablingCompleted := TRUE;
END_REGION Disabling
ELSE // Undefined state in state machine reached
REGION Undefined state
#statDiagnostics.status := #ERR_UNDEFINED_STATE;
#statDiagnostics.stateNumber := #statFbState;
#statErrorUserCleared := TRUE;
END_REGION Undefined state
END_CASE;
REGION State change handling
// Reset the timers if state has changed
IF #statFbStatePrevious <> #statFbState THEN
#instTimerLeavePos.TON(IN := FALSE,
PT := #configuration.monitoringLeavingFeedback);
#instTimerReachPos.TON(IN := FALSE,
PT := #configuration.monitoringReachingFeedback);
END_IF;
END_REGION State change handling
REGION Reset outputs on error
// Check if the condition for error must be acknowledged - then move to error handler state
IF #configuration.resetOutputsOnError AND #statDiagnostics.status.%X15
AND #statDiagnostics.status <> #ERR_MORE_THAN_ONE_CMD_PRESENT_AT_SAME_TIME
AND #statDiagnostics.status <> #ERR_UNDEFINED_STATE
AND #statFbState <> #FB_STATE_ERROR_HANDLER
THEN
#statFbState := #FB_STATE_ERROR_HANDLER;
END_IF;
END_REGION Reset outputs on error
// Leave state machine if state has not changed or error is present
// Stay in state machine if state has changed and no error is present
UNTIL (#statFbStatePrevious = #statFbState OR #statDiagnostics.status.%X15)
END_REPEAT;
END_REGION STATE MACHINE
REGION CONFIGURATION HANDLING
// Refresh module interface configuration with process configuration
IF #moduleInterface.commands.refreshConfiguration AND NOT #moduleInterface.commands.editConfiguration THEN
#moduleInterface.configuration := #configuration;
END_IF;
#moduleInterface.commands.refreshConfiguration := FALSE;
// Save module interface configuration to process configuration
IF #moduleInterface.commands.saveConfiguration AND #moduleInterface.commands.editConfiguration THEN
#configuration := #moduleInterface.configuration;
#statReferenceDesignator := #configuration.referenceDesignator;
#moduleInterface.commands.saveConfiguration := FALSE;
END_IF;
END_REGION CONFIGURATION HANDLING
REGION PROCESS OUTPUT SIGNALS
// Write outputs
IF #statDisablingCompleted THEN
REGION Disabling
// Reset outputs if disabling completed
#statValid := FALSE;
#statBusy := FALSE;
#statError := FALSE;
#statErrorUserCleared := FALSE;
#statErrorAutoCleared := FALSE;
#statDiagnostics.status := #STATUS_NO_CALL;
// Execution finished --> set state no processing
#statFbState := #FB_STATE_NO_PROCESSING;
END_REGION Disabling
ELSIF #statErrorUserCleared AND NOT #statError THEN
REGION Error user cleared
// Error can only be cleared by user; rising edge at enable input is needed to continue
#statValid := FALSE;
#statBusy := FALSE;
#statError := TRUE;
// Write diagnostics
#diagnostics := #statDiagnostics;
// Execution aborted --> set state no processing
#statFbState := #FB_STATE_NO_PROCESSING;
// switch off control outputs
#statProcessValues.goToHomePos := FALSE;
#statProcessValues.goToWorkPos := FALSE;
END_REGION Error user cleared
ELSIF #statErrorAutoCleared AND NOT #statError THEN
REGION Error auto cleared
// Error can be reset by FB automatically
#statValid := FALSE;
#statBusy := TRUE;
#statError := TRUE;
// Write diagnostics
#diagnostics := #statDiagnostics;
END_REGION Error auto cleared
ELSIF NOT #statErrorAutoCleared AND NOT #statErrorUserCleared AND #statError THEN
REGION After user/auto cleared
// If auto cleared error is acknowledged
#statValid := TRUE;
#statBusy := TRUE;
#statError := FALSE;
END_REGION After user/auto cleared
END_IF;
REGION Write monitoring structure
#statProcessValues.inHomePos := #statFbState = #FB_STATE_IN_HOME_POSITION;
#statProcessValues.inWorkPos := #statFbState = #FB_STATE_IN_WORK_POSITION;
END_REGION Write monitoring structure
REGION Write Process data to module interface
#statProcessValues.error := #statError;
#moduleInterface.monitoring := #statProcessValues;
#moduleInterface.diagnostics := #statDiagnostics;
END_REGION
REGION Write work data to interface and outputs
// Function status
#goToHomePos := #statProcessValues.goToHomePos;
#goToWorkPos := #statProcessValues.goToWorkPos;
#inHomePos := #statProcessValues.inHomePos;
#inWorkPos := #statProcessValues.inWorkPos;
// Write status outputs
#valid := #statValid;
#busy := #statBusy;
#error := #statError;
#status := #statDiagnostics.status;
// ENO mechanism disabled, ENO - forced to TRUE
ENO := TRUE;
END_REGION Write static values to outputs
END_REGION PROCESS OUTPUT SIGNALS
END_FUNCTION_BLOCK