1. 从两个挨得极近的脉冲说起:为什么肉眼判定一定会翻车
做嵌入式信号采集、PLC高速计数、或者电源双脉冲测试的朋友,大概率都遇到过这种场景:示波器屏幕上两个脉冲几乎贴在一起,中间只有一小段凹槽。你盯着屏幕看了半天,心里犯嘀咕——这到底是传感器真实输出了两次事件,还是仅仅一次脉冲因为线路寄生参数产生的振铃?如果你凭肉眼拍板,那后面的计数、报警、逻辑判断全都会跟着错。
这个问题在工业现场极其常见。比如信捷PLC的XD3系列做伺服驱动器脉冲信号采集时,编码器输出的差分脉冲经过长线缆传输后,边沿会叠加振铃;再比如HX711这类称重ADC,采样率设在10Hz还是80Hz,直接决定了你能不能分辨出两个紧挨着的重量变化脉冲。还有电源领域的双脉冲测试,用来评估功率器件的开关特性,两个脉冲之间的间隔往往在微秒级,振铃和真实脉冲混在一起,没有一套明确的判定规则根本没法干活。
核心矛盾就一句话:脉冲宽度、间隔时间、振铃衰减时间这三者处在同一量级时,任何基于“看起来像”的判定都是不可靠的。你需要的是两个硬指标——判定窗和恢复时间。判定窗决定“多近的两个边沿才算两次独立事件”,恢复时间决定“一次事件之后要安静多久才能确认它真的结束了”。这两个参数不能拍脑袋定,必须从信号本身的物理特性、采样系统的能力、以及后端逻辑的容忍度反推出来。
这篇文章面向的是做数据采集、PLC编程、电源测试、传感器信号处理的工程师和技术爱好者。我会把判定窗和恢复时间的推导逻辑拆开讲清楚,给出可以直接套用的计算方法和实操步骤,再把我自己在现场踩过的坑整理成排查清单。不管你是刚接触脉冲信号的新手,还是已经调过不少板子的老手,应该都能从中找到能直接抄作业的东西。
2. 判定窗与恢复时间的底层逻辑:不是拍脑袋,是算出来的
2.1 脉冲、振铃与采样率的三方博弈
要理解判定窗和恢复时间,先得把三个基本概念的关系理清楚。
脉冲是你要检测的有效信号变化。它可能是一个上升沿、一个下降沿,或者一个窄脉冲。振铃是脉冲边沿之后由于传输线阻抗不匹配、寄生电感电容谐振而产生的衰减振荡。采样率是你用来观察和判定这个信号的系统时钟频率。
这三者之间的关系可以用一个生活化的类比来理解:假设你在一个安静的房间里听人敲门。真正的敲门声是脉冲,但房间有回音,敲一下之后会有短暂的余响,这就是振铃。如果你的耳朵反应足够快(采样率高),你能分辨出敲门声和回音;如果反应慢(采样率低),回音和下一次敲门声就会混在一起,你就不知道到底敲了几下。
关键结论:采样率必须至少是振铃频率的2倍以上,否则你连振铃本身都看不到,更谈不上区分。根据奈奎斯特采样定理,要还原一个频率为f的信号,采样率至少要是2f。但实际工程中,为了能准确判定脉冲边沿和振铃的边界,我通常建议采样率至少是振铃最高频率分量的5到10倍。
举个例子:某伺服驱动器编码器输出脉冲,边沿振铃频率实测约2MHz。如果你用10MHz采样率去采,每个振铃周期只有5个采样点,勉强能看出振荡但很难精确定位衰减到阈值以下的时间点。换成50MHz采样率,每个周期25个点,衰减包络就清晰多了。这就是为什么HX711在80Hz采样率下比10Hz更能分辨快速变化的重量信号——采样率直接决定了时间分辨率。
2.2 判定窗到底在判定什么
判定窗(Decision Window)的本质是一个时间阈值。当两个脉冲边沿之间的时间间隔小于这个阈值时,系统判定为“一次事件带振铃”;大于这个阈值时,判定为“两次独立事件”。
这个阈值的设定不能凭感觉,要从三个维度反推:
第一,振铃的衰减时间。振铃从峰值衰减到系统噪声底以下所需的时间,记为t_ring。判定窗必须大于t_ring,否则你会把振铃的第二个波峰误判为第二次事件。t_ring可以通过实测得到:给系统一个理想的单次脉冲,观察边沿后振荡衰减到噪声底的时间。
第二,后端逻辑的最小响应时间。你的计数器、中断服务程序、或者PLC的高速计数模块,从接收到一个有效边沿到准备好接收下一个边沿,需要一定的时间。这个时间记为t_logic。判定窗必须大于t_logic,否则第二次事件会被漏掉。
第三,信号本身的物理约束。如果传感器或信号源本身不可能在短时间内产生两次真实事件,那么判定窗可以设得更大一些,以提高抗干扰能力。比如一个机械开关,物理上不可能在1ms内完成两次通断,那判定窗就可以设到1ms以上。
最终判定窗的取值:T_window = max(t_ring, t_logic, t_physical_min) × 安全系数。安全系数通常取1.5到2,给温漂、老化、批次差异留余量。
2.3 恢复时间的真实含义
恢复时间(Recovery Time)经常被和判定窗混淆,但两者作用不同。判定窗是“两个边沿之间至少隔多久才算两次事件”,恢复时间是“一次事件被确认后,系统需要多长时间才能回到稳定状态、准备接受下一次判定”。
恢复时间包含几个部分:信号调理电路的建立时间、ADC或比较器的恢复时间、数字滤波器的群延迟、以及软件状态机的复位时间。在双脉冲测试中,恢复时间还涉及功率器件的关断拖尾和测试电路的储能元件复位。
我见过太多人把恢复时间设得太短,结果第一次脉冲的振铃还没完全衰减,系统就重新武装了,导致振铃被误判为第二次脉冲。也见过把恢复时间设得太长,两个真实脉冲间隔明明够大,但第二个脉冲被“恢复期”屏蔽掉了。
恢复时间的设定原则:T_recovery ≥ T_window + t_margin,其中t_margin是额外余量,通常取判定窗的20%到50%。这样确保系统在判定完一次事件后,有足够时间完全稳定下来,再进入下一次判定。
2.4 为什么不能凭肉眼:一个真实的翻车案例
去年帮一个客户调信捷PLC的XD3-24T-E伺服脉冲采集程序。现场现象是:伺服电机低速运行时,PLC计数正常;一旦提速,计数就偏多,而且速度越快偏得越多。
客户坚持说伺服驱动器没问题,用示波器看波形“很干净”。我让他把时基打到100ns/div再看,结果每个脉冲边沿后面都跟着一串约3MHz的振铃,衰减时间大约800ns。在低速时,脉冲间隔远大于800ns,振铃在下一个脉冲到来前已经衰减完了;但高速时脉冲间隔缩短到1μs左右,振铃还没完全消失,PLC的高速计数模块就把振铃的第二个波峰也计了一次。
解决方案很简单:在PLC程序里加一个判定窗,设定为1.2μs。两个边沿间隔小于1.2μs时,只计一次。同时把恢复时间设为1.5μs,确保振铃完全衰减后再重新武装计数器。改完之后,全速段计数准确。
这个案例说明:肉眼看到的“干净波形”,在足够高的时间分辨率下可能完全是另一回事。判定窗和恢复时间必须基于实测数据来设定,而不是基于“看起来没问题”的直觉。
3. 核心参数计算与实操设定:从理论到可落地的数值
3.1 振铃衰减时间的实测方法
设定判定窗的第一步是测出振铃衰减时间t_ring。具体操作如下:
- 让信号源输出一个理想的单次脉冲,或者让设备在最低速下运行,确保两个脉冲间隔远大于预期振铃时间。
- 用示波器高分辨率采集这个脉冲的边沿,时基设置到能看清振铃细节的程度。一般振铃频率在1MHz到10MHz之间,时基建议50ns/div到200ns/div。
- 打开示波器的包络测量功能,或者用光标手动测量:从脉冲边沿的峰值开始,到振铃幅度衰减到系统噪声底(通常是峰峰值的2%到5%)的时间。
- 记录至少10组数据,取最大值作为t_ring。
注意:测量时要用设备实际工作时的线缆长度和连接方式,不要用短跳线代替。线缆的寄生参数直接影响振铃频率和衰减时间。
如果手头没有高带宽示波器,可以用一个间接方法:逐步提高信号源的脉冲重复频率,观察计数系统从准确到开始出错的临界频率。临界频率的倒数就是振铃时间的一个保守估计。这个方法虽然粗糙,但在现场应急时很实用。
3.2 采样率与判定精度的量化关系
采样率决定了你能分辨的最小时间间隔。如果采样周期为T_s,那么两个边沿之间的时间差测量误差最大为T_s。判定窗的设定必须考虑这个误差。
假设采样率为f_s,采样周期T_s = 1/f_s。如果你需要分辨的最小脉冲间隔为T_min,那么要求:
T_s ≤ T_min / 5
也就是说,采样率至少是最小待分辨间隔的5倍。比如你需要分辨1μs的脉冲间隔,采样率至少要5MHz。实际工程中我建议留更多余量,取10倍以上。
回到HX711的例子:10Hz采样率对应采样周期100ms,80Hz对应12.5ms。如果你要检测的重量变化脉冲间隔在50ms左右,10Hz采样率下每个脉冲只有0.5个采样点,根本分辨不了;80Hz下每个脉冲有4个采样点,勉强能分辨。这就是为什么高速称重场景必须用80Hz。
| 采样率 | 采样周期 | 可分辨最小间隔(5倍原则) | 适用场景 |
|---|---|---|---|
| 10Hz | 100ms | 500ms | 静态称重、慢速温度采集 |
| 80Hz | 12.5ms | 62.5ms | 动态称重、快速重量变化 |
| 1MHz | 1μs | 5μs | 一般数字脉冲采集 |
| 10MHz | 100ns | 500ns | 伺服编码器、高速计数 |
| 100MHz | 10ns | 50ns | 双脉冲测试、功率器件评估 |
3.3 判定窗的完整计算流程
把前面的因素综合起来,判定窗的计算流程如下:
步骤一:确定振铃衰减时间t_ring。通过3.1节的方法实测,取最大值。
步骤二:确定后端逻辑响应时间t_logic。查阅PLC高速计数模块的手册,或者实测中断服务程序的执行时间。信捷XD3系列的高速计数模块,单相计数时最高响应频率200kHz,对应最小响应时间5μs;但这是电气层面的,软件层面还要加上中断延迟和程序执行时间,实际t_logic可能在10μs到50μs之间。
步骤三:确定物理最小间隔t_physical。根据信号源的物理特性确定。比如机械开关的抖动时间通常在1ms到10ms,那t_physical就取10ms。
步骤四:计算判定窗。T_window = max(t_ring, t_logic, t_physical) × 1.5。
步骤五:验证。用已知间隔的两个脉冲测试,间隔略大于T_window时应该计为两次,略小于时应该计为一次。如果不符合,调整安全系数重新计算。
3.4 恢复时间的设定与验证
恢复时间的设定相对简单,但验证同样重要:
T_recovery = T_window + max(T_window × 0.3, t_stabilize)
其中t_stabilize是信号调理电路的建立时间,通常可以从运放或比较器的手册中查到。对于大多数比较器,建立时间在100ns到1μs之间。
验证方法:用两个间隔等于T_recovery的脉冲测试,第二个脉冲应该被正常计数。然后把间隔缩小到T_recovery的80%,第二个脉冲应该被屏蔽。如果不符合,说明恢复时间设短了或设长了。
实操心得:恢复时间不要设得刚好等于判定窗,一定要留余量。我通常会把恢复时间设成判定窗的1.3到1.5倍。多出来的时间不会影响正常计数,但能有效防止振铃误判。
4. 完整实操流程:从信号采集到逻辑判定的全链路实现
4.1 硬件层面的信号调理
在进入数字判定之前,硬件层面要先做好信号调理,尽量把振铃压下去。这样判定窗和恢复时间就可以设得更小,系统能分辨更近的脉冲。
第一,阻抗匹配。如果信号线是长线缆,源端和负载端都要做阻抗匹配。通常源端串一个33Ω到50Ω的电阻,负载端并一个等于线缆特性阻抗的电阻(常见50Ω或75Ω)。匹配好了,振铃幅度能下降一半以上。
第二,比较器加迟滞。用LM339这类比较器做脉冲整形时,一定要加迟滞。没有迟滞的比较器在信号边沿附近会多次翻转,产生额外的窄脉冲。迟滞窗口一般设为信号幅度的5%到10%。具体做法:在比较器输出和同相输入端之间接一个正反馈电阻,阻值根据需要的迟滞量计算。
第三,RC低通滤波。在比较器输入端加一个RC低通,截止频率设为振铃频率的1/3到1/2。比如振铃频率3MHz,RC截止频率设1MHz到1.5MHz。这样振铃被大幅衰减,而脉冲边沿的上升时间只会略微变慢。计算:R取1kΩ,C取100pF,截止频率约1.6MHz。
第四,施密特触发器整形。如果信号经过长线缆后边沿已经很差,可以用74HC14这类施密特触发器做最后整形。它的迟滞特性天然抑制振铃。
4.2 数字判定状态机的设计
硬件调理之后,进入数字判定环节。我习惯用一个简单的状态机来实现判定窗和恢复时间:
typedef enum { STATE_IDLE, // 空闲,等待第一个边沿 STATE_WINDOW, // 判定窗内,忽略后续边沿 STATE_RECOVERY // 恢复期,等待系统稳定 } pulse_state_t; pulse_state_t state = STATE_IDLE; uint32_t last_edge_time = 0; uint32_t window_ticks = WINDOW_US; // 判定窗对应的计数值 uint32_t recovery_ticks = RECOVERY_US; // 恢复时间对应的计数值 void on_edge_detected(uint32_t current_time) { uint32_t elapsed = current_time - last_edge_time; switch (state) { case STATE_IDLE: // 第一次边沿,计数并进入判定窗 pulse_count++; last_edge_time = current_time; state = STATE_WINDOW; break; case STATE_WINDOW: // 判定窗内,忽略 break; case STATE_RECOVERY: // 恢复期内,忽略 break; } } void on_timer_tick(uint32_t current_time) { uint32_t elapsed = current_time - last_edge_time; if (state == STATE_WINDOW && elapsed >= window_ticks) { state = STATE_RECOVERY; last_edge_time = current_time; } else if (state == STATE_RECOVERY && elapsed >= recovery_ticks) { state = STATE_IDLE; } }这个状态机的逻辑很清晰:检测到第一个边沿后,进入判定窗,在判定窗内忽略所有后续边沿;判定窗结束后进入恢复期,恢复期内也忽略边沿;恢复期结束后回到空闲,准备接受下一个有效边沿。
关键参数就是window_ticks和recovery_ticks,它们由前面的计算结果换算成定时器计数值。比如定时器频率1MHz,判定窗1.2μs,那window_ticks = 1.2,取整为2。恢复时间1.5μs,recovery_ticks = 1.5,取整为2。
注意:定时器频率要足够高,否则判定窗的精度不够。建议定时器频率至少是采样率的2倍,或者直接用采样时钟作为定时基准。
4.3 在PLC中实现判定窗和恢复时间
信捷XD3系列PLC的高速计数功能本身不带判定窗,需要在梯形图程序里自己实现。思路和上面的状态机一样,只是用PLC的定时器和计数器来实现。
具体步骤:
- 用高速计数器的中断功能,每次边沿触发一个中断。
- 在中断程序里,读取一个自由运行定时器的当前值,计算与上一次边沿的时间差。
- 如果时间差小于判定窗设定值,直接返回,不计数。
- 如果时间差大于判定窗,计数器加一,并更新上一次边沿的时间戳。
- 用一个单独的定时器实现恢复时间,在恢复期内屏蔽中断。
梯形图的关键网络包括:时间差计算网络、判定窗比较网络、计数使能网络、恢复定时器网络。具体指令可以用DSUB做时间差,DCMP做比较,DADD做计数。
实测下来,XD3-24T-E在200kHz计数频率下,加上判定窗逻辑后,CPU扫描周期会增加约0.5ms。如果扫描周期本来就紧张,可以把判定窗逻辑放在中断程序里,减少对主程序的影响。
4.4 双脉冲测试中的特殊处理
双脉冲测试的场景更复杂一些,因为两个脉冲是你主动产生的,间隔精确可控,但功率器件的响应会引入额外的振铃和拖尾。
在双脉冲测试中,判定窗主要用来区分“第一个脉冲的关断振铃”和“第二个脉冲的开启边沿”。恢复时间则用来确保测试电路在第二个脉冲到来前已经完全复位。
我的做法是:先用一个脉冲测试,测出关断振铃的衰减时间t_ring_off。然后设定判定窗为t_ring_off × 1.5。恢复时间设为判定窗的1.2倍。第二个脉冲的延迟时间必须大于恢复时间,否则会被屏蔽。
如果测试中发现第二个脉冲的电流波形异常,首先检查恢复时间是否设得太短,导致测试电路还没复位就开启了第二个脉冲。其次检查判定窗是否太大,把第二个脉冲的开启边沿也屏蔽了。
5. 常见问题与排查技巧实录
5.1 计数偏多:振铃被误判为脉冲
这是最常见的症状。表现是计数值比实际脉冲数多,且多出来的数量与信号边沿的振铃程度相关。
排查步骤:
- 用高带宽示波器观察脉冲边沿,确认振铃频率和衰减时间。
- 检查判定窗是否小于振铃衰减时间。如果是,增大判定窗。
- 检查恢复时间是否小于判定窗。如果是,增大恢复时间。
- 检查硬件调理是否到位。如果振铃幅度很大,光靠数字判定窗可能不够,需要加RC滤波或阻抗匹配。
避坑技巧:判定窗和恢复时间不要同时调。先固定恢复时间为判定窗的1.5倍,只调判定窗,找到临界值后再微调恢复时间。
5.2 计数偏少:真实脉冲被屏蔽
表现是计数值比实际脉冲数少,且丢失的脉冲往往出现在高速段。
排查步骤:
- 确认判定窗是否设得太大,把两个真实脉冲之间的间隔也覆盖了。
- 确认恢复时间是否设得太长,第二个脉冲落在恢复期内被屏蔽。
- 检查后端逻辑的响应时间是否足够。如果PLC扫描周期太长,即使判定窗设得合理,中断响应不及时也会丢脉冲。
- 用已知间隔的脉冲源测试,逐步缩小间隔,找到开始丢脉冲的临界点,与判定窗和恢复时间的设定值对比。
5.3 低速正常、高速出错:采样率或逻辑响应跟不上
这种症状通常不是判定窗本身的问题,而是采样率或逻辑响应时间不够。
排查步骤:
- 计算当前采样率下可分辨的最小间隔。如果最小间隔大于实际脉冲间隔,必须提高采样率。
- 检查PLC高速计数模块的最高响应频率。信捷XD3系列单相最高200kHz,双相最高100kHz。如果脉冲频率接近这个上限,计数出错是正常的,需要换更高规格的模块或改用硬件计数方案。
- 检查中断程序的执行时间。如果中断程序太长,两次中断之间来不及处理,就会丢脉冲。优化中断程序,只做最必要的计数和状态更新,其他处理放到主程序。
5.4 常见问题速查表
| 症状 | 可能原因 | 排查方法 | 解决措施 |
|---|---|---|---|
| 计数偏多 | 振铃被误判 | 高带宽示波器看边沿 | 增大判定窗,加硬件滤波 |
| 计数偏少 | 真实脉冲被屏蔽 | 用已知间隔脉冲源测试 | 减小判定窗或恢复时间 |
| 高速出错 | 采样率不足 | 计算最小可分辨间隔 | 提高采样率或换硬件 |
| 低速出错 | 恢复时间太长 | 检查恢复时间设定 | 减小恢复时间 |
| 随机出错 | 信号完整性差 | 检查线缆和接地 | 加阻抗匹配,改善接地 |
| 温漂后出错 | 参数余量不足 | 高低温测试 | 增大安全系数 |
5.5 独家避坑经验
经验一:判定窗不要设成整数。比如计算出来是1.2μs,不要设成1μs或2μs,就设1.2μs。整数往往是其他周期的倍数,容易产生谐波干扰。非整数设定能避开一些系统性的噪声。
经验二:恢复时间要分场景。同一个设备,低速运行和高速运行时,恢复时间可以设不同的值。低速时振铃有足够时间衰减,恢复时间可以短一些;高速时恢复时间要长一些。可以在程序里根据当前速度动态调整。
经验三:留一个调试接口。在程序里留一个变量,可以实时修改判定窗和恢复时间,不用重新下载程序。现场调试时这个接口能省大量时间。
经验四:用双脉冲测试验证。不要只用连续脉冲测试,要用两个间隔精确可控的脉冲测试。第一个脉冲用来产生振铃,第二个脉冲用来验证判定窗和恢复时间是否合理。双脉冲测试能暴露出连续脉冲测试发现不了的问题。
经验五:注意温度影响。振铃频率和衰减时间会随温度变化。如果设备工作在宽温环境,判定窗和恢复时间要按最高温度下的振铃时间来计算,并留足够余量。我一般会按常温实测值乘以1.5作为宽温场景的设定值。
6. 从信号到决策:把判定窗和恢复时间变成系统能力
判定窗和恢复时间这两个参数,表面上看只是两个时间阈值,但它们决定了整个采集系统的“时间分辨能力”。设得太小,系统被噪声和振铃淹没;设得太大,系统反应迟钝,真实事件被漏掉。找到那个恰到好处的值,靠的不是肉眼,而是对信号物理特性的理解、对采样系统的量化分析、以及对后端逻辑的准确评估。
我在多个项目里反复验证过一个原则:先测振铃,再算判定窗,最后定恢复时间。这个顺序不能乱。跳过振铃实测直接拍脑袋设判定窗,十有八九要返工。恢复时间一定要比判定窗大,大多少取决于信号调理电路的建立时间和后端逻辑的复位时间,不能想当然。
还有一个容易被忽视的点:判定窗和恢复时间不是设一次就一劳永逸的。设备老化、线缆更换、工作环境变化,都会改变振铃特性。定期用双脉冲测试验证一下这两个参数是否仍然合适,应该成为设备维护的常规项目。
最后分享一个我在现场常用的小技巧:如果手头没有高带宽示波器,可以用一个简单的方法估算振铃时间——把信号源的脉冲频率逐步提高,同时观察计数系统的输出。当计数开始出错时,记录当前的脉冲间隔,这个间隔就是振铃时间的一个保守上界。虽然不够精确,但足以帮你设定一个安全的判定窗。等有条件时再用示波器精确测量并优化。