CODESYS 边缘检测问题(反弹)
CODESYS problems with edge detection (bounce)
我的 CODESYS 程序有问题。我有三个按钮,它们被定义为输入。为每个按钮存储一个数字。例如数字 1。
我现在创建了一个程序,它可以识别按钮上的边缘并将按钮的数值 (2) 存储在一个数组中。如果您现在按下另一个带有值 (3) 的按钮,该值也会再次存储在变量中。这两个变量应该加在一起。 2 + 3 = 23。在我的程序中,如果我按下值为 2 的按钮测试器,我会得到 22。这是错误的。我认为问题是由于按钮的瘀伤引起的。检测到多个边缘。所以想从技术上拖延解决这个软件。你知道我该如何编程吗?
代码:
IF (PLC_PRG.calls[5].gpio = TRUE) THEN // edge detection on gpio
IF (counter = 0) THEN // counter for the first value
floorstorage2[0] := PLC_PRG.calls[5].message.floorstore[5]; // save button value in the array to calculate the total
counter := 1;
ELSE
floorstorage2[1] := PLC_PRG.calls[5].message.floorstore[5]; // save button value in the array to calculate the total
counter := 0;
END_IF
END_IF
IF (PLC_PRG.calls[6].gpio = TRUE) THEN // edge detection on gpio
IF (counter = 0) THEN // counter for the first value
floorstorage2[0] := PLC_PRG.calls[6].message.floorstore[6]; // save button value in the array to calculate the total
counter := 1;
ELSE
floorstorage2[1] := PLC_PRG.calls[6].message.floorstore[6]; // save button value in the array to calculate the total
counter := 0;
END_IF
END_IF
IF (PLC_PRG.calls[7].gpio = TRUE) THEN // edge detection on gpio
IF (counter = 0) THEN // counter for the first value
floorstorage2[0] := PLC_PRG.calls[7].message.floorstore[7]; // save button value in the array to calculate the total
counter := 1;
ELSE
floorstorage2[1] := PLC_PRG.calls[7].message.floorstore[7]; // save button value in the array to calculate the total
counter := 0;
END_IF
END_IF
GlobalVar.floorstorage := concat(floorstorage2[0],floorstorage2[1]); // Total of value 1 and value 2 (1 + 2 = 12)
我会以更面向对象的方式实现整个逻辑。
首先,我们定义一个Button。
声明部分:
FUNCTION_BLOCK FB_Button
VAR
bSignal AT%I* : BOOL;
IButtonHandler : I_ButtonHandler;
fbPushTimer : TON;
fbTrig : R_TRIG;
sValue : STRING;
END_VAR
实现部分:
IF IButtonHandler = 0
THEN
RETURN;
END_IF
fbPushTimer(IN:= bSignal, PT:=T#50MS);
fbTrig(CLK:=fbPushTimer.Q);
IF fbTrig.Q
THEN
IButtonHandler.onPush(sValue);
END_IF
该按钮有四个属性:
第一 属性:
声明部分:
PROPERTY getValue : String
实现部分:
getValue := sValue;
第二 属性:
声明部分:
PROPERTY isPushed : BOOL
实现部分:
isPushed := bSignal;
第 3 属性:
声明部分:
PROPERTY setPushHandler : I_ButtonHandler
实现部分:
IButtonHandler := setPushHandler;
第 4 属性:
声明部分:
PROPERTY setValue : String
实现部分:
sValue := setValue;
然后我们定义接口。
INTERFACE I_ButtonHandler
并添加接口方法:
METHOD onPush
VAR_INPUT
sValue : STRING;
END_VAR
最后我们定义了处理程序。
声明部分:
FUNCTION_BLOCK FB_ButtonHandler IMPLEMENTS I_ButtonHandler
VAR_OUTPUT
floorstorage : STRING;
END_VAR
处理程序有两个方法:
第一种方法:
声明部分:
METHOD onPush
VAR_INPUT
sValue : STRING;
END_VAR
实现部分:
floorstorage := concat(floorstorage,sValue);
第二种方法:
声明部分:
METHOD reset
实现部分:
floorstorage := '';
现在我们需要初始化按钮并在 main 中调用它们。
主要声明部分:
PROGRAM MAIN
VAR
aButtons : ARRAY[1..10] OF FB_Button;
fbButtonHandler : FB_ButtonHandler;
i : UINT;
bInit : BOOL;
END_VAR
实现部分:
IF NOT bInit
THEN
FOR i := 1 TO 10 DO
aButtons[i].setPushHandler := fbButtonHandler;
aButtons[i].setValue := UINT_TO_STRING(i);
END_FOR
bInit := TRUE;
END_IF
FOR i := 1 TO 10 DO
aButtons[i]();
END_FOR
您可以根据按钮选择自己的按钮值。
为简单起见,我将循环索引指定为按钮的值。
每次按下按钮时,onPush 方法只会在 50 毫秒后调用一次。
当您想访问 floorstorage 的值时,您只需调用 fbButtonHandler.floorstorage 将其分配给另一个变量。
这样做比将其声明为 global.
可以为您的变量提供更强大的封装和数据保护
我在这里没有看到任何边缘检测
IF (PLC_PRG.calls[5].gpio = TRUE) THEN // edge detection on gpio
IF (counter = 0) THEN // counter for the first value
floorstorage2[0] := PLC_PRG.calls[5].message.floorstore[5]; // save button value in the array to calculate the total
counter := 1;
ELSE
floorstorage2[1] := PLC_PRG.calls[5].message.floorstore[5]; // save button value in the array to calculate the total
counter := 0;
END_IF
END_IF
你检查按钮是否被按下。这意味着当您按住此按钮时,此条件为真。这意味着当您按住按钮时,counter
会在每个 PLC 循环中更改其状态。这意味着如果当您释放按钮时 PLC 进行了偶数次循环,则什么都不会改变,如果是奇数次 f 循环,它将发生变化。以下是检测上升沿的方法。
VAR
xSignal, xSignalM: BOOL;
END_VAR
IF xSignal AND NOT xSignalM THEN
// Raising edge is here
END_IF
xSignalM := xSignal;
这样的条件只会在一个PLC周期起作用,一切都会好起来的。所以你的代码看起来像这样。
VAR
M1, M1, M3: BOOL;
END_VAR
IF (PLC_PRG.calls[5].gpio AND NOT M1) THEN // edge detection on gpio
IF (counter = 0) THEN // counter for the first value
floorstorage2[0] := PLC_PRG.calls[5].message.floorstore[5]; // save button value in the array to calculate the total
counter := 1;
ELSE
floorstorage2[1] := PLC_PRG.calls[5].message.floorstore[5]; // save button value in the array to calculate the total
counter := 0;
END_IF
END_IF
M1 = PLC_PRG.calls[5].gpio;
IF (PLC_PRG.calls[6].gpio AND NOT M2) THEN // edge detection on gpio
IF (counter = 0) THEN // counter for the first value
floorstorage2[0] := PLC_PRG.calls[6].message.floorstore[6]; // save button value in the array to calculate the total
counter := 1;
ELSE
floorstorage2[1] := PLC_PRG.calls[6].message.floorstore[6]; // save button value in the array to calculate the total
counter := 0;
END_IF
END_IF
M2 = PLC_PRG.calls[6].gpio;
IF (PLC_PRG.calls[7].gpio AND NOT M3) THEN // edge detection on gpio
IF (counter = 0) THEN // counter for the first value
floorstorage2[0] := PLC_PRG.calls[7].message.floorstore[7]; // save button value in the array to calculate the total
counter := 1;
ELSE
floorstorage2[1] := PLC_PRG.calls[7].message.floorstore[7]; // save button value in the array to calculate the total
counter := 0;
END_IF
END_IF
M3 = PLC_PRG.calls[7].gpio;
或者您可以使用 R_TRIG
VAR
RT1:R_TRIG;
END_VAR
R1(CLK := PLC_PRG.calls[5].gpio);
IF (R1.Q) THEN
IF (counter = 0) THEN
floorstorage2[0] := PLC_PRG.calls[5].message.floorstore[5];
counter := 1;
ELSE
floorstorage2[1] := PLC_PRG.calls[5].message.floorstore[5];
counter := 0;
END_IF
END_IF
您需要实施边缘检测。这是您可以使用的代码模板:
// Generate Oneshot Signal
VAR_INPUT
SIGNAL : BOOL; // Input
END_VAR
VAR
LATCH_SIGNAL : BOOL; // Latch
END_VAR
VAR_TEMP
OS_P_SIGNAL : BOOL; // Oneshot - Rising edge detection
OS_N_SIGNAL : BOOL; // Oneshot - Falling edge detection
END_VAR
//Code - Rising edge detection
OS_P_SIGNAL := SIGNAL AND NOT LATCH_SIGNAL;
LATCH_SIGNAL := SIGNAL;
//Code - Falling edge detection
OS_N_SIGNAL := NOT SIGNAL AND NOT LATCH_SIGNAL;
LATCH_SIGNAL := NOT SIGNAL;
我的 CODESYS 程序有问题。我有三个按钮,它们被定义为输入。为每个按钮存储一个数字。例如数字 1。 我现在创建了一个程序,它可以识别按钮上的边缘并将按钮的数值 (2) 存储在一个数组中。如果您现在按下另一个带有值 (3) 的按钮,该值也会再次存储在变量中。这两个变量应该加在一起。 2 + 3 = 23。在我的程序中,如果我按下值为 2 的按钮测试器,我会得到 22。这是错误的。我认为问题是由于按钮的瘀伤引起的。检测到多个边缘。所以想从技术上拖延解决这个软件。你知道我该如何编程吗?
代码:
IF (PLC_PRG.calls[5].gpio = TRUE) THEN // edge detection on gpio
IF (counter = 0) THEN // counter for the first value
floorstorage2[0] := PLC_PRG.calls[5].message.floorstore[5]; // save button value in the array to calculate the total
counter := 1;
ELSE
floorstorage2[1] := PLC_PRG.calls[5].message.floorstore[5]; // save button value in the array to calculate the total
counter := 0;
END_IF
END_IF
IF (PLC_PRG.calls[6].gpio = TRUE) THEN // edge detection on gpio
IF (counter = 0) THEN // counter for the first value
floorstorage2[0] := PLC_PRG.calls[6].message.floorstore[6]; // save button value in the array to calculate the total
counter := 1;
ELSE
floorstorage2[1] := PLC_PRG.calls[6].message.floorstore[6]; // save button value in the array to calculate the total
counter := 0;
END_IF
END_IF
IF (PLC_PRG.calls[7].gpio = TRUE) THEN // edge detection on gpio
IF (counter = 0) THEN // counter for the first value
floorstorage2[0] := PLC_PRG.calls[7].message.floorstore[7]; // save button value in the array to calculate the total
counter := 1;
ELSE
floorstorage2[1] := PLC_PRG.calls[7].message.floorstore[7]; // save button value in the array to calculate the total
counter := 0;
END_IF
END_IF
GlobalVar.floorstorage := concat(floorstorage2[0],floorstorage2[1]); // Total of value 1 and value 2 (1 + 2 = 12)
我会以更面向对象的方式实现整个逻辑。
首先,我们定义一个Button。
声明部分:
FUNCTION_BLOCK FB_Button
VAR
bSignal AT%I* : BOOL;
IButtonHandler : I_ButtonHandler;
fbPushTimer : TON;
fbTrig : R_TRIG;
sValue : STRING;
END_VAR
实现部分:
IF IButtonHandler = 0
THEN
RETURN;
END_IF
fbPushTimer(IN:= bSignal, PT:=T#50MS);
fbTrig(CLK:=fbPushTimer.Q);
IF fbTrig.Q
THEN
IButtonHandler.onPush(sValue);
END_IF
该按钮有四个属性:
第一 属性:
声明部分:
PROPERTY getValue : String
实现部分:
getValue := sValue;
第二 属性:
声明部分:
PROPERTY isPushed : BOOL
实现部分:
isPushed := bSignal;
第 3 属性:
声明部分:
PROPERTY setPushHandler : I_ButtonHandler
实现部分:
IButtonHandler := setPushHandler;
第 4 属性:
声明部分:
PROPERTY setValue : String
实现部分:
sValue := setValue;
然后我们定义接口。
INTERFACE I_ButtonHandler
并添加接口方法:
METHOD onPush
VAR_INPUT
sValue : STRING;
END_VAR
最后我们定义了处理程序。
声明部分:
FUNCTION_BLOCK FB_ButtonHandler IMPLEMENTS I_ButtonHandler
VAR_OUTPUT
floorstorage : STRING;
END_VAR
处理程序有两个方法:
第一种方法:
声明部分:
METHOD onPush
VAR_INPUT
sValue : STRING;
END_VAR
实现部分:
floorstorage := concat(floorstorage,sValue);
第二种方法:
声明部分:
METHOD reset
实现部分:
floorstorage := '';
现在我们需要初始化按钮并在 main 中调用它们。
主要声明部分:
PROGRAM MAIN
VAR
aButtons : ARRAY[1..10] OF FB_Button;
fbButtonHandler : FB_ButtonHandler;
i : UINT;
bInit : BOOL;
END_VAR
实现部分:
IF NOT bInit
THEN
FOR i := 1 TO 10 DO
aButtons[i].setPushHandler := fbButtonHandler;
aButtons[i].setValue := UINT_TO_STRING(i);
END_FOR
bInit := TRUE;
END_IF
FOR i := 1 TO 10 DO
aButtons[i]();
END_FOR
您可以根据按钮选择自己的按钮值。
为简单起见,我将循环索引指定为按钮的值。
每次按下按钮时,onPush 方法只会在 50 毫秒后调用一次。
当您想访问 floorstorage 的值时,您只需调用 fbButtonHandler.floorstorage 将其分配给另一个变量。
这样做比将其声明为 global.
可以为您的变量提供更强大的封装和数据保护我在这里没有看到任何边缘检测
IF (PLC_PRG.calls[5].gpio = TRUE) THEN // edge detection on gpio
IF (counter = 0) THEN // counter for the first value
floorstorage2[0] := PLC_PRG.calls[5].message.floorstore[5]; // save button value in the array to calculate the total
counter := 1;
ELSE
floorstorage2[1] := PLC_PRG.calls[5].message.floorstore[5]; // save button value in the array to calculate the total
counter := 0;
END_IF
END_IF
你检查按钮是否被按下。这意味着当您按住此按钮时,此条件为真。这意味着当您按住按钮时,counter
会在每个 PLC 循环中更改其状态。这意味着如果当您释放按钮时 PLC 进行了偶数次循环,则什么都不会改变,如果是奇数次 f 循环,它将发生变化。以下是检测上升沿的方法。
VAR
xSignal, xSignalM: BOOL;
END_VAR
IF xSignal AND NOT xSignalM THEN
// Raising edge is here
END_IF
xSignalM := xSignal;
这样的条件只会在一个PLC周期起作用,一切都会好起来的。所以你的代码看起来像这样。
VAR
M1, M1, M3: BOOL;
END_VAR
IF (PLC_PRG.calls[5].gpio AND NOT M1) THEN // edge detection on gpio
IF (counter = 0) THEN // counter for the first value
floorstorage2[0] := PLC_PRG.calls[5].message.floorstore[5]; // save button value in the array to calculate the total
counter := 1;
ELSE
floorstorage2[1] := PLC_PRG.calls[5].message.floorstore[5]; // save button value in the array to calculate the total
counter := 0;
END_IF
END_IF
M1 = PLC_PRG.calls[5].gpio;
IF (PLC_PRG.calls[6].gpio AND NOT M2) THEN // edge detection on gpio
IF (counter = 0) THEN // counter for the first value
floorstorage2[0] := PLC_PRG.calls[6].message.floorstore[6]; // save button value in the array to calculate the total
counter := 1;
ELSE
floorstorage2[1] := PLC_PRG.calls[6].message.floorstore[6]; // save button value in the array to calculate the total
counter := 0;
END_IF
END_IF
M2 = PLC_PRG.calls[6].gpio;
IF (PLC_PRG.calls[7].gpio AND NOT M3) THEN // edge detection on gpio
IF (counter = 0) THEN // counter for the first value
floorstorage2[0] := PLC_PRG.calls[7].message.floorstore[7]; // save button value in the array to calculate the total
counter := 1;
ELSE
floorstorage2[1] := PLC_PRG.calls[7].message.floorstore[7]; // save button value in the array to calculate the total
counter := 0;
END_IF
END_IF
M3 = PLC_PRG.calls[7].gpio;
或者您可以使用 R_TRIG
VAR
RT1:R_TRIG;
END_VAR
R1(CLK := PLC_PRG.calls[5].gpio);
IF (R1.Q) THEN
IF (counter = 0) THEN
floorstorage2[0] := PLC_PRG.calls[5].message.floorstore[5];
counter := 1;
ELSE
floorstorage2[1] := PLC_PRG.calls[5].message.floorstore[5];
counter := 0;
END_IF
END_IF
您需要实施边缘检测。这是您可以使用的代码模板:
// Generate Oneshot Signal
VAR_INPUT
SIGNAL : BOOL; // Input
END_VAR
VAR
LATCH_SIGNAL : BOOL; // Latch
END_VAR
VAR_TEMP
OS_P_SIGNAL : BOOL; // Oneshot - Rising edge detection
OS_N_SIGNAL : BOOL; // Oneshot - Falling edge detection
END_VAR
//Code - Rising edge detection
OS_P_SIGNAL := SIGNAL AND NOT LATCH_SIGNAL;
LATCH_SIGNAL := SIGNAL;
//Code - Falling edge detection
OS_N_SIGNAL := NOT SIGNAL AND NOT LATCH_SIGNAL;
LATCH_SIGNAL := NOT SIGNAL;