梯形图计数器CNTR复位条件竞争导致的计数值跳变消除

发布于 2026-03-17 06:47:38 · 浏览 5 次 · 评论 0 条

梯形图编程中,CNTR(计数器)指令的复位条件若与计数输入存在时序重叠,极易引发复位信号与计数脉冲在同一个扫描周期内同时有效,造成计数值跳变——例如本应从 99 → 0 的正常复位,却偶然出现 99 → 100 → 099 → 0 → 1 等异常跃变。该现象本质是复位条件竞争(Reset Race Condition),在PLC扫描机制下无法通过单纯增加延时或调整触点顺序彻底规避。以下为可直接落地、无需修改硬件、不依赖特定品牌PLC的通用消除方案。


一、先确认你是否真的遇到了复位条件竞争

不是所有计数值“跳变”都源于此。请按顺序执行以下诊断步骤:

  1. 启用PLC在线监控,将 CNTR 指令的当前值寄存器(如 CNTR.V)、复位线圈(如 CNTR.R 对应的软元件)、计数输入触点(如 I0.1)全部加入变量表,并设置采样周期 ≤ 10 ms(远小于PLC扫描周期,确保捕获单个扫描内的状态变化)。

  2. 触发一次计数过程,观察连续3~5次复位动作发生时的时序快照。重点关注以下三组信号在同一PLC扫描周期内的逻辑电平组合:

    • 计数输入触点 XON(上升沿或持续ON均可能触发计数)
    • 复位线圈 RON
    • 当前计数值 V:是否等于预设值 PV(即复位阈值)
  3. 若发现任一扫描周期内同时满足:

    • X == ON
    • R == ON
    • V == PV

    100%确认存在复位条件竞争。此时PLC在该扫描周期内会先执行计数(V = V + 1),再执行复位(V = 0),但因内部执行顺序不可控或受优化影响,部分PLC可能先清零再加1,导致 V 在一个扫描内经历两次变更。

✅ 正确理解:这不是PLC“故障”,而是梯形图逻辑在扫描周期边界处的确定性行为缺陷。IEC 61131-3标准未规定同一网络中多个输出线圈的执行先后顺序,厂商实现各异,故必须通过逻辑重构规避。


二、根本解决原理:分离“判断”与“动作”,用双锁存机制切断竞争路径

核心思想:绝不允许复位信号 R 和计数输入 X 在同一逻辑网络中直接驱动同一计数器。需将“是否达到复位条件”的判断,与“何时执行复位”的动作,在时间上强制错开至少一个扫描周期。

具体拆解为两个独立环节:

  • 环节A(条件锁存):在计数值 V 首次等于 PV 的扫描周期,仅置位一个专用锁存标志 M_RST_TRIG,且该标志一旦置位,必须保持至复位完成。
  • 环节B(动作执行):在 M_RST_TRIG == ON 的下一个扫描周期,才真正激活 CNTR.R;并在 CNTR.R 执行后,立即清除 M_RST_TRIG

这样,XR 永远不会在同一扫描中同时为 ON——因为 R 的激活严格滞后于 V == PV 的判定。


三、四步实操:手把手搭建抗竞争计数器网络

以下以通用梯形图符号描述(适配西门子S7-1200/1500、三菱FX5U、欧姆龙NJ/NX系列等主流PLC)。所有元件名使用标准标识,括号内注明典型地址示例。

步骤1:声明必要软元件(全局DB或M区)

元件类型 名称 地址示例 说明
INT CNTR_PV DB1.DBW2 预设值(如100)
INT CNTR_V DB1.DBW4 当前值(CNTR指令自动更新)
BOOL CNT_INPUT I0.1 计数脉冲输入(建议接上升沿触点)
BOOL M_RST_TRIG M10.0 复位触发锁存标志(关键!)
BOOL M_RST_EXEC M10.1 复位执行标志(单周期脉冲)

