在Codesys梯形图编程中,常遇到“输入信号短暂抖动或扫描周期内持续为ON,导致上升沿(R_TRIG)触发后重复执行动作”的问题。例如,当按钮硬件消抖不良,或传感器信号存在毛刺时,单次按下可能被多个扫描周期识别为多次“上升沿”,造成电机误启、计数器多加、报警重复触发等严重逻辑错误。虽然标准R_TRIG功能块本身具备边沿记忆能力,但若其CLK输入在多个周期内持续为TRUE(如未加滤波的机械开关信号),则仅在首次由FALSE→TRUE跳变时触发Q输出;然而,若信号在未完全稳定前反复波动(如0→1→0→1),仍可能产生多次有效边沿。更隐蔽的问题是:当R_TRIG被放置在条件分支(如FB实例未始终使能)或受使能链影响时,其内部状态可能未被连续更新,导致边沿丢失或误判。如何在梯形图中稳健实现**单次、抗干扰、可复位**的上升沿检测,并确保动作仅执行一次?这是工业现场PLC逻辑可靠性的关键基础。
1条回答 默认 最新
rememberzrr 2026-02-26 23:00关注```html一、现象剖析:为什么标准 R_TRIG 在工业现场“不可靠”?
在 Codesys 梯形图中,
R_TRIG功能块仅检测CLK输入的 单次 FALSE→TRUE 跳变,其内部使用静态布尔变量(如MEM)锁存前一周期状态。但当输入信号存在硬件抖动(如机械按钮 5–20ms 毛刺)、EMI 干扰或长线反射时,原始信号波形可能呈现:周期0: FALSE → 周期1: TRUE → 周期2: FALSE → 周期3: TRUE → 周期4: TRUE
此时,R_TRIG 将在周期1和周期3各触发一次 Q=TRUE——即两次误触发。更严重的是:若该 R_TRIG 被置于 IF 条件分支内(如
IF bEnable THEN R_TRIG(...); END_IF;),当bEnable=FALSE时,功能块不执行,其内部状态停滞,导致边沿丢失或状态不同步。二、根因分层诊断模型
层级 典型诱因 Codesys 表现 影响范围 物理层 按钮触点弹跳、NPN传感器漏电流、未加 RC 滤波 输入映像区(%IX*)连续多周期跳变 全系统基础信号链 执行层 FB 实例未全局使能、R_TRIG 置于 GOTO 跳转后、扫描周期波动 >10ms 功能块静态变量未更新,MEM 状态失准 逻辑分支可靠性坍塌 设计层 未区分“瞬态事件”与“稳态条件”,复位逻辑缺失或异步 Q 输出持续为 TRUE 或无法清除,动作重复执行 安全联锁、计数、报警等关键功能失效 三、工业级抗抖动上升沿方案(梯形图原生实现)
以下为可直接部署于 Codesys ST/LD 的零依赖、可复位、扫描周期鲁棒型上升沿检测结构(LD 描述):
- 对原始信号
IN进行 软件滤波:使用移位寄存器(SR)或计数器实现 ≥3 周期一致确认(推荐 3~5 个扫描周期); - 将滤波后信号
IN_Filtered接入标准R_TRIG的 CLK; - 引入独立复位信号
RESET(上升沿/下降沿/电平均可),通过SR或SET/RESET触发器清零 R_TRIG 内部 MEM; - 将
R_TRIG.Q输出与一个自锁SR(置位由 Q 触发,复位由 RESET 控制)组合,确保动作仅执行一次且可人工干预复位。
四、推荐实现:LD+ST 混合结构(含复位同步机制)
// 自定义抗抖动上升沿 FB(ST 实现,供 LD 调用) FUNCTION_BLOCK F_R_TRIG_DEBOUNCE VAR_INPUT CLK : BOOL; // 原始输入(带抖动) RESET : BOOL; // 复位信号(建议用上升沿触发) TON_MS : TIME := T#20ms; // 滤波时间基准(对应扫描周期倍数) END_VAR VAR_OUTPUT Q : BOOL; END_VAR VAR fbTON : TON; // 定时器实现延时确认 bLast : BOOL; bStable : BOOL; rTrig : R_TRIG; END_VAR // 1. 滤波:CLK 持续为 TRUE ≥ TON_MS 后才认定稳定 fbTON(IN := CLK, PT := TON_MS); bStable := fbTON.Q; // 2. 上升沿检测(作用于稳定信号) rTrig(CLK := bStable); Q := rTrig.Q; // 3. 同步复位:RESET 上升沿清除 rTrig 内部状态 IF RESET AND NOT bLast THEN rTrig.MEM := FALSE; // 强制重置记忆位(需 Codesys V3.5+ 支持显式访问) END_IF; bLast := RESET;五、可视化逻辑流(Mermaid 流程图)
flowchart TD A[原始输入 CLK] --> B{是否持续 TRUE ≥ TON_MS?} B -- 否 --> C[保持 bStable = FALSE] B -- 是 --> D[bStable = TRUE] C & D --> E[R_TRIG CLK = bStable] E --> F{R_TRIG.Q 上升沿?} F -- 是 --> G[输出 Q = TRUE] F -- 否 --> H[Q = FALSE] I[RESET 上升沿] --> J[强制 rTrig.MEM := FALSE] J --> E G --> K[执行一次动作] K --> L[等待 RESET 复位]六、现场部署黄金法则
- 滤波时间选择:机械按钮取 T#15ms~T#30ms;光电开关取 T#2ms~T#5ms;严禁使用固定 1 周期延迟(无法应对扫描波动);
- 复位信号设计:必须为边沿触发(如
F_TRIG(RESET)),避免电平复位导致 Q 锁死; - 实例化约束:F_R_TRIG_DEBOUNCE 必须在主程序循环(如
CyclicTask)中无条件调用,禁止嵌套于 IF/FOR 中; - 诊断增强:为每个关键上升沿添加
TIME类型的LastTriggerTime变量,用于 HMI 显示最近触发时刻,辅助定位抖动源。
七、进阶验证:抖动注入测试模板
在 Codesys Simulation 中构建如下测试环境:
- 创建虚拟输入
%IX0.0,绑定到BOOL类型的TestSignal; - 编写测试 ST 代码,用
FOR i:=0 TO 9 DO TestSignal := (i MOD 2 = 0); Delay(1); END_FOR模拟 0→1→0→1 抖动; - 对比标准 R_TRIG 与 F_R_TRIG_DEBOUNCE 输出波形:前者 Q 出现 5 次脉冲,后者仅 1 次;
- 启用 Codesys Trace 功能,捕获
rTrig.MEM和bStable变量变化曲线,验证滤波有效性。
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报- 对原始信号