电机控制中的数字滤波算法:从一阶低通到滑动平均的实战指南

发布时间:2026/7/31 4:26:03

电机控制中的数字滤波算法:从一阶低通到滑动平均的实战指南 1. 从噪声到指令为什么电机控制离不开滤波做电机控制的朋友尤其是玩过无刷直流电机BLDC、步进电机或者伺服的朋友肯定都遇到过这样的场景你精心设计的PID参数在仿真里稳如泰山一上真机电机就开始“跳舞”——要么是转速波动要么是位置抖动甚至发出奇怪的啸叫声。你盯着示波器上那根本该平滑的反馈信号线看到的却是一条毛茸茸的“草履虫”。这时候你心里冒出的第一个念头八成就是“得加个滤波器”。没错滤波算法在电机控制里就像炒菜时的盐看似不起眼少了它却绝对不行。它处理的不是主菜比如FOC矢量控制、SVPWM调制这些核心算法而是那些影响“口感”的杂质——噪声。这些噪声来源五花八门电流采样时的量化噪声和运放热噪声、编码器或霍尔传感器受到电磁干扰产生的跳变、PWM开关引起的电源纹波耦合到信号里甚至电机本身换相、齿槽转矩引起的转矩脉动都会在反馈回路中引入高频或低频的扰动。如果不加处理这些噪声会直接“喂”给控制器。PID控制器是个老实人它可不管输入的是真实误差还是噪声它会不遗余力地去“纠正”这些它认为是误差的噪声信号。结果就是控制器输出端会产生大量无用的、高频的控制量变化导致PWM占空比频繁剧烈调整。这不仅白白增加了功率器件的开关损耗和发热更会引发电机的高频振动产生额外的噪音严重时甚至会让整个系统失稳。所以滤波的根本目的不是为了把信号变“好看”而是为了保护控制器让它只对真实的、有效的误差信号做出响应从而让系统运行得更平稳、更高效、更安静。今天我们就抛开那些高深的控制理论聚焦在“滤波”这个实操环节聊聊在电机控制里几种最常用、也最值得你花时间理解的滤波算法。我会结合具体的场景告诉你它们怎么用为什么这么用以及我最常踩的那些坑。2. 一阶低通滤波电机控制中的“万金油”与双刃剑说到滤波绝大多数工程师第一个想到并且第一个动手实现的就是一阶低通滤波器First-Order Low-Pass Filter, 1st-order LPF。它的概念简单到令人发指只让低频信号通过高频噪声被衰减掉。在数字世界里我们不用电容电阻而是用一个极其简单的公式来实现它y(n) α * x(n) (1 - α) * y(n-1)这里x(n)是当前时刻的采样值比如电流、转速y(n)是当前时刻滤波后的输出值y(n-1)是上一时刻的输出值。而α就是整个滤波器的核心称为滤波系数它的取值范围在0到1之间。这个公式完美体现了一阶低通滤波的思想当前的输出是当前输入和上一时刻输出的加权平均。α越大表示你越信任当前的新采样值滤波器的“惯性”越小响应越快但滤除高频噪声的能力也越弱。α越小表示你更依赖过去的历史输出滤波器的“惯性”越大对噪声的平滑效果越好但信号的延迟也越严重。2.1 截止频率与时间常数的实战换算很多资料会告诉你这个α和滤波器的截止频率fc有关。但对于嵌入式工程师来说我们更关心它在离散系统里的表现。这里有一个非常实用的换算关系α ΔT / (τ ΔT)其中ΔT你的控制周期或采样周期。比如你的PID控制环运行在10kHz那么ΔT 0.0001秒100微秒。τ滤波器的时间常数。这个参数直接决定了滤波器的“反应速度”。τ越大滤波器越“迟钝”平滑效果越好延迟越大。举个例子假设你的电流环频率是20kHz (ΔT50us)你希望滤除1kHz以上的噪声。那么截止频率fc可以设为1kHz。一阶低通滤波器的时间常数τ与截止频率的关系是τ 1 / (2π * fc) ≈ 1 / (6.283 * 1000) ≈ 0.000159秒159微秒。然后代入公式α 0.00005 / (0.000159 0.00005) ≈ 0.00005 / 0.000209 ≈ 0.239。所以在你的代码里α就可以取0.239或者用定点数比如Q15格式的0.239*32768≈7830来实现。每次采样到新的电流值I_adc你就执行I_filtered 0.239 * I_adc 0.761 * I_filtered_prev。注意这个计算是基于“后向差分”离散化方法在控制频率远高于截止频率时比如这里20kHz vs 1kHz精度足够。如果两者接近则需要更精确的离散化方法如双线性变换但在绝大多数电机控制场景下这个简化公式完全够用。2.2 无处不在的应用场景与隐形成本一阶低通滤波在电机控制里几乎无处不在电流环反馈滤波这是最经典的应用。从ADC采样回来的相电流值通常噪声很大直接用于FOC的Clarke/Park变换和PI调节器会引起严重的高频振荡。加上一个截止频率在1kHz到几kHz的LPF具体取决于你的开关频率和控制带宽能立刻让波形干净很多。速度估算滤波无论是通过编码器脉冲计算M法/T法速度还是通过反电动势观测器估算转速得到的速度值都可能是跳变的。用一个时间常数稍大比如对应截止频率10-50Hz的LPF进行平滑可以得到更稳定的速度反馈有利于速度环PI参数的整定。参考指令平滑如果给定速度或位置指令是阶跃变化的直接送给控制器可能会引起冲击。在指令通道加一个LPF可以让指令平滑过渡减少对机械结构的冲击这就是所谓的“斜坡函数”或“S曲线”的简化实现。然而一阶低通滤波是一把双刃剑它的代价就是相位滞后。这个滞后是实实在在的它会直接叠加在你的控制回路延迟上。对于电流环这种需要高带宽的快环过度的滤波τ太大会严重压缩系统的稳定裕度可能导致振荡。我的经验法则是电流环LPF的截止频率至少应设为电流环目标带宽的3到5倍以上。比如你希望电流环带宽是500Hz那么LPF的截止频率最好在1.5kHz到2.5kHz以上以确保引入的相位滞后在可接受范围内。3. 滑动平均滤波对付脉冲干扰的“硬汉”如果说一阶低通滤波是平滑连续噪声的“内功”那么滑动平均滤波Moving Average Filter就是对付突发性脉冲干扰的“外家功夫”。它的原理更粗暴开一个长度为N的队列数组每次新的采样值进来就挤掉最老的那个值然后计算队列里所有N个数据的算术平均值作为输出。y(n) (x(n) x(n-1) ... x(n-N1)) / N在C语言中为了高效我们通常不用每次都累加整个数组而是维护一个队列和和一个队列指针实现循环队列每次更新只需做一次加法、一次减法和一次除法。3.1 为何在电机控制中它不可或缺你可能会问有一阶低通滤波了为什么还需要滑动平均关键在于它们应对的噪声类型不同。一阶低通滤波对白噪声频谱平坦的随机噪声效果很好但对于偶发的、幅值很大的脉冲型干扰比如编码器受到一次强烈的电磁干扰跳变了一个计数一阶低通因为其“惯性”输出只会被缓慢地拉偏一点干扰过去后恢复也慢。而滑动平均滤波如果脉冲干扰只持续了一个采样周期那么它在这一个周期内会对输出产生1/N的影响下一个周期这个干扰值就会被移出窗口输出立刻恢复正常。因此滑动平均滤波特别适用于编码器位置/速度滤波编码器信号可能因振动或干扰产生偶然的毛刺。一个长度为3或5的滑动平均能有效滤除这种单点跳变而不会像重滤波器那样引入过大延迟。ADC采样值预处理在进入更复杂的控制算法之前先对原始ADC值做一次短窗口的滑动平均可以消除偶发的采样异常值为后续处理提供更干净的数据。通信指令平滑从上位机接收的速度指令可能因通信抖动产生微小波动。用一个短窗口滑动平均可以让指令更平稳。3.2 长度N的选择在平滑与延迟间走钢丝滑动平均滤波的性能完全取决于窗口长度N。N越大平滑效果越好但延迟也越大。而且滑动平均滤波引入的延迟是固定的群延迟等于(N-1)/2 * ΔT。这是一个非常明确的、不随频率变化的延迟。例如你的控制周期是100us使用N5的滑动平均那么无论信号频率如何这个滤波器都会固定引入(5-1)/2 * 100us 200us的延迟。你必须把这个延迟考虑到你的控制环时序和稳定性分析里。我的实操心得是在电机控制中滑动平均的窗口N通常取奇数并且不宜过大一般3、5、7足矣。它的角色更像是“哨兵”负责干掉那些明显的、突发的“坏点”而不是去做精细的频谱塑造。对于需要深度平滑的信号应该交给一阶低通或者更高级的滤波器。同时在资源紧张的MCU上要小心计算开销虽然循环队列更新很快但每个周期多一次除法尤其是浮点除法也可能成为负担可以考虑用移位来实现2的整数次幂的N如48的除法。4. 非线性滤波中位值平均与限幅滤波的组合拳当信号中的噪声不仅仅是随机白噪声还混杂着严重的脉冲干扰又称“椒盐噪声”时线性滤波器如一阶低通、滑动平均往往会力不从心。因为它们对所有数据点一视同仁一个巨大的 outlier异常值会显著污染输出。这时候就需要引入非线性思维。4.1 中位值平均滤波去头尾保平安中位值平均滤波Median-Average Filter有时也叫“防脉冲干扰平均滤波”是电机控制工程中非常实用的一种鲁棒性滤波方法。它的操作分两步取中位值连续采样N次N通常为奇数如3,5,7将这N个采样值进行排序取中间的那个值作为“候选值”。这一步的精髓在于它能免疫掉N个样本中少数少于一半的极端异常值。比如采样5次即使有2次被严重干扰取中间值也能得到相对合理的那个。滑动平均将上述得到的中位值再放入一个长度为M的滑动平均窗口进行平均。这一步是为了进一步平滑掉剩余的高频随机噪声。这种方法结合了中值滤波的抗脉冲干扰能力和平均滤波的平滑能力。在电机控制中它特别适合用于关键且易受干扰的模拟量采样例如母线电压检测。母线电压一般比较稳定但可能在功率管开关瞬间被耦合进高频毛刺。用中位值平均滤波能有效得到稳定的电压值用于过压、欠压保护或电压前馈补偿。低分辨率传感器的信号处理某些低成本电位器或霍尔位置传感器输出可能伴有接触噪声或跳变中位值滤波能很好地处理。实现时通常N取3或5即可M也可以取3或5。计算中位值对于3个数很简单比较交换对于5个数也有优化的排序网络算法在嵌入式系统中开销可控。4.2 限幅滤波为算法戴上“紧箍咒”限幅滤波Limiting Filter严格来说不是一个独立的滤波器而是一个必须与其它滤波算法配合使用的“保护罩”。它的逻辑简单粗暴判断本次采样值与前一次滤波输出值的差值或变化率是否超过一个预设的合理限幅值Δ。如果差值|x(n) - y(n-1)| Δ则认为本次采样有效交给后续的滤波器如LPF处理。如果差值|x(n) - y(n-1)| Δ则认为本次采样是异常跳变直接丢弃用上一次的输出y(n-1)或一个预设的安全值来代替本次采样值x(n)。这个Δ的设定非常关键需要基于你对信号最大合理变化速率的了解。例如对于电机转速你知道电机从0加速到额定转速最快需要100ms那么在一个1ms的控制周期内转速最大变化量是可以估算出来的。将这个估算值放大一点作为Δ就能滤除那些不可能发生的剧烈跳变。限幅滤波通常放在采样链路的最前端作为第一道防线。它成本极低两次减法、一次比较判断但能有效防止偶发的、巨大的采样错误比如ADC读取错误、通信误码冲垮你的整个滤波和控制环节。我强烈建议在任何重要的控制回路反馈通路上都考虑加入一个合理的限幅滤波这是系统鲁棒性的廉价保障。5. 滤波器在控制环路中的位置与参数整定心法知道了各种滤波器的原理更关键的问题是把它们放在哪里参数怎么调这直接决定了滤波是“治病”还是“致病”。5.1 位置决定性质反馈 vs 前馈反馈通道滤波这是最常见的用法即对传感器反馈信号电流、速度、位置进行滤波。这里的滤波器会直接影响闭环系统的稳定性和动态性能。因为它位于闭环内滤波器引入的延迟和相位滞后会直接减少系统的相位裕度。因此反馈通道的滤波器必须“轻量”截止频率要足够高远高于控制环带宽以最小化对稳定性的影响。原则是在能有效抑制噪声的前提下截止频率尽可能高。前馈通道滤波对给定指令速度指令、位置指令进行滤波。这里的滤波器位于闭环外不影响闭环稳定性只影响指令的跟踪响应速度。因此你可以根据对系统动态响应和平稳性的要求来调整它。如果想减少启动、停止时的冲击就可以把时间常数设大一些让指令平滑过渡。控制器输出滤波对PID控制器的输出量通常是电压或电流指令进行滤波。这种做法较少见需要非常小心。因为它相当于在控制器和被控对象之间增加了一个环节同样会影响闭环特性。通常仅用于滤除控制器输出中因噪声引起的极高频分量其截止频率必须远高于闭环带宽。5.2 参数整定一个“由紧到松”的迭代过程滤波器参数整定没有一成不变的公式但有一个安全的实践流程初始设定宁紧勿松。开始时将滤波器的截止频率设得非常高对应时间常数非常小或滑动平均窗口N1即不滤波或者干脆先旁路掉滤波器。先确保你的核心控制算法如PID、FOC在“理想”的、无噪声的仿真或轻微噪声下能稳定工作并整定出初步的控制器参数P, I, D。引入噪声观察恶化。在真实系统或加入噪声模型的仿真中运行。观察反馈信号的噪声水平以及噪声对控制器输出和最终控制效果如转速波动、电流THD的影响。逐步加强滤波。非常缓慢地增加滤波强度降低LPF截止频率、增大滑动平均窗口N。每调整一次观察噪声抑制效果示波器上反馈信号是否变得平滑系统动态响应对阶跃指令的响应速度是否明显变慢超调是否增大稳定性系统是否出现新的、低频的振荡找到平衡点。当加强滤波到某个点时你会发现噪声被抑制到可接受范围但系统响应开始变得“迟钝”或出现振荡趋势。那么回调一点找到那个动态性能尚可、噪声抑制也足够的“甜蜜点”。这个点就是你的最佳滤波参数。一个关键技巧利用频域分析。如果条件允许用扫频仪或系统的频率响应分析工具直接测量加入滤波器前后开环传递函数的伯德图。你可以清晰地看到滤波器在哪个频率点开始衰减以及引入了多少相位滞后。这比盲目试错要科学得多。6. 数字滤波器的实现陷阱与代码优化理论很美好但把滤波器写成代码跑在MCU上时坑就来了。这里分享几个我踩过的坑和优化经验。6.1 数据类型与计算精度这是最容易出问题的地方。电机控制中信号范围广电流可能是几十安培转速可能是几千RPM。滤波计算中如果数据类型选择不当会导致溢出或精度损失。定点数 vs 浮点数对于高性能MCU如Cortex-M4/M7带FPU直接使用浮点数float最方便。但对于无FPU的芯片如很多Cortex-M0/M3浮点计算非常慢。必须使用定点数通常是Q格式。例如使用Q15格式1位符号位15位小数位。这时滤波系数α0.239就需要量化为int16_t alpha_q15 0.239 * 32768 7830。滤波计算y_q15 ((int32_t)alpha_q15 * x_q15) 15 ((int32_t)(32768 - alpha_q15) * y_prev_q15) 15。这里必须用int32_t做中间变量防止乘法溢出右移15位相当于除以32768。一阶低通滤波的初始化滤波器上电或使能时y(n-1)的初始值是什么如果设为0而实际信号不为0滤波器需要很长时间才能“爬升”到真实值。最佳实践是在使能滤波器的第一个周期直接让y(n-1) x(n)。这样输出从一开始就是正确的没有过渡过程。6.2 滑动平均滤波的高效实现直接每次求和再除计算复杂度是O(N)。使用循环队列和队列和可以降到O(1)。// 假设 N5 #define MA_WINDOW_SIZE 5 int32_t adc_buffer[MA_WINDOW_SIZE]; int32_t adc_sum 0; uint8_t adc_index 0; int32_t moving_average_update(int32_t new_sample) { // 减去即将被覆盖的旧值 adc_sum - adc_buffer[adc_index]; // 存入新值 adc_buffer[adc_index] new_sample; // 加上新值 adc_sum new_sample; // 更新索引 adc_index (adc_index 1) % MA_WINDOW_SIZE; // 返回平均值 return adc_sum / MA_WINDOW_SIZE; }注意adc_sum要用足够大的类型如int32_t防止累加溢出。如果N是2的幂最后的除法可以用右移代替更快。6.3 多速率系统中的滤波在复杂的电机控制系统中可能存在多个不同频率的控制环。例如电流环快环运行在20kHz速度环慢环运行在2kHz。为速度环提供反馈的转速值是在电流环中计算出来的。这时滤波器的设计要小心在快环电流环中计算的转速已经包含了快环的噪声。如果直接以20kHz的频率送给慢环速度环慢环的控制器会响应这些高频噪声产生不必要的动作。正确的做法是在快环中计算出的转速先经过一个截止频率略高于慢环带宽的LPF进行滤波然后以慢环的频率2kHz进行降采样再送给速度环控制器。这样既滤除了高频噪声又减少了不必要的计算量。7. 超越基础何时需要更高级的滤波方案当一阶低通、滑动平均这些常规武器解决不了问题时你可能需要考虑更高级的方案。这通常发生在对性能要求极高或者噪声特性特别复杂的场合。7.1 陷波滤波器精准狙击特定频率噪声有时候噪声不是宽频带的而是集中在某个特定的频率点。最常见的就是与PWM开关频率或其谐波频率同频的噪声。例如你的电机驱动器开关频率是20kHz由于硬件布局不当这个20kHz的噪声可能耦合到了电流采样电路中。用一个截止频率很高的低通滤波器固然能滤掉它但也会无情地衰减所有高频有用信号。此时陷波滤波器Notch Filter就是最佳选择。它的频率响应特性是在一个非常窄的频带内比如以20kHz为中心±500Hz产生深度衰减而其他频率的信号几乎无衰减地通过。这样就能精准地“挖掉”那个讨厌的特定频率噪声同时保留信号的其他成分。设计陷波滤波器需要知道噪声的精确频率可以通过频谱分析仪测量得到。在数字实现上一个二阶IIR陷波滤波器是常见选择。7.2 卡尔曼滤波在噪声中估计最优状态对于更高级的应用比如基于反电动势观测器的无传感器控制或者需要融合多传感器信息如IMU的平衡车、无人机电机控制卡尔曼滤波就登场了。它不再是一个简单的、固定系数的滤波器而是一套完整的“最优估计”算法。卡尔曼滤波的核心思想是你有一个描述系统动态的模型状态方程也有一个描述传感器测量的模型观测方程。这两个模型都不完美分别受到过程噪声和测量噪声的影响。卡尔曼滤波通过递归计算不断地、动态地权衡“根据模型预测的状态”和“传感器实际测量的状态”这两者之间的可信度从而给出一个统计意义上最优的状态估计。在无传感器FOC中观测器比如滑模观测器、龙伯格观测器估算出的转子位置和速度噪声和误差可能很大。这时可以用一个扩展卡尔曼滤波器EKF用于非线性系统来对这个估算值进行滤波和优化能得到比固定滤波器平滑得多、准确得多的结果。当然它的代价是巨大的计算复杂度和参数整定难度。7.3 自适应滤波让滤波器学会“与时俱进”还有一种情况噪声的特性会随着电机运行状态如转速、负载而变化。比如某种机械共振引起的振动噪声其频率会随转速变化。这时固定参数的滤波器就无能为力了因为它只能滤除固定频率的噪声。自适应滤波器能够根据输入信号自动调整自身的参数如陷波器的中心频率、带宽实时跟踪并抑制变化的噪声。算法上可能涉及LMS最小均方等算法。这在高端伺服系统、精密运动控制中有所应用用于抑制与转速相关的周期性转矩脉动或振动。实现它需要更强的处理能力和更深入的信号处理知识。对于绝大多数工业电机控制、无人机电调、机器人关节驱动等应用熟练掌握一阶低通、滑动平均及其组合并理解它们在控制环中的影响已经能够解决95%以上的噪声问题。高级滤波器是性能攻坚时的利器但前提是基础必须扎实。我的建议是先从用好、用懂基础的滤波算法开始建立起对信号、噪声和控制环相互作用的直觉当遇到基础工具无法解决的瓶颈时再带着明确的问题去探索更高级的方案。

相关新闻