Plc 多独立输入定时器
假设我们有独立的布尔变量,它们可以独立出现。现在,如果在一段时间内至少有一个变量出现,则会激活警报。常见的解决方案是为每个变量使用一个计时器 是否有一个只能与单个计时器一起使用的最佳解决方案 传递时间为1秒的2个变量示例:Plc 多独立输入定时器,plc,twincat,st,Plc,Twincat,St,假设我们有独立的布尔变量,它们可以独立出现。现在,如果在一段时间内至少有一个变量出现,则会激活警报。常见的解决方案是为每个变量使用一个计时器 是否有一个只能与单个计时器一起使用的最佳解决方案 传递时间为1秒的2个变量示例: VAR Timer1,Timer2:TON; bVar1,bVar2:BOOL; tSetDelay:TIME:=T#1S; Alarm:BOOL; END_VAR Timer1(IN:=bVar1,PT:=tSetDelay); Timer
VAR
Timer1,Timer2:TON;
bVar1,bVar2:BOOL;
tSetDelay:TIME:=T#1S;
Alarm:BOOL;
END_VAR
Timer1(IN:=bVar1,PT:=tSetDelay);
Timer2(IN:=bVar2,PT:=tSetDelay);
IF Timer1.Q RO Timer2.Q THEN
Alarm:=TRUE;
END_IF
如果我们使用或
则不正确
Timer(IN:=bVar1 OR bVar2,PT:=tSetDelay);
因为VAR可能在相同的t延时
时间内重叠,这意味着它们的发生时间可能小于延时,但定时器输出为真
在本例中,我们只有2个变量,但如果我们有更多的变量,则找到更好的解决方案将更为重要。不可能使用单个计时器来管理此问题。 如果您希望确保触发源是单个变量(没有来自其他变量的任何逻辑干扰),则必须将每个变量与其自身的历史(计时器)进行比较 建议的前进路径是构建一个报警功能块,以一致的方式处理这里的大部分逻辑。此类功能块的示例如下: 报警监视器
不可能用一个计时器来管理它。 如果您希望确保触发源是单个变量(没有来自其他变量的任何逻辑干扰),则必须将每个变量与其自身的历史(计时器)进行比较 建议的前进路径是构建一个报警功能块,以一致的方式处理这里的大部分逻辑。此类功能块的示例如下: 报警监视器
如果没有单独的计时器,则无法执行此操作。以下是我将如何处理这个问题 设置全局常量和变量
VAR_GLOBAL
glbEvents: ARRAY[1..c_EventsNum] OF stMyEvents; (* Events array *)
END_VAR
VAR_GLOBAL CONSTANT
c_EventsNum: INT := 3; (* Number of events *)
END_VAR
现在,您可以将glbEvents[1]状态映射到PLC的输入
定义新结构
TYPE stMyEvents : STRUCT
State : BOOL; (* Event current state *)
StateM : BOOL; (* Memmory of state in previouse cycle to get the trigger *)
Timer: TON := (PT := T#1S); (* Timer *)
END_STRUCT
END_TYPE
创建函数
FUNCTION ProcessEvents : BOOL
VAR
iCount: INT; (* Counter *)
END_VAR
FOR iCount := 1 TO c_EventsNum DO
glbEvents[iCount].Timer(IN := glbEvents[iCount].State);
IF glbEvents[iCount].Timer.Q THEN
ProcessEvents := TRUE;
EXIT;
END_IF;
END_FOR;
END_FUNCTION
实施
PROGRAM PLC_PRG
VAR
xAlarm: BOOL; (* Alarm *)
END_VAR
IF ProcessEvents() THEN
// Alarm happened
END_IF;
END_PROGRAM
使用这种方法,虽然您没有1个计时器,但您有一定的抽象级别,这使得它更灵活地支持和修改
但如果你绝对不想有这么多吨计时器,你可以创建自己的计时器。它将是一个FB中的单个计时器
VAR_GLOBAL
glbEvents: ARRAY[1..c_EventsNum] OF stMyEvents; (* Events array *)
END_VAR
VAR_GLOBAL CONSTANT
c_EventsNum: INT := 3; (* Number of events *)
END_VAR
TYPE stMyEvents : STRUCT
State : BOOL; (* Event current state *)
StateM : BOOL; (* Memmory of state in previouse cycle to get the trigger *)
TimeM: TIME; (* Memmory of event start time *)
END_STRUCT
END_TYPE
FUNCTION_BLOCK ProcessEvents
VAR
iCount: INT; (* Counter *)
END_VAR
VAR_OUTPUT
Q: BOOL; (* Impulse if alarm *)
END_VAR
Q := FALSE;
FOR iCount := 1 TO c_EventsNum DO
(* Get raising edge and save the timer *)
IF glbEvents[iCount].State AND NOT glbEvents[iCount].StateM THEN
glbEvents[iCount].TimeM := TIME();
END_IF;
glbEvents[iCount].StateM := glbEvents[iCount].State;
(* If event is low reset timer *)
IF NOT glbEvents[iCount].State THEN
glbEvents[iCount].TimeM := T#0S;
END_IF;
(* if more than a second make impuls on Q *)
IF (glbEvents[iCount].TimeM > T#0S) AND ((TIME() - glbEvents[iCount].TimeM) >= T#1S) THEN
Q := TRUE;
glbEvents[iCount].TimeM := T#0S;
END_IF;
END_FOR;
END_FUNCTION_BLOCK
PROGRAM PLC_PRG
VAR
fbeventProcess: ProcessEvents; (* function block *)
END_VAR
fbeventProcess();
IF fbeventProcess.Q THEN
// Alarm happened
END_IF;
END_PROGRAM
如果没有单独的计时器,则无法执行此操作。以下是我将如何处理这个问题
设置全局常量和变量
VAR_GLOBAL
glbEvents: ARRAY[1..c_EventsNum] OF stMyEvents; (* Events array *)
END_VAR
VAR_GLOBAL CONSTANT
c_EventsNum: INT := 3; (* Number of events *)
END_VAR
现在,您可以将glbEvents[1]状态映射到PLC的输入
定义新结构
TYPE stMyEvents : STRUCT
State : BOOL; (* Event current state *)
StateM : BOOL; (* Memmory of state in previouse cycle to get the trigger *)
Timer: TON := (PT := T#1S); (* Timer *)
END_STRUCT
END_TYPE
创建函数
FUNCTION ProcessEvents : BOOL
VAR
iCount: INT; (* Counter *)
END_VAR
FOR iCount := 1 TO c_EventsNum DO
glbEvents[iCount].Timer(IN := glbEvents[iCount].State);
IF glbEvents[iCount].Timer.Q THEN
ProcessEvents := TRUE;
EXIT;
END_IF;
END_FOR;
END_FUNCTION
实施
PROGRAM PLC_PRG
VAR
xAlarm: BOOL; (* Alarm *)
END_VAR
IF ProcessEvents() THEN
// Alarm happened
END_IF;
END_PROGRAM
使用这种方法,虽然您没有1个计时器,但您有一定的抽象级别,这使得它更灵活地支持和修改
但如果你绝对不想有这么多吨计时器,你可以创建自己的计时器。它将是一个FB中的单个计时器
VAR_GLOBAL
glbEvents: ARRAY[1..c_EventsNum] OF stMyEvents; (* Events array *)
END_VAR
VAR_GLOBAL CONSTANT
c_EventsNum: INT := 3; (* Number of events *)
END_VAR
TYPE stMyEvents : STRUCT
State : BOOL; (* Event current state *)
StateM : BOOL; (* Memmory of state in previouse cycle to get the trigger *)
TimeM: TIME; (* Memmory of event start time *)
END_STRUCT
END_TYPE
FUNCTION_BLOCK ProcessEvents
VAR
iCount: INT; (* Counter *)
END_VAR
VAR_OUTPUT
Q: BOOL; (* Impulse if alarm *)
END_VAR
Q := FALSE;
FOR iCount := 1 TO c_EventsNum DO
(* Get raising edge and save the timer *)
IF glbEvents[iCount].State AND NOT glbEvents[iCount].StateM THEN
glbEvents[iCount].TimeM := TIME();
END_IF;
glbEvents[iCount].StateM := glbEvents[iCount].State;
(* If event is low reset timer *)
IF NOT glbEvents[iCount].State THEN
glbEvents[iCount].TimeM := T#0S;
END_IF;
(* if more than a second make impuls on Q *)
IF (glbEvents[iCount].TimeM > T#0S) AND ((TIME() - glbEvents[iCount].TimeM) >= T#1S) THEN
Q := TRUE;
glbEvents[iCount].TimeM := T#0S;
END_IF;
END_FOR;
END_FUNCTION_BLOCK
PROGRAM PLC_PRG
VAR
fbeventProcess: ProcessEvents; (* function block *)
END_VAR
fbeventProcess();
IF fbeventProcess.Q THEN
// Alarm happened
END_IF;
END_PROGRAM
你可以把计时器和布尔放在一个数组中,然后在上面循环。你可以把计时器和布尔放在一个数组中,然后在上面循环。