You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

结构化文本(ST)实现PLC温度数组1分钟定时存储的技术求助

解决ST语言中每隔1分钟存储温度到数组的问题

首先得明确:PLC的程序是循环扫描执行的,你原来写的FOR循环会在一个扫描周期里直接跑完所有6次赋值,根本不会有延迟。而且直接在循环里加阻塞延迟(比如DELAY指令)会导致整个PLC程序卡住,完全不可行。咱们得用非阻塞式定时+索引递增的思路来实现,下面给你两种实用方案:

方案一:全局变量跟踪索引+定时器状态(通用型)

这种方式几乎所有支持ST的PLC都能实现,逻辑清晰好调试:

  1. 先定义几个全局变量(如果是结构化编程,也可以放在功能块FB的内部变量里):

    VAR_GLOBAL
        Temp: ARRAY[0..5] OF REAL; // 存储温度的目标数组
        CurrentIndex: INT := 0;    // 当前要写入的数组索引,初始从0开始
        MinuteTimer: TON;          // IEC标准的通电延时定时器(TON)
        DoneFlag: BOOL := FALSE;   // 标记定时器触发是否已处理,避免重复执行
    END_VAR
    
  2. 主程序里的核心逻辑:

    // 启动定时器:定时器未触发时,一直保持输入为TRUE,到1分钟后Q输出为TRUE
    MinuteTimer(IN := NOT MinuteTimer.Q, PT := T#1M);
    
    // 当定时器首次触发(Q从FALSE跳TRUE)时,执行存储操作
    IF MinuteTimer.Q AND NOT DoneFlag THEN
        Temp[CurrentIndex] := tempsensor; // 把当前传感器值写入数组对应位置
        DoneFlag := TRUE; // 标记已处理这次触发,防止同一扫描周期重复执行
        
        // 索引递增,到数组上限后重置(如果需要循环覆盖旧数据的话)
        CurrentIndex := CurrentIndex + 1;
        IF CurrentIndex > 5 THEN
            CurrentIndex := 0;
        END_IF;
    END_IF;
    
    // 定时器复位时(Q变回FALSE),清空标记,准备下一次触发
    IF NOT MinuteTimer.Q THEN
        DoneFlag := FALSE;
    END_IF;
    

方案二:上升沿检测+取模循环索引(简化版)

如果你的PLC支持R_TRIG(上升沿检测功能块),可以简化逻辑,少用一个标记变量:

VAR_GLOBAL
    Temp: ARRAY[0..5] OF REAL;
    CurrentIndex: INT := 0;
    MinuteTimer: TON;
    TimerRise: R_TRIG; // 上升沿检测功能块
END_VAR

// 启动定时器并检测上升沿
MinuteTimer(IN := TRUE, PT := T#1M);
TimerRise(CLK := MinuteTimer.Q);

// 上升沿触发时执行存储+索引更新
IF TimerRise.Q THEN
    Temp[CurrentIndex] := tempsensor;
    CurrentIndex := (CurrentIndex + 1) MOD 6; // 用取模运算自动循环索引(0-5)
    MinuteTimer.IN := FALSE; // 若你的TON需要手动复位,这里加一行复位,下一个扫描周期再设回TRUE即可
END_IF;

关键注意事项

  • 绝对禁用阻塞延迟:比如DELAY T#1M这种指令会让PLC的扫描周期变成1分钟,其他控制逻辑完全瘫痪,工业现场绝对不能这么做。
  • 匹配定时器时基:不同PLC的定时器时基可能不同(比如1ms、10ms、1s),设置PT值要对应——比如1ms时基设60000,1s时基设60。
  • 数组边界检查:一定要保证CurrentIndex不会超出数组的0-5范围,避免触发数组越界错误。

内容的提问来源于stack exchange,提问作者Mazdak Khan

火山引擎 最新活动