发布日期:2026-01-26 23:04 点击次数:162

单片机采样总是不准,滤波选错一步错全盘,到底该信经验还是看数据。
昨天调了一个压力传感器,数据跳得跟心跳似的,一会儿98,一会儿105,一会儿又掉到82。不是硬件坏,也不是接线松,就是ADC读出来的原始值太“毛”。查了手册,没写怎么滤波;翻论坛,一堆人贴代码但不说为啥这么写。最后翻出本旧书,里面画了张图,横轴时间,纵轴数值,几条线叠在一起——原来滤波不是为了把数“压平”,是让机器能看懂人想测的东西。

限幅滤波我最先试,逻辑就两行:和上回差太多?那就别要。结果温度缓慢上升时,它卡在85不动了三分钟,像死机。后来发现,阈值设成2太小,改成5又压不住开关电源哼哼的干扰。改来改去,才明白这法子根本不是“滤波”,是“守门员”,只拦猛的,不管嗡嗡响的。
中位值滤波看起来靠谱,采5个数排个序,拿中间那个。可我用在电机电流上,转速一快,它老掉拍子——前一秒3.2A,后一秒直接蹦到3.7,它还在排第3个数。缓冲区占8字节,排序花掉400个时钟周期。单片机没说话,但发热了。
递推平均我后来焊了个硬件DMA配合用,窗口设成8,采样率1kHz,结果50Hz工频干扰真少了。但换到电池电压监测上,它反应太慢,开云官方app下载电量从92%掉到85%时,显示还停在89。就像电梯按钮按了,门还慢慢关。
加权递推平均我抄了个线性权重表:1、2、3、4、5。算起来比普通平均多几步乘法,但确实没那么“钝”。只是表存哪儿?ROM?RAM?最后把权重全换成移位加法,凑合能跑。不是所有MCU都有硬件乘法器,这点没人提醒过。
卡尔曼滤波我装了个MATLAB模型跑通了,状态估计很稳。但烧进STM32F103里,光矩阵运算就卡住,主频72MHz撑不住。后来查资料才知道,工业现场用的简易卡尔曼,连状态方程都简化成一条直线斜率加个偏移量。不是理论不行,是咱手里的芯片不够“想得多”。
最实用的反而是限幅+消抖组合。用在车间继电器反馈信号上,既不被电焊机闪断,也不被接触器抖动骗。逻辑就三段:1.新值和旧值差太大?扔掉;2.差得不大但变来变去?计数;3.连续5次一样?才更新。没高大上名词,就一个flag和一个count变量。
{jz:field.toptypename/}调试时用串口把原始值、滤波后值、中间变量全打出来,放在Excel里画曲线。一眼看出中位值在阶跃响应里拖尾巴,一阶滞后在快速变化时“追不上”。理论说α=0.6对应时间常数,实测发现0.5更合适——因为运放电路里还有个0.1μF电容在偷偷帮忙。
现在我的滤波代码里,没有“最优”,只有“这次能用”。有些函数开头写着//20240317_车间实测有效,有些标着//未验证_勿上线。文档没写,但我知道,温度传感器配中位值+限幅,电流传感器必须加滑动窗口,而电池电压得单独用一阶滞后,因为它的噪声频谱完全不一样。
滤波不是加个算法就完事。得知道传感器怎么输出,线怎么走,电源是不是干净,PCB有没有地割裂。有一次数据飘,最后发现是ADC参考电压引脚旁边挨着LED驱动线,隔层没铺铜。
我删过三次滤波模块,每次重写都比上次少三行代码。现在最常用的就四个:限幅(守底线)、递推平均(压周期噪声)、中位值(打坏点)、一阶滞后(拖慢快变)。别的不是不好,是没必要。
手上这个项目下周要交样机,板子已经打回来了。滤波参数调了七版,今天定稿。最后一遍烧录,串口吐出来的数字稳了。
烧完就去吃饭。