定时轮询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。下次碰到需要错峰启动的场景,不妨把这货拖出来试试,改改参数直接能用。