定时轮询PLC程序,纯SCL编写。 已经封装成FB,方便多次调用。 适用于风机水泵阀门等轮询切换启动。 程序结构简单,可灵活调整成更多数量的轮询切换。

先甩个代码骨架:

FUNCTION_BLOCK FB_PollingControl
VAR_INPUT
    Enable: Bool; // 总使能
    PollingTime: TIME := T#5S; // 轮询间隔
    DeviceCount: INT := 3; // 设备数量
END_VAR
VAR_OUTPUT
    ActiveIndex: INT; // 当前激活设备索引
END_VAR
VAR
    Timer: TON;
    CurrentDevice: INT := 0;
    CycleCounter: INT := 0;
END_VAR

核心逻辑其实就个带刹车的老司机循环。定时器到点就切下个设备,注意这里用模运算实现环形计数:

IF Enable THEN
    Timer(IN:=NOT Timer.Q, PT:=PollingTime);
    
    IF Timer.Q THEN
        CurrentDevice := (CurrentDevice + 1) MOD DeviceCount;
        CycleCounter := CycleCounter + (CurrentDevice / DeviceCount);
        Timer(IN:=FALSE);
    END_IF;
    
    ActiveIndex := CurrentDevice;
ELSE
    Timer(IN:=FALSE);
    CurrentDevice := 0;
END_IF

重点说下这个MOD运算——当CurrentDevice自增到DeviceCount时,取模会自动归零,形成0→1→2→0的循环。实际项目中给水泵组用这个逻辑,八个泵轮流切愣是没出过岔子。

定时轮询PLC程序,纯SCL编写。 已经封装成FB,方便多次调用。 适用于风机水泵阀门等轮询切换启动。 程序结构简单,可灵活调整成更多数量的轮询切换。

调用示例更简单:

// OB1中调用
#Polling_Fans := (Enable:=true, PollingTime:=T#30S, DeviceCount:=5);

想改轮询策略?比如设备3需要双倍时长,直接改定时器参数就行:

IF ActiveIndex = 3 THEN
    Timer.PT := T#10S;  // 特殊设备延长到10秒
ELSE
    Timer.PT := PollingTime; // 其他设备保持原时长
END_IF

实测中发现个坑:DeviceCount设为0会导致模运算异常,最好在初始化时加个保护:

IF DeviceCount <= 0 THEN
    DeviceCount := 1;
END_IF;

这个FB最大的优势是内存占用固定,不像用数组实现的那样吃资源。最近做的空压机集群项目,20台设备轮询,扫描周期也就多了0.2ms。下次碰到需要错峰启动的场景,不妨把这货拖出来试试,改改参数直接能用。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