4、软件滤波:滑动平均滤波、中值滤波、卡尔曼滤波在母线电压采样中的应用
母线电压采样,说白了就是FOC控制系统的「眼睛」。
眼睛要是花了,电机肯定跑不稳。我见过太多工程师,算法调得天花乱坠,结果一上电,母线电压跳得像心电图,最后全白费。
今天咱们就聊聊,怎么用软件把这双「眼睛」擦亮。
4.1 为什么需要软件滤波?
硬件上我们通常会加RC低通滤波,但有个问题——RC滤波会带来相位延迟。你想想看,母线电压采样要是滞后了,电流环的响应速度立马打折。
我个人的习惯是:硬件做粗滤,软件做精滤。硬件把高频毛刺干掉,软件负责处理那些低频的、周期性的波动。
核心观点:软件滤波不是万能的,但它能解决硬件解决不了的问题。比如电机突然加载导致的电压跌落,硬件RC根本来不及反应,但软件滤波可以做到「预测性补偿」。
4.2 滑动平均滤波
这是最基础、也最常用的方法。说白了就是取最近N次采样值的平均值。
数学表达式:
y[n] = (x[n] + x[n-1] + ... + x[n-N+1]) / N
代码实现(C语言):
#define WINDOW_SIZE 16
static uint16_t buffer[WINDOW_SIZE];
static uint8_t index = 0;
static uint32_t sum = 0;
uint16_t moving_average(uint16_t new_sample) {
sum -= buffer[index];
buffer[index] = new_sample;
sum += new_sample;
index = (index + 1) % WINDOW_SIZE;
return sum / WINDOW_SIZE;
}
我踩过的坑:
我曾经在一个项目中,把窗口大小设成了64。结果电机启动时,母线电压明明已经掉到24V了,滤波输出还显示26V。为什么?窗口太大,响应太慢!
经验值:对于1kHz的采样率,窗口大小建议在8~16之间。既能滤掉开关噪声,又不至于让响应滞后超过10ms。
4.3 中值滤波
滑动平均最怕什么?怕「野值」。比如ADC偶尔采到一个异常值,滑动平均会被拉偏。中值滤波就是专门对付这种「毛刺」的。
原理:取N个采样值,排序后取中间那个。
uint16_t median_filter(uint16_t *data, uint8_t len) {
uint16_t temp[len];
for(uint8_t i = 0; i < len; i++) temp[i] = data[i];
// 冒泡排序,只排一半就够了
for(uint8_t i = 0; i < len/2 + 1; i++) {
for(uint8_t j = 0; j < len - i - 1; j++) {
if(temp[j] > temp[j+1]) {
uint16_t t = temp[j];
temp[j] = temp[j+1];
temp[j+1] = t;
}
}
}
return temp[len/2];
}
注意:中值滤波的窗口大小必须是奇数。3、5、7都行。我建议用5,排序计算量不大,效果也够用。
什么时候用中值滤波?
- 采样信号偶尔出现尖峰脉冲(比如IGBT开关瞬间的耦合噪声)
- ADC参考电压不稳定导致的偶发跳变
- 通信干扰导致的异常数据
4.4 卡尔曼滤波
嗯,说到卡尔曼滤波,很多朋友会觉得「高大上」、「难懂」。其实没那么玄乎。
卡尔曼滤波的核心思想就一句话:用模型预测 + 用测量修正。
对于母线电压来说,我们可以建立一个简单的模型:
- 状态量:母线电压 Vbus
- 过程噪声:负载变化引起的电压波动
- 测量噪声:ADC采样噪声
简化的一维卡尔曼滤波:
typedef struct {
float x; // 估计值
float p; // 估计误差协方差
float q; // 过程噪声协方差
float r; // 测量噪声协方差
float k; // 卡尔曼增益
} Kalman_1D;
void kalman_init(Kalman_1D *kf, float init_val) {
kf->x = init_val;
kf->p = 1.0f;
kf->q = 0.01f; // 根据实际调整
kf->r = 0.1f; // 根据ADC噪声调整
}
float kalman_update(Kalman_1D *kf, float measurement) {
// 预测
kf->p = kf->p + kf->q;
// 更新
kf->k = kf->p / (kf->p + kf->r);
kf->x = kf->x + kf->k * (measurement - kf->x);
kf->p = (1.0f - kf->k) * kf->p;
return kf->x;
}
关键参数调优:
| 参数 | 含义 | 调大 | 调小 |
|---|---|---|---|
| Q | 过程噪声 | 响应更快,但波动大 | 响应慢,更平滑 |
| R | 测量噪声 | 更信任模型预测 | 更信任实际测量 |
我个人的经验:
卡尔曼滤波在母线电压采样中,最大的优势是无相位延迟。滑动平均和中值滤波都会引入延迟,但卡尔曼滤波能做到「实时跟踪」。我在做伺服驱动器时,用卡尔曼滤波替代了滑动平均,电流环带宽直接提升了15%。
4.5 三种滤波方法的对比
| 方法 | 延迟 | 计算量 | 抗野值 | 适用场景 |
|---|---|---|---|---|
| 滑动平均 | 中 | 低 | 差 | 噪声平稳的场合 |
| 中值滤波 | 高 | 中 | 好 | 偶发尖峰噪声 |
| 卡尔曼滤波 | 低 | 中高 | 中 | 需要实时跟踪的场合 |
4.6 实战建议:组合使用
说实话,我很少只用一种滤波方法。实际项目中,我通常这样搭配:
- 第一级:中值滤波(窗口=5)—— 干掉ADC的偶发毛刺
- 第二级:卡尔曼滤波 —— 平滑处理,同时保持低延迟
为什么这么搭?中值滤波负责「剔除坏数据」,卡尔曼滤波负责「平滑好数据」。各司其职,效果最好。
避坑指南:我曾经在一个项目中,只用了滑动平均,结果电机低速运行时,母线电压采样值一直有周期性波动。后来发现是PWM开关频率和采样频率产生了差拍。换成卡尔曼滤波后,问题立刻解决。
4.7 知识体系总览
下面这张图,帮你理清三种滤波方法在母线电压采样中的定位:
嗯,三种方法各有千秋。滑动平均最简单,中值滤波最抗噪,卡尔曼滤波最智能。选哪个,取决于你的项目对延迟和计算资源的容忍度。
我个人建议:先从中值滤波+卡尔曼滤波的组合开始试。如果MCU算力紧张,再退回到滑动平均。别一上来就追求「高大上」,稳定可靠才是第一位的。
公众号:蓝海资料掘金营,微信deep3321