该定时可用于在触发或关闭同一电动机时产生延迟,或者在不同电动机之间的接通或断开时产生延迟。 这是用于保护电动机的功能,避免间隔很短的驱动器。 在发生警报时,会自动禁用电动机(优先级随时间推移),以避免进一步损坏。
通过创建一个子例程以读取机器的状态来启动我的代码,这将告诉我它是打开还是关闭。然后创建一个子程序,该程序读取处于警报状态的计算机,然后我检查了该计算机是否处于警报状态。在此代码下方,我创建了一个驱动电动机的例程,然后创建了一个例程,以触发必须连接电动机的输出,然后用else完成了我的代码,在该例程中,电动机关闭了。
VAR_INPUT
ENABLE : BOOL := FALSE; (*ENABLES THE BLOCK OPERATION*)
DEV_STS1 : BOOL := FALSE; (*REPRESENTS MOTOR STATUS 1 ON / OFF*)
DEV_STS2 : BOOL := FALSE; (*REPRESENTS MOTOR STATUS 2 ON / OFF*)
DEV_STS3 : BOOL := FALSE; (*REPRESENTS MOTOR STATUS 3 ON / OFF*)
DEV_STS4 : BOOL := FALSE; (*REPRESENTS MOTOR STATUS 4 ON / OFF*)
DEV_STS5 : BOOL := FALSE; (*REPRESENTS MOTOR STATUS 5 ON / OFF*)
DEV_STS6 : BOOL := FALSE; (*REPRESENTS MOTOR STATUS 6 ON / OFF*)
DEV_ALA1 : BOOL := FALSE; (*REPRESENTS MOTOR ALARM CONDITION 1*)
DEV_ALA2 : BOOL := FALSE; (*REPRESENTS MOTOR ALARM CONDITION 2*)
DEV_ALA3 : BOOL := FALSE; (*REPRESENTS MOTOR ALARM CONDITION 3*)
DEV_ALA4 : BOOL := FALSE; (*REPRESENTS MOTOR ALARM CONDITION 4*)
DEV_ALA5 : BOOL := FALSE; (*REPRESENTS MOTOR ALARM CONDITION 5*)
DEV_ALA6 : BOOL := FALSE; (*REPRESENTS MOTOR ALARM CONDITION 6*)
T_MIN_ON : REAL := 0.0; (*MINIMUM TIME ON ONE SAME MOTOR / RANGE 0.0 ~ 9999.0 **)
T_MIN_OFF : REAL := 0.0; (*MINIMUM TIME OFF OF SAME MOTOR / RANGE 0.0 ~ 9999.0*)
T_ON_ON : REAL := 0.0; (*MINIMUM TIME BETWEEN TWO PARTS OF THE SAME MOTOR / RANGE 0.0 ~ 9999.0*)
T_ON_OTHER : REAL := 0.0; (*TIME BETWEEN TURN ON DIFFERENT MOTORS / RANGE 0.0 ~ 9999.0*)
T_OFF_OTHER : REAL := 0.0; (*TIME BETWEEN TURN OFF DIFFERENT MOTORS / RANGE 0.0 ~ 9999.0*)
END_VAR
VAR_OUTPUT
REQ_DEV1 : BOOL := FALSE; (*STATUS D0 MOTOR 1 (COMPRESSOR) ACCORDING TO THE TIMER LOGIC*)
REQ_DEV2 : BOOL := FALSE; (*STATUS D0 MOTOR 2 (COMPRESSOR) ACCORDING TO THE TIMER LOGIC*)
REQ_DEV3 : BOOL := FALSE; (*STATUS D0 MOTOR 3 (COMPRESSOR) ACCORDING TO THE TIMER LOGIC*)
REQ_DEV4 : BOOL := FALSE; (*STATUS D0 MOTOR 4 (COMPRESSOR) ACCORDING TO THE TIMER LOGIC*)
REQ_DEV5 : BOOL := FALSE; (*STATUS D0 MOTOR 5 (COMPRESSOR) ACCORDING TO THE TIMER LOGIC*)
REQ_DEV6 : BOOL := FALSE; (*STATUS D0 MOTOR 6 (COMPRESSOR) ACCORDING TO THE TIMER LOGIC*)
END_VAR
VAR
DEV_STS : ARRAY[1..6] OF BOOL; (*MOTOR STATUS READING ARRAY*)
DEV_ALA : ARRAY[1..6] OF BOOL; (*ARRAY READING OF MOTORS ALARMS*)
REQ_DEV : ARRAY[1..6] OF BOOL; (*ARRAY TO MANIPULATE MOTORS STATES*)
FLAG_STS : ARRAY[1..6] OF BOOL; (*ARRAY FOR PREVIOUS STATUS CONTROL OF MOTORS*)
IDX : USINT := 0; (*GENERIC INDEX TO HANDLE ARRAY*)
DEV_ON : USINT := 0; (*AMOUNT OF MOTORS MUST BE TURN ON*)
T_ON_INT : ARRAY[1..6] OF REAL; (*INTERNAL TIME ON A SAME MOTOR*)
T_OFF_INT : ARRAY[1..6] OF REAL; (*INTERNAL TIME OFF A SAME MOTOR*)
T_CYCLE : ARRAY[1..6] OF REAL; (*CYCLE TIME OF SAME MOTOR*)
END_VAR
IF ENABLE THEN
(*==================================================================================*)
(*READINGS OF MOTORS STATUS*)
(*==================================================================================*)
DEV_STS[1] := DEV_STS1;
DEV_STS[2] := DEV_STS2;
DEV_STS[3] := DEV_STS3;
DEV_STS[4] := DEV_STS4;
DEV_STS[5] := DEV_STS5;
DEV_STS[6] := DEV_STS6;
(*==================================================================================*)
(*READINGS OF THE MOTORS ALARM STATUS*)
(*==================================================================================*)
DEV_ALA[1] := DEV_ALA1;
DEV_ALA[2] := DEV_ALA2;
DEV_ALA[3] := DEV_ALA3;
DEV_ALA[4] := DEV_ALA4;
DEV_ALA[5] := DEV_ALA5;
DEV_ALA[6] := DEV_ALA6;
(*==================================================================================*)
(*CHECK IF ANY MOTOR IS ALARMED*)
(*==================================================================================*)
FOR IDX := 0 TO 6 BY 1 DO
IF DEV_ALA[IDX] = TRUE THEN
REQ_DEV[IDX] := FALSE;
END_IF;
END_FOR;
(*==================================================================================*)
(*CHECKING WHAT MOTOR SHOULD BE TURN ON*)
(*==================================================================================*)
FOR IDX := 0 TO 6 BY 1 DO
IF DEV_STS[IDX] = TRUE THEN
DEV_ON := DEV_ON + 1;
END_IF;
END_FOR;
(*==================================================================================*)
(*ACTING A MOTOR*)
(*==================================================================================*)
FOR IDX := 0 TO 6 DO
T_CYCLE[IDX] := T_ON_INT[IDX] + T_OFF_INT[IDX];
IF DEV_STS[IDX] = TRUE AND FLAG_STS[IDX] = FALSE THEN
IF T_CYCLE[IDX] > T_ON_ON THEN
IF T_ON_INT[IDX] < T_MIN_OFF THEN
REQ_DEV[IDX] := TRUE;
END_IF;
END_IF;
END_IF;
IF DEV_STS[IDX] = FALSE AND FLAG_STS[IDX] = TRUE THEN
IF T_ON_INT[IDX] >= T_MIN_ON THEN
REQ_DEV[IDX] := FALSE;
END_IF;
END_IF;
IF DEV_STS[IDX] = TRUE AND FLAG_STS[IDX] = TRUE THEN
T_ON_INT[IDX] := T_ON_INT[IDX] + 1.0;
END_IF;
END_FOR;
(*==================================================================================*)
(*LEADING OUTPUTS*)
(*==================================================================================*)
REQ_DEV1 := REQ_DEV[1] ;
REQ_DEV2 := REQ_DEV[2] ;
REQ_DEV3 := REQ_DEV[3] ;
REQ_DEV4 := REQ_DEV[4] ;
REQ_DEV5 := REQ_DEV[5] ;
REQ_DEV6 := REQ_DEV[6] ;
(*==================================================================================*)
(*FLAG*)
(*==================================================================================*)
FLAG_STS[1] := REQ_DEV1;
FLAG_STS[2] := REQ_DEV2;
FLAG_STS[3] := REQ_DEV3;
FLAG_STS[4] := REQ_DEV4;
FLAG_STS[5] := REQ_DEV5;
FLAG_STS[6] := REQ_DEV6;
ELSE
REQ_DEV1 := FALSE;
REQ_DEV2 := FALSE;
REQ_DEV3 := FALSE;
REQ_DEV4 := FALSE;
REQ_DEV5 := FALSE;
REQ_DEV6 := FALSE;
END_IF;
我尚未测试代码。但是我通常使用CFC进行测试。
答案 0 :(得分:1)
对于CFC,这可能没问题,但对于ST而言却不是。在ST中,您必须使用不同的概念。我对您的代码有很多疑问,但是让我向您展示我的理解方式,稍后您会提出问题。
首先,创建一个类型。
TYPE MOTOR : STRUCT
State: BOOL; (* State of the motor translated to DO *)
Task: BOOL; (* Do we want to turn this motor off or on *)
Alarm: BOOL; (* Motor alarm *)
TimerOnMax: TP; (* Timer to maximum work for motor *)
TimerOnMin: TP; (* Timer to maximum work for motor *)
TimerOff: TP; (* Timer for minimum pause between work *)
TimeOnMax: TIME; (* Maximum time for motor to work *)
TimeOnMin: TIME; (* Minimum time for motor to work *)
TimeOff: TIME; (* Minimum time for motor to rest *)
END_STRUCT
END_TYPE
现在定义全局变量
VAR_GLOBAL
(* Array of motors to manage *)
stMotors: ARRAY[1.._MOTORS_NUM] OF MOTOR := [
_MOTORS_NUM(TimeOnMax := T#1h, TimeOnMin := T#10m, TimeOff := T#30m)
];
END_VAR
VAR_GLOBAL CONSTANT
_MOTORS_NUM: INT := 6; (* Number of motors in array *)
END_VAR
根据CoDeSys版本的不同,初始化可能有所不同
现在我们的功能块
FUNCTION_BLOCK ManageMotors
VAR_INPUT
ENABLE: BOOL; (* Enable motor management *)
M_NUM: INT; (* Number of motors to be working *)
END_VAR
VAR
iCount: INT; (* Index for circle *)
iNumOfMotors: INT; (* Number of currently working motors *)
END_VAR
IF NOT ENABLE THEN
actTurnOffAll();
actApply();
RETURN;
END_IF;
actCountWroking();
FOR iCount := 1 TO _MOTORS_NUM DO
(* If motor in alarm state turn it off *)
IF stMotors[iCount].Alarm AND stMotors[iCount].State THEN
stMotors[iCount].Task := FALSE;
iNumOfMotors := iNumOfMotors - 1;
END_IF;
(* If motor works longer that allowed time turn it off *)
IF stMotors[iCount].State AND
stMotors[iCount].Task AND
NOT stMotors[iCount].TimerOnMax.Q
THEN
stMotors[iCount].Task := FALSE;
iNumOfMotors := iNumOfMotors - 1;
END_IF;
(* If amout of working motors more that allowed number turn one off *)
IF iNumOfMotors > M_NUM AND
stMotors[iCount].State AND
stMotors[iCount].Task AND
NOT stMotors[iCount].TimerOnMin.Q
THEN
stMotors[iCount].Task := FALSE;
iNumOfMotors := iNumOfMotors - 1;
END_IF;
(* If amount of working motors less then required turn one motor on *)
IF iNumOfMotors < M_NUM AND
NOT stMotors[iCount].State AND
NOT stMotors[iCount].Task AND
NOT stMotors[iCount].TimerOff.Q
THEN
stMotors[iCount].Task := TRUE;
iNumOfMotors := iNumOfMotors + 1;
END_IF;
stMotors[iCount].TimerOnMax(
IN := (stMotors[iCount].Task AND NOT stMotors[iCount].State),
PT := stMotors[iCount].TimeOnMax
);
stMotors[iCount].TimerOnMin(
IN := (stMotors[iCount].Task AND NOT stMotors[iCount].State),
PT := stMotors[iCount].TimeOnMin
);
stMotors[iCount].TimerOff(
IN := (NOT stMotors[iCount].Task AND stMotors[iCount].State),
PT := stMotors[iCount].TimeOff
);
END_FOR;
actApply();
ACTION actCountWroking:
iNumOfMotors := 0;
FOR iCount := 1 TO _MOTORS_NUM DO
IF stMotors[iCount].State THEN
iNumOfMotors := iNumOfMotors + 1;
END_IF;
END_FOR;
END_ACTION;
ACTION actTurnOffAll:
FOR iCount := 1 TO _MOTORS_NUM DO
stMotors[iCount].Task := FALSE;
END_FOR;
END_ACTION;
ACTION actApply:
FOR iCount := 1 TO _MOTORS_NUM DO
stMotors[iCount].State := stMotors[iCount].Task;
END_FOR;
END_ACTION;
END_FUNCTION_BLOCK
我添加了一些注释,但其余代码必须清楚。我使用了ACTION
,因为它与CDS 3.5一样在CDS 2.3中可用,但是如果您有3.5版本,则可以使用METHOD
。