第1章:温度采集与滤波——NTC/PTC原理、ADC采样、滑动平均滤波、卡尔曼滤波入门

大家好,我是老张。在BMS这个行当摸爬滚打了十几年,要说最基础也最要命的一环,就是温度采集。你想想看,电池包里的电芯要是温度测不准,热管理策略就是瞎指挥,轻则续航打折,重则热失控。今天咱们就来聊聊温度采集与滤波的那些事儿。

1.1 NTC与PTC:温度传感器的选型逻辑

先说传感器。BMS里用的最多的就是NTC(负温度系数热敏电阻)。说白了,温度越高,电阻值越小。PTC(正温度系数)刚好反过来,温度越高电阻越大。我个人习惯在电池模组里用NTC,因为它在常温段灵敏度高,适合我们关心的-20℃到60℃这个区间。

NTC的关键参数:

  • B值(材料常数): 一般在3000-4500K之间。B值越大,温度变化时电阻变化越剧烈。我建议选B=3950的,这是行业主流,互换性好。
  • R25(25℃时的标称电阻): 常用10kΩ或100kΩ。10kΩ的功耗小,适合电池包这种对自热敏感的场景。
  • 精度: 1%还是5%?别省这个钱。我在项目里吃过亏,用了5%的NTC,结果同一温度下不同电芯读数差了2℃多,均衡算法直接乱套。

避坑指南: 我曾经遇到过NTC引线过长导致测量偏差的问题。线阻每增加1Ω,在低温区可能引入0.5℃的误差。所以,要么用四线制接法,要么在软件里做线阻补偿。

1.2 ADC采样:从模拟到数字的桥梁

NTC的电阻变化是模拟信号,MCU只认数字。所以中间需要ADC(模数转换器)。BMS里常用的ADC分辨率是12位或16位。12位能分辨4096个等级,16位是65536个。你想想看,对于0-100℃的范围,12位ADC的理论分辨率是0.024℃,够用了。但实际噪声会把这个精度吃掉不少。

ADC采样的关键点:

  1. 参考电压: 内部参考还是外部参考?我建议用外部精密参考(比如2.5V或3.3V),内部参考温漂太大,夏天和冬天能差出几十个LSB。
  2. 采样时间: ADC内部有个采样电容,需要时间充电。采样时间太短,电容没充满,读数偏小。我一般设成10μs以上,具体看MCU手册。
  3. 过采样: 简单粗暴但有效。比如采64次取平均,等效分辨率能提高3位。代价是采样时间变长,但BMS对实时性要求没那么苛刻。

我的小技巧: 在ADC输入端并联一个0.1μF的电容,能滤掉大部分高频噪声。别小看这个电容,它救过我好几次项目。

1.3 滑动平均滤波:简单实用的降噪利器

ADC采回来的数据,直接拿去用?别急,噪声大得很。最简单的滤波就是滑动平均。维护一个长度为N的队列,每次新数据进来,扔掉最老的,算一下队列平均值。

// 滑动平均滤波示例(C语言伪代码)
#define FILTER_LEN 8
float buffer[FILTER_LEN] = {0};
int index = 0;
float sum = 0;

float sliding_average(float new_sample) {
    sum -= buffer[index];          // 减去最老的数据
    buffer[index] = new_sample;    // 存入新数据
    sum += new_sample;             // 加上新数据
    index = (index + 1) % FILTER_LEN;
    return sum / FILTER_LEN;
}

N取多少合适?我一般取8或16。N太小,滤波效果差;N太大,响应变慢。比如电池包突然从25℃升到30℃,N=16的滤波可能要等好几秒才能跟上。嗯,这里要注意:滑动平均对周期性噪声(比如50Hz工频干扰)效果很好,但对突发性尖峰脉冲,它只能削弱,不能完全消除。

1.4 卡尔曼滤波入门:从“猜”到“准”

滑动平均虽然简单,但不够聪明。卡尔曼滤波就不一样了,它会根据模型“预测”下一个温度值,然后用实际测量值去修正预测。说白了,就是一边猜一边改,越猜越准。

卡尔曼滤波的核心思想:

  • 预测: 根据上一时刻的状态,估计当前时刻的状态。比如温度不会突变,所以预测值≈上一时刻的滤波值。
  • 更新: 用当前测量值去修正预测值。修正的力度取决于“卡尔曼增益”——测量越可靠,增益越大;预测越可靠,增益越小。

对于温度这种变化缓慢的量,卡尔曼滤波的模型可以简化:

// 一维卡尔曼滤波(温度场景简化版)
float x_hat = 25.0;  // 初始估计值(比如室温)
float P = 1.0;        // 估计误差协方差
float Q = 0.01;       // 过程噪声(模型不确定性)
float R = 0.1;        // 测量噪声(传感器精度)

float kalman_filter(float z) {
    // 预测
    float x_pred = x_hat;          // 温度变化慢,预测值≈上一时刻
    float P_pred = P + Q;          // 预测误差增大
    
    // 更新
    float K = P_pred / (P_pred + R);  // 卡尔曼增益
    x_hat = x_pred + K * (z - x_pred); // 修正估计
    P = (1 - K) * P_pred;              // 更新误差
    
    return x_hat;
}

你看,代码比滑动平均长不了多少,但效果天差地别。卡尔曼滤波能自适应地调整滤波强度:当测量值噪声大时,它更相信预测;当测量值稳定时,它快速跟踪真实值。

注意: 卡尔曼滤波不是万能的。它假设噪声是高斯分布,如果实际噪声不是这样(比如有突发干扰),效果会打折扣。我建议在卡尔曼滤波之前,先做一次简单的限幅滤波,把明显异常的点剔除掉。

1.5 知识体系总览

为了让你更直观地理解本章的知识结构,我画了一张图:

温度采集与滤波知识体系 温度传感器 NTC(负温度系数) ADC采样 参考电压/采样时间/过采样 数字滤波 滑动平均 卡尔曼滤波 核心逻辑:传感器选型 → 模拟信号采集 → 数字滤波处理 目标:获得准确、稳定、低延迟的温度测量值 输出:可靠温度数据 → 热管理策略

1.6 实战建议:三种滤波怎么选?

讲了这么多,你可能会问:到底用哪种滤波?我根据经验给你一个参考:

场景 推荐滤波方式 理由
电池包正常工况 滑动平均(N=8) 计算量小,效果够用
快充/大倍率放电 卡尔曼滤波 温度变化快,需要快速跟踪
传感器老化/噪声大 卡尔曼滤波 + 限幅 自适应性强,能抑制异常值
资源受限的MCU 滑动平均 不占内存,不耗算力

我的经验: 别把滤波搞得太复杂。我见过有人用卡尔曼滤波调了两个月参数,最后发现滑动平均加个中值滤波效果差不多。先跑通,再优化,这是铁律。

好了,温度采集与滤波的基础就聊到这儿。记住:传感器是眼睛,ADC是神经,滤波是大脑。三者配合好了,你的BMS才算有了“感觉”。


公众号:蓝海资料掘金营,微信deep3321