如何使用结构化文本在代码中的函数中添加计时器?

问题描述 投票:0回答:1

我在Codesys V3.5 SP9 Patch 5中遇到了结构化文本的问题。我想要做的是能够在我创建的函数中使用计时器,这在POU中调用。我通过将计时器直接放入POU而不使用功能完成了同样的工作。

我的功能声明:

FUNCTION AssignDOORStatus : USINT
VAR_INPUT

    DDUC_ComSta_Dcux_x: BOOL; //No communication
    DDUC_DCUxEmHdler_x: BOOL; //Emergency handler

END_VAR
VAR

    Timer: TP; //Timer to do intermittence between current doors status and emergency handler
    CurrentDoorStatus: USINT;
    TONProcessTime: TIME := T#1S; //TONProcesTime

END_VAR

我的功能代码:

IF DDUC_ComSta_Dcux_x THEN

    CurrentDoorStatus := 0;

ELSE

    CurrentDoorStatus := 1; 

END_IF


IF DDUC_DCUxEmHdler_x THEN

    Timer(IN := NOT Timer.Q, PT := TONProcessTime); //Timer starts
    Timer();

    IF Timer.Q THEN //When TONProcessTime has gone by

        IF AssignDOORStatus <> CurrentDoorStatus THEN

            AssignDOORStatus := CurrentDoorStatus;

        ELSE AssignDOORStatus := 10;

        END_IF

    END_IF

ELSE

    AssignDOORStatus := CurrentDoorStatus;

END_IF

我的代码在POU主要:

testdoor := AssignDOORStatus(DDUC_ComSta_Dcu1_S1_T,DDUC_DCU1EmHdler_S1_T);

此代码用于根据变量“DDUC_ComSta_Dcux_x”分配给“AssignDOORStatus”0或1,然后,当“DDUC_DCUxEmHdler_x”为真时,它使用定时器将“AssignDOORStatus”值从“0或1”翻转为10。

我必须多次调用POU这个函数。

提前致谢!

function timer codesys structured-text
1个回答
4
投票

功能没有记忆。因此,在VAR中声明的所有变量都是临时的,并且会为每个新调用重置为其默认值。

FunctionBlocks / Programs有内存。因此,VAR中声明的所有变量在每次调用之间都保持其值。

这就是为什么你不应该使用一个函数,它将忘记MAIN每次调用之间的所有事情。例如,计时器将从之前的呼叫重置。

相反,你应该编写一个功能块(或FB),它可以重复用于你想要处理的几个门。功能块内部将是一组变量(尤其是计时器),这些变量对于每个实例都是唯一的,并且还可以从调用到被调用来记住。

以上是一个非常简短的描述,因此您应该在编译器帮助文件中查找功能块以获得正确的解释,例如:用于输入/输出参数。 以下是我对一个程序的建议,该程序对三个不同的门实例使用相同的FB:

(The FB, first the declaration and then it's code)
FUNCTION_BLOCK FB_AssignDOORStatus
VAR_INPUT
    DDUC_ComSta_Dcux_x: BOOL; //No communication
    DDUC_DCUxEmHdler_x: BOOL; //Emergency handler
END_VAR
VAR_OUTPUT  
    AssignDoorStatus: USINT;    
END_VAR
VAR
    Timer: TP; //Timer to do intermittence between current doors status and emergency handler
    CurrentDoorStatus: USINT;
    TONProcessTime: TIME := T#1S; //TONProcesTime
END_VAR
----------
IF DDUC_ComSta_Dcux_x THEN
    CurrentDoorStatus := 0;
ELSE
    CurrentDoorStatus := 1; 
END_IF

IF DDUC_DCUxEmHdler_x THEN
    Timer(IN := NOT Timer.Q, PT := TONProcessTime); //Timer starts
    Timer();

    IF Timer.Q THEN //When TONProcessTime has gone by
        IF AssignDOORStatus <> CurrentDoorStatus THEN
            AssignDOORStatus := CurrentDoorStatus;
        ELSE
            AssignDOORStatus := 10;
        END_IF
    END_IF
ELSE
    AssignDOORStatus := CurrentDoorStatus;
END_IF

(MAIN, first the declaration and then it's code)
PROGRAM MAIN
VAR
    // You must make an instance of your function block(s). This instance will live from call to call. 
    fbAssignDOORStatus_1: FB_AssignDOORStatus;
    fbAssignDOORStatus_2: FB_AssignDOORStatus;
    fbAssignDOORStatus_3: FB_AssignDOORStatus;
    // ...
    // Better to use an array to hold the many FB instances needed...
    // You could use a for loop in the MAIN program to call all the instances.

    // Test variables to hand to the fb's during runtime.
    ComSta: BOOL;
    EmHdler: BOOL;
    TestDoor1, TestDoor2, TestDoor3: USINT;
    // Here you could also use an array or re-use some common variable... 
END_VAR
----------
fbAssignDOORStatus_1(
    DDUC_ComSta_Dcux_x := ComSta,
    DDUC_DCUxEmHdler_x := FALSE,
    AssignDoorStatus => TestDoor1);

fbAssignDOORStatus_2(
    DDUC_ComSta_Dcux_x := TRUE,
    DDUC_DCUxEmHdler_x := EmHdler,
    AssignDoorStatus => TestDoor2);

fbAssignDOORStatus_3(
    DDUC_ComSta_Dcux_x := ComSta,
    DDUC_DCUxEmHdler_x := EmHdler,
    AssignDoorStatus => TestDoor3);
© www.soinside.com 2019 - 2024. All rights reserved.