⚠️ 注意:CNT_INPUT 必须使用硬件滤波后的上升沿检测(如 P_TRIG 功能块),禁止直接用常开触点。否则机械抖动或噪声会伪造多个计数脉冲,掩盖真实问题。

步骤2:构建“条件锁存”网络(独立梯级)

|----[ CNT_INPUT ]-------------------( SET )----[ M_RST_TRIG ]
|                                     |
|----[ CNTR_V == CNTR_PV ]-----------|
  • 解释:当 CNT_INPUTON CNTR_V 等于 CNTR_PV 时,SET 线圈激活,M_RST_TRIG 置位并自锁(梯形图中 SET 具备锁存特性)。
  • 关键设计:此处 CNT_INPUT 触点必须与 CNTR_V == CNTR_PV 串联。这意味着只有在脉冲到来的同一扫描内恰好 V 达到 PV,才会触发锁存。这正是我们要捕获的“临界点”。

步骤3:构建“动作执行”网络(下一梯级,严格隔离)

|----[ M_RST_TRIG ]--------------------( R )----[ M_RST_EXEC ]
|                                                 |
|----[ NOT M_RST_EXEC ]-------------------------( SET )----[ CNTR.R ]
  • 解释
    • 第一行:M_RST_TRIGON 时,将 M_RST_EXEC 复位(R 线圈)。注意这是清除操作,目的是让 M_RST_EXEC 在后续扫描中能重新置位。
    • 第二行:M_RST_EXECOFF 时(即上一扫描未执行过复位),SET 线圈激活 CNTR.R
    • 效果:CNTR.R 仅在 M_RST_TRIGON第二个扫描周期被激活,且只维持一个扫描周期(因下一扫描 M_RST_EXEC 变为 ON,第二行条件失效)。

步骤4:重构原始CNTR指令(关键!)

原始写法(❌ 危险):

|----[ CNT_INPUT ]----[ CNTR_PV ]----( CNTR )

改为(✅ 安全):

|----[ CNT_INPUT ]----[ NOT M_RST_TRIG ]----( CNTR )
  • 解释:在 M_RST_TRIGON(即已判定需复位)后,立即禁止后续计数。这防止在 M_RST_TRIG == ONCNTR.R == ON 的一个扫描延迟期内,新的脉冲再次进入计数器,导致 V 超调(如 100 → 101)。
  • 同时,CNTR.R 线圈由步骤3独立控制,不再与 CNT_INPUT 共存于同一网络。

四、验证效果:用三组数据对比说明

假设 CNTR_PV = 3,输入脉冲序列为 ON, ON, ON, ON(第4个脉冲应触发复位):

扫描周期 CNT_INPUT CNTR.V(原逻辑) CNTR.V(新逻辑) 关键状态
1 ON 1 1
2 ON 2 2
3 ON 3 3 M_RST_TRIG = ON(步骤2触发)
4 ON 04(跳变!) 3(被禁止计数) CNTR.R = ON(步骤3执行),M_RST_EXEC = ON
5 OFF 0 0 CNTR.R 已完成复位,M_RST_TRIG 被步骤3第二行隐含清除(因 CNTR.R 执行后 CNTR.V=0 ≠ PV,且无新触发)

✅ 结果:新逻辑下,CNTR.V 严格遵循 0→1→2→3→0,无任何中间跳变。第4周期因计数被禁,V 停留在 3;第5周期 R 生效,V 清零。


五、进阶加固:应对多计数器协同与断电保持

场景1:同一设备有多个CNTR需同步复位(如包装机的袋长计数+热封次数)

  • 禁止为每个计数器单独做上述四步——会导致复位时刻微秒级偏移,破坏同步性。
  • 正确做法:共用一套 M_RST_TRIG / M_RST_EXEC 逻辑,但为每个 CNTR 单独添加 NOT M_RST_TRIG 使能条件:
    |----[ CNT_INPUT_1 ]----[ NOT M_RST_TRIG ]----( CNTR_1 )
    |----[ CNT_INPUT_2 ]----[ NOT M_RST_TRIG ]----( CNTR_2 )
  • 复位时,所有 CNTR.R 线圈由同一 M_RST_EXEC 控制,确保原子性。

