数字量输入防抖是电气自动化系统中保障控制可靠性最基础、却最容易被忽视的关键环节。按钮按下、限位开关触发、光电传感器通断——这些看似简单的“0/1”信号,在真实工业现场几乎必然伴随毫秒级的机械抖动(contact bounce)或电气干扰(electrical noise),导致PLC或控制器误读为多次动作,引发设备误启停、计数错误、安全逻辑失效等严重后果。
防抖不是“加个延时就行”,而是需根据信号特性、响应要求和硬件资源,选择匹配的逻辑策略。以下分三类典型方案展开:软件定时器防抖(最通用)、边沿+计数防抖(高抗扰)、硬件+软件协同防抖(工业级可靠)。所有方法均基于标准IEC 61131-3编程模型(以ST语言为主),适用于主流PLC(如西门子S7-1200/1500、三菱FX/Q系列、欧姆龙NJ/NX系列)及嵌入式控制器(如树莓派+PLC库、ESP32+FreeRTOS)。
一、理解抖动本质:为什么“按下一次”会变成“多个脉冲”
机械式按钮或微动开关在触点闭合/断开瞬间,金属簧片因弹性形变发生反复弹跳,产生持续0.5–20 ms的振荡信号。示波器实测典型波形如下(文字描述):
- 初始稳定高电平(常开按钮未按下)→ 触点首次接触 → 电平开始下跳 → 在低电平区间内出现3–8次快速上下跳变(每次宽约0.3–2 ms)→ 最终稳定低电平(按钮完全按下)
- 松开过程同理:稳定低电平 → 首次分离 → 多次跳变 → 稳定高电平
该抖动不属于故障,而是物理规律。若PLC扫描周期为10 ms,且程序每周期直接读取输入点(%I0.0),则一次按下可能被捕捉到3–5次下降沿,造成 R_TRIG 触发器误动作或计数器多加。
关键结论:防抖目标不是“消除抖动”,而是确保输出状态仅在抖动结束后、输入真正稳定时才改变,且延迟可控(通常≤20 ms可接受)。
二、方案一:定时器防抖(推荐用于90%常规场景)
原理:检测到输入边沿后启动定时器,仅当输入在定时器设定时间内持续保持新状态,才确认有效动作。分为“上升沿防抖”和“下降沿防抖”,以常开按钮(按下为0)的下降沿防抖为例。
步骤说明(ST语言,西门子S7-1200兼容写法)
-
声明变量
VAR btn_raw: BOOL; // 原始输入点,如 %I0.0 btn_debounced: BOOL; // 防抖后输出 t_debounce: TON; // 定时器实例(TON = On-Delay Timer) t_delay_ms: TIME := T#20MS; // 防抖时间,20毫秒(覆盖99%机械抖动) END_VAR -
编写防抖逻辑
// 检测原始信号下降沿(按钮按下) btn_falling := btn_raw AND NOT btn_raw_prev; btn_raw_prev := btn_raw; // 若检测到下降沿,启动定时器;否则复位定时器 IF btn_falling THEN t_debounce(IN := TRUE, PT := t_delay_ms); ELSE t_debounce(IN := FALSE); END_IF; // 定时器完成且原始信号仍为低电平,则确认有效按下 btn_debounced := t_debounce.Q AND btn_raw; -
使用要点
-
t_delay_ms取值原则:≥ 最长抖动持续时间,且 < 允许的最大响应延迟。
实测数据参考:
| 开关类型 | 典型抖动时间范围 | 推荐防抖时间 |
|----------------|------------------|--------------|
| 薄膜按键 | 1–5 ms |T#5MS|
| 工业按钮(带弹簧)| 5–15 ms |T#20MS|
| 微动限位开关 | 10–30 ms |T#40MS|
| 接近开关(电磁干扰强)| 无固定抖动,但有噪声脉冲 |T#50MS(需结合滤波)| -
严禁将
t_debounce.Q直接作为输出:因为定时器完成时,原始信号可能已反弹回高电平(松开瞬间抖动),必须用AND btn_raw锁定最终状态。 -
多按钮复用:每个按钮需独立定时器实例(
t_debounce_1,t_debounce_2),不可共用同一TON块。
-
三、方案二:边沿+计数防抖(适用于高干扰、低功耗或无定时器资源场景)
原理:不依赖时间基准,而是统计连续采样周期内输入状态一致的次数。当连续N次采样均为目标电平(如低电平),即判定为有效;任意一次不一致则清零计数。适合扫描周期稳定且较短(≤2 ms)的系统。
步骤说明(ST语言)
-
声明变量
VAR btn_raw: BOOL; btn_debounced: BOOL; cnt_stable: INT := 0; // 稳定计数器 cnt_threshold: INT := 10; // 连续采样次数阈值(对应20ms@2ms周期) scan_period_ms: TIME := T#2MS; // PLC扫描周期(需实测或查手册) END_VAR -
编写计数防抖逻辑
// 每扫描周期执行 IF btn_raw = FALSE THEN // 检测到低电平(按下) cnt_stable := cnt_stable + 1; IF cnt_stable >= cnt_threshold THEN btn_debounced := TRUE; END_IF; ELSE // 检测到高电平(释放或抖动) cnt_stable := 0; btn_debounced := FALSE; END_IF; -
参数计算与校准
cnt_threshold = ROUND(t_debounce_ms / scan_period_ms)
例:要求20 ms防抖,扫描周期为2 ms →cnt_threshold = 10- 优势:完全规避定时器精度误差(如PLC时钟漂移),抗电源波动更强;
- 局限:要求扫描周期高度稳定;若扫描周期大于抖动时间(如50 ms扫描),该方法失效。
四、方案三:硬件+软件协同防抖(工业安全级应用)
单一软件防抖无法应对雷击浪涌、变频器高频干扰等极端工况。必须从源头抑制噪声,再叠加软件验证。
硬件层:三级滤波设计
| 层级 | 元件 | 功能说明 | 典型参数 |
|---|---|---|---|
| 一级 | RC低通滤波 | 抑制高频噪声(>100 kHz),防止干扰触发输入光耦 | R=10 kΩ, C=100 nF → 截止≈160 Hz |
| 二级 | TVS二极管(双向) | 泄放瞬态高压(ESD、浪涌),钳位电压至安全范围(如5 V) | SMAJ5.0A(5 V钳位) |
| 三级 | 光电隔离(高速光耦) | 物理隔离现场侧与PLC侧,阻断共模干扰;选型要求传输延迟<0.5 μs,CTR>50% | TLP2362、ACPL-K370 |
注:RC滤波时间常数
τ = R × C必须 小于 软件防抖时间(如20 ms),否则硬件滤波本身引入过大延迟,失去意义。
软件层:双校验机制
在定时器防抖基础上,增加“历史状态一致性”校验:
VAR
btn_raw: BOOL;
btn_last_valid: BOOL := FALSE; // 上次确认有效的状态
btn_debounced: BOOL;
t_main: TON; // 主防抖定时器(20 ms)
t_verify: TON; // 二次验证定时器(100 ms)
END_VAR
// 主防抖逻辑(同方案一)
IF btn_raw AND NOT btn_raw_prev THEN
t_main(IN := TRUE, PT := T#20MS);
ELSE
t_main(IN := FALSE);
END_IF;
btn_main_ok := t_main.Q AND btn_raw;
// 二次验证:主防抖输出需持续100 ms稳定,才最终输出
IF btn_main_ok <> btn_last_valid THEN
t_verify(IN := TRUE, PT := T#100MS); // 状态变化时启动验证
ELSE
t_verify(IN := FALSE);
END_IF;
IF t_verify.Q THEN
btn_debounced := btn_main_ok;
btn_last_valid := btn_main_ok;
END_IF;
此结构确保:
- 短时干扰(<20 ms)被主定时器过滤;
- 中期波动(20–100 ms)被二次验证拦截;
- 仅当信号连续100 ms稳定,才更新输出——彻底杜绝误动作,代价是最大延迟120 ms,适用于非实时安全回路(如报警确认、批量计数)。
五、避坑指南:6个高频错误及修正
| 错误现象 | 根本原因 | 正确做法 |
|---|---|---|
| 防抖后按钮响应明显变慢 | t_delay_ms 设为100 ms以上 |
严格按开关实测抖动时间设值,优先≤20 ms |
| 松开按钮时输出滞后 | 仅对下降沿防抖,未处理上升沿 | 必须为“按下”和“释放”分别配置两套防抖逻辑 |
| 多个按钮互相干扰 | 共用同一定时器实例或计数器变量 | 每个输入点独占变量,命名明确(btn1_q, btn2_q) |
| 断电重启后状态丢失 | 未对 btn_debounced 加 RETAIN |
在变量声明中添加 RETAIN 关键字(S7系列) |
| 防抖失效(仍误触发) | 输入点未启用PLC内置硬件滤波 | 在硬件组态中启用输入滤波(如S7-1200:属性→常规→输入滤波,设2.5 ms) |
| 通讯中断时输出异常 | 防抖逻辑依赖网络IO(如分布式I/O) | 所有防抖必须在本地CPU模块执行,禁用远程站直接输入 |
六、实战验证方法(无需示波器)
现场无专业仪器时,用以下三步法闭环验证:
-
计数器自检法
将防抖输出接入PLC内部计数器(CTU),手动按按钮10次,观察计数值是否精确为10。若>10,存在漏防抖;若<10,存在过度滤波(阈值过大)。 -
LED反馈法
用LED指示灯连接防抖输出点:- 正常操作:按住按钮不放 → LED亮起后不再闪烁;松开 → LED熄灭后不再闪烁;
- 失效表现:LED在按/松过程中出现2次以上明暗变化。
-
日志抓取法(支持Web服务器的PLC)
编写简易日志程序,记录每次原始信号跳变与防抖输出时间戳:IF btn_raw <> btn_raw_prev THEN LogEntry('RAW', TIME_OF_DAY(), btn_raw); btn_raw_prev := btn_raw; END_IF; IF btn_debounced <> btn_debounced_prev THEN LogEntry('DEBOUNCE', TIME_OF_DAY(), btn_debounced); btn_debounced_prev := btn_debounced; END_IF;下载CSV日志,用Excel查看时间差,确认防抖延迟是否符合设定。
七、选型决策树:根据场景快速匹配方案
| 场景特征 | 推荐方案 | 理由 |
|---|---|---|
| 普通人机界面按钮、指示灯控制 | 定时器防抖 | 实现简单、资源占用低、延迟可控 |
| 电池供电传感器(如IoT节点) | 边沿+计数防抖 | 无需定时器外设,降低MCU唤醒频率 |
| 安全继电器输入、急停回路 | 硬件+软件协同防抖 | 满足ISO 13849-1 Cat.3/PL e要求,双重冗余 |
| 高速包装机(周期<10 ms) | 硬件RC滤波 + 计数防抖 | 避免定时器累积误差,计数阈值按实际扫描周期精确计算 |
| 老旧PLC(无TON指令,仅有线圈/触点) | 计数防抖(梯形图实现) | 用辅助继电器+计数器构成“稳定锁存”,如 X0接通10次→M10置位 |
| 存在强变频干扰的产线 | 硬件TVS+光耦 + 定时器 | 从物理层切断干扰路径,软件层做最终确认 |
防抖逻辑的本质,是用确定性的时间或次数规则,驯服物理世界的不确定性。它不创造新功能,却是一切自动化动作可信的起点。每一次准确的启停、每一笔无误的计数、每一个及时的安全响应,背后都是这毫秒级的耐心等待。

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