4、电压采集标定:ADC采样原理、硬件滤波与软件滤波策略、电压通道一致性标定

电压采集,说白了就是BMS的「眼睛」。眼睛要是花了,后面什么SOC估算、故障诊断全得跑偏。我入行那会儿,就见过一个项目因为电压采集偏差,导致电芯过充保护误动作,整包电池被误判报废——嗯,那场面,至今难忘。

今天咱们就聊聊电压采集标定这件事。我把它拆成三个部分:ADC采样原理、滤波策略、通道一致性标定。一个一个来。

4.1 ADC采样原理:从模拟到数字的「翻译」

BMS里用的ADC,最常见的是逐次逼近型(SAR ADC)。为什么?因为它在精度、速度和功耗之间找到了一个不错的平衡点。你想想看,一个电池包少则几十个电芯,多则上百个,每个都得采,速度慢了不行,功耗高了也不行。

ADC的核心参数,我列个表,你对照着看:

参数 说明 我的建议值
分辨率 12位~16位常见 至少14位,16位更稳妥
采样率 每通道每秒采样次数 100Hz~1kHz,看应用场景
参考电压 决定满量程范围 2.5V或3.3V,要稳定
INL/DNL 积分/微分非线性误差 ±1LSB以内

这里有个坑,我提醒你一下:参考电压的稳定性。我曾经在一个项目中,ADC的参考电压直接用了一颗普通的LDO,结果温度一变化,采样值跟着飘。后来换成高精度基准源,问题才解决。说白了,参考电压就是ADC的「尺子」,尺子不准,量什么都白搭。

4.2 硬件滤波策略:第一道防线

硬件滤波,就是在信号进入ADC之前,先把高频噪声干掉。为什么?因为ADC采样有个「混叠」效应——高频噪声会被折叠到低频段,你根本分不清是真实信号还是噪声。

最常见的硬件滤波电路,就是RC低通滤波器。我直接给你一个典型电路:

电芯电压 → 分压电阻 → RC低通滤波 → 运放跟随 → ADC输入

RC滤波的截止频率怎么选?我个人的习惯是:

  • 对于电芯电压(变化慢),截止频率设在10Hz~100Hz
  • 对于电流采样(变化快),截止频率可以放到1kHz以上
  • 电阻选10kΩ~100kΩ,电容选0.1μF~1μF

你可能会问:「为什么不用更高阶的滤波器?」嗯,这里有个权衡。高阶滤波器效果好,但会引入相位延迟。对于BMS来说,电压采集的实时性很重要,延迟大了,过压保护就来不及响应。所以,我一般只用一阶RC,配合软件滤波来补足。

注意:RC滤波的电容不能太大。电容大了,充电时间常数变大,ADC采样时如果采样时间不够,电压还没稳定就被采走了,结果就是测量值偏小。我见过有人用10μF的电容,结果采样值比实际低了20mV——这可不是小数目。

4.3 软件滤波策略:第二道防线

硬件滤波搞定了高频噪声,但低频噪声和随机噪声还得靠软件。软件滤波的好处是灵活,想怎么改就怎么改,不用动硬件。

常用的软件滤波方法,我按推荐顺序列一下:

  1. 中值滤波:连续采N个值,取中间值。对脉冲噪声效果极好。
  2. 滑动平均滤波:维护一个窗口,每次取平均值。平滑效果好,但延迟大。
  3. 一阶低通滤波:y(n) = α * x(n) + (1-α) * y(n-1)。计算量小,适合嵌入式。
  4. 卡尔曼滤波:效果最好,但计算量大,一般用在高端BMS上。

我个人的做法是:先用中值滤波去掉毛刺,再用一阶低通滤波做平滑。代码长这样:

// 中值滤波:取5个值的中间值
uint16_t median_filter(uint16_t *buf, uint8_t len) {
    // 排序后取中间值
    for (int i = 0; i < len - 1; i++) {
        for (int j = 0; j < len - i - 1; j++) {
            if (buf[j] > buf[j + 1]) {
                uint16_t tmp = buf[j];
                buf[j] = buf[j + 1];
                buf[j + 1] = tmp;
            }
        }
    }
    return buf[len / 2];
}

// 一阶低通滤波
#define ALPHA 0.2f  // 滤波系数,越小越平滑
static uint16_t last_value = 0;

uint16_t lowpass_filter(uint16_t raw) {
    uint16_t result = (uint16_t)(ALPHA * raw + (1 - ALPHA) * last_value);
    last_value = result;
    return result;
}

这里有个关键点:滤波系数α怎么选?α越大,响应越快,但噪声抑制差;α越小,越平滑,但延迟大。我一般从0.1开始试,看波形效果再调。说白了,这是个「手感活」,没有标准答案。

小技巧:如果你用的是滑动平均滤波,窗口长度建议选2的幂次方(比如4、8、16),这样求平均值时可以用移位操作代替除法,速度快很多。

4.4 电压通道一致性标定:让所有通道「说同一种语言」

好了,ADC采样和滤波都搞定了,但还有一个大问题:通道一致性

你想想看,一个BMS芯片通常有8个、12个甚至16个采样通道。每个通道的PCB走线长度不同、分压电阻有误差、ADC内部也有差异。结果就是:同一个电压,不同通道采出来的值不一样。这要是用在均衡策略上,非出乱子不可。

通道一致性标定,说白了就是给每个通道算一个「校正系数」。我常用的方法是两点标定:

  1. 输入一个低电压(比如2.0V),记录每个通道的采样值
  2. 输入一个高电压(比如4.5V),记录每个通道的采样值
  3. 用这两点算出每个通道的增益和偏移

公式很简单:

实际电压 = 采样值 × 增益 + 偏移

增益 = (V_high - V_low) / (ADC_high - ADC_low)
偏移 = V_low - ADC_low × 增益

标定完成后,每个通道都有自己的增益和偏移。每次采样后,用这个公式算一下,就能得到校正后的电压值。

我曾经在一个项目中,发现标定后还有0.5mV的偏差。查了半天,原来是温度变化导致的。后来我加了一个温度补偿:在BMS板上放一个温度传感器,根据温度查表修正增益。效果立竿见影。

核心要点:通道一致性标定不是一劳永逸的。温度、老化、湿度都会影响精度。我建议每半年或每1万公里做一次重新标定。如果条件允许,可以在BMS启动时做一次自标定——用内部基准电压来校准。

4.5 避坑指南:我踩过的那些坑

最后,分享几个我亲身经历过的坑,你遇到了可以少走弯路:

  • 采样时间不够:ADC采样时,内部的采样电容需要充电。如果采样时间太短,电压还没稳定就被转换了。我一般把采样时间设为ADC时钟的10个周期以上。
  • 地线干扰:高压侧和低压侧的地线如果没处理好,共模电压会把ADC烧掉。隔离是必须的,别省这个钱。
  • 滤波参数「一刀切」:不同电芯的噪声特性不一样。我建议每个通道单独配滤波参数,别图省事用同一套。
  • 标定后不验证:标定完了,一定要用高精度万用表抽检几个点。我见过标定程序写错了,结果所有通道的增益都反了——嗯,那场面,挺尴尬的。

好了,电压采集标定这部分就聊到这儿。说白了,ADC采样是基础,滤波是保障,一致性标定是灵魂。三者缺一不可。下一章咱们聊聊电流采集,那个坑更多,到时候再细说。