0

我的 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)
4

3 回答 3

0

我会以更面向对象的方式实现整个逻辑。

首先,我们定义一个 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;

第三个属性:

声明部分:

PROPERTY setPushHandler : I_ButtonHandler

实现部分:

IButtonHandler := setPushHandler;

第四个属性:

声明部分:

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.js 中调用它们。

主要声明部分:

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将其分配给另一个 var。

通过这样做,您可以对变量进行更强大的封装和数据保护,而不是将其声明为global

于 2020-01-07T21:03:18.997 回答
0

我在这里看不到任何边缘检测

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
于 2020-01-08T06:22:00.157 回答
0

您需要实现边缘检测。这是您可以使用的代码模板:

//  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;
于 2020-01-08T06:42:09.423 回答