场景2:计数值需断电保持(如累计运行小时)

  • CNTR.V 存储到带保持属性的DB块(如S7的DBx.DBW4设为Retentive),但绝对不可对 M_RST_TRIGM_RST_EXEC 做保持
  • 理由:断电重启后,若 M_RST_TRIG 仍为 ON,将立即触发复位,丢失已计数值。
  • 解决方案:在启动组织块(OB100)中插入初始化网络:
    |----[ SM0.1 ]----( R )----[ M_RST_TRIG ]
                        |
                        +----( R )----[ M_RST_EXEC ]

    SM0.1 是CPU上电第一个扫描周期为 ON 的特殊标志位,确保每次上电后锁存标志清零。


六、为什么不用定时器延时?——揭露常见误区

工程师常尝试如下方案(❌ 无效):

|----[ CNTR.V == PV ]----( TON )----[ T1.Q ]----( CNTR.R )

其中 T1 设定时间为 100 ms

失败原因

  • TON 定时器本身也受扫描周期影响,其 Q 输出并非精确 100 ms,而是 100 ms ± 1个扫描周期
  • 更致命的是:若 CNTR.V == PV 持续多个扫描周期(如因输入触点粘连),TON 会反复启停,Q 输出抖动;
  • 根本未解决 CNT_INPUTCNTR.R 的同周期冲突——只要 CNT_INPUTT1.Q == ON 时再次出现,竞争依旧。

结论:延时是“掩耳盗铃”,锁存+错时才是“釜底抽薪”。


七、代码级验证模板(SCL语言,用于自动化测试)

将以下SCL代码放入测试功能块,可批量验证逻辑鲁棒性:

// 输入模拟:按需切换CNT_INPUT电平
IF Sim_Pulse_Count > 0 THEN
    CNT_INPUT := TRUE;
    Sim_Pulse_Count := Sim_Pulse_Count - 1;
ELSE
    CNT_INPUT := FALSE;
END_IF;

// 核心逻辑(与梯形图完全等效)
IF CNT_INPUT AND (CNTR_V = CNTR_PV) THEN
    M_RST_TRIG := TRUE;
END_IF;

IF M_RST_TRIG THEN
    IF NOT M_RST_EXEC THEN
        CNTR_R := TRUE; // 触发复位
        M_RST_EXEC := TRUE;
    END_IF;
ELSE
    CNTR_R := FALSE;
    M_RST_EXEC := FALSE;
END_IF;

// 计数使能:仅在未触发复位时允许
IF CNT_INPUT AND NOT M_RST_TRIG THEN
    CNTR_V := CNTR_V + 1;
END_IF;

// 复位动作(在CNTR_R为TRUE的扫描周期执行)
IF CNTR_R THEN
    CNTR_V := 0;
END_IF;

运行时注入1000次随机脉冲序列,监控 CNTR_V 最大值。合格标准:最大值恒为 CNTR_PV,且复位后必为 0,无其他值出现。


八、最后检查清单(部署前逐项打钩)

  • [ ] CNT_INPUT 已通过 P_TRIG 或硬件滤波,确认无抖动;
  • [ ] CNTR.VCNTR_PV 数据类型一致(均为 INTDINT),避免比较异常;
  • [ ] M_RST_TRIGM_RST_EXEC 使用非保持型布尔量(勿勾选Retentive);
  • [ ] 所有 CNTR 指令的 R 线圈均由 M_RST_EXEC 统一驱动,无任何直接触点连接;
  • [ ] 在首次上线前,用强制功能将 CNTR.V 设为 CNTR_PV - 1,手动触发一个脉冲,用监控确认 V 是否严格变为 0 且无跳变。

完成以上,即可永久消除CNTR复位跳变。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文