4、BMS数据采集详解:电池单体电压采集、电池组总电压与电流采集、温度传感器布局与采样策略

大家好,我是老张。在储能系统里摸爬滚打了十来年,今天咱们聊聊BMS数据采集这个核心话题。

说白了,BMS就是电池的“大脑”。它要是采集不准,后面所有算法都是白搭。我见过太多项目,算法模型建得漂漂亮亮,结果一上线就崩——查到最后,都是数据采集环节埋的雷。

这一章,咱们把BMS数据采集的四个关键点掰开揉碎讲清楚:单体电压、总电压与电流、温度传感器布局,还有采样策略。

BMS数据采集 单体电压采集 AFE芯片 + 差分采样 总电压/电流采集 霍尔传感器 / 分流器 温度传感器布局 NTC / 热电偶 精度 ±1mV 同步采样 隔离设计 卡尔曼滤波 电芯表面/极柱 采样周期 1s 核心目标:高精度 + 高可靠性 + 低延迟

4.1 电池单体电压采集

单体电压是BMS最基础、最重要的参数。为什么?因为SOC估算、SOH评估、均衡控制,全都依赖它。

我习惯用AFE(模拟前端)芯片来做采集。市面上主流的有TI的BQ系列、ADI的LTC系列、NXP的MC33771等。这些芯片内部集成了多通道ADC、隔离通信、均衡开关,一颗芯片就能搞定一串电池的电压采集。

关键指标:

  • 采样精度:通常要求 ±1mV ~ ±5mV
  • 采样速率:10ms ~ 100ms 每通道
  • 通道数:6通道、12通道、16通道不等
  • 共模电压范围:最高可达 60V 或更高

这里有个坑,我踩过。AFE芯片的采样精度,在数据手册上写得漂漂亮亮,但实际用起来受PCB布局影响很大。差分走线要等长,参考电压要干净,采样电容要靠近芯片引脚。我曾经在一个项目里,因为PCB走线没注意,导致单体电压采集误差达到了±8mV,均衡策略直接失效。

注意:单体电压采集必须使用差分采样方式。单端采样会引入共模误差,在高压电池组里尤其明显。

代码层面,AFE芯片通常通过SPI或I2C与MCU通信。下面是一个典型的初始化流程:

// AFE芯片初始化示例(伪代码)
void AFE_Init(void) {
    // 1. 配置采样通道
    AFE_SetChannel(ALL_CHANNELS);
    
    // 2. 设置采样速率
    AFE_SetSampleRate(10);  // 10ms采样周期
    
    // 3. 开启过压/欠压保护
    AFE_EnableProtection(OVERVOLTAGE | UNDERVOLTAGE);
    
    // 4. 启动连续采样模式
    AFE_StartConversion(CONTINUOUS_MODE);
}

// 读取单体电压
uint16_t AFE_ReadCellVoltage(uint8_t cell_index) {
    uint16_t raw_value = AFE_ReadRegister(CELL_VOLTAGE_REG + cell_index);
    // 转换为实际电压值(单位:mV)
    return raw_value * VOLTAGE_LSB;  // LSB = 0.1mV 或 0.305mV
}

4.2 电池组总电压与电流采集

总电压和电流,是计算功率、估算SOC的另一条腿。单体电压再准,总电压测偏了也不行。

总电压采集相对简单,用电阻分压加隔离运放就能搞定。但电流采集就讲究多了。

目前主流方案有两种:

方案 原理 精度 成本 适用场景
霍尔传感器 霍尔效应 ±0.5% ~ ±2% 中等 大电流、非接触
分流器 采样电阻 + 差分运放 ±0.1% ~ ±0.5% 高精度、小体积

我个人更倾向于分流器方案,尤其是做SOC估算时。霍尔传感器受温度影响大,零漂也明显。分流器只要选好温漂系数(比如50ppm/℃以下),配合高精度ADC,能做到长期稳定。

小技巧:电流采样建议用24位Σ-Δ ADC,比如TI的ADS1262或ADI的AD7175。配合分流器,分辨率能做到1mA级别。

但分流器有个致命弱点——隔离问题。分流器两端直接连在高压回路里,MCU侧必须做隔离。我见过有人图省事,直接用光耦隔离模拟信号,结果噪声大得没法看。正确的做法是用隔离式ADC,或者用隔离电源加数字隔离器。

// 电流采样数据处理
typedef struct {
    int32_t raw_current;      // 原始ADC值
    float calibrated_current; // 校准后电流(A)
    float accumulated_ah;     // 累积安时
    uint32_t timestamp;       // 时间戳
} CurrentData;

void Current_Sample(CurrentData *data) {
    // 读取ADC值
    data->raw_current = ADC_Read(CURRENT_CHANNEL);
    
    // 校准:减去零漂,乘以增益
    data->calibrated_current = (data->raw_current - ZERO_OFFSET) * CURRENT_GAIN;
    
    // 累积安时(用于SOC估算)
    static uint32_t last_time = 0;
    uint32_t now = GetSystemTime();
    float dt = (now - last_time) / 1000.0;  // 秒
    data->accumulated_ah += data->calibrated_current * dt / 3600.0;
    last_time = now;
}

4.3 温度传感器布局与采样策略

温度采集,很多人不重视。觉得随便贴几个NTC就行了。其实不然。

电池的温度分布是不均匀的。电芯中心温度比表面高,正极比负极热,充放电时温升速率也不同。如果传感器布局不合理,你采到的温度可能跟实际电芯温度差好几度。

我建议的布局原则:

  • 每个模组至少2个传感器:一个在进风口,一个在出风口
  • 电芯表面贴装:贴在电芯大面中心位置,避开极柱
  • 关键位置加密:电池组中间位置、靠近发热元件的位置,传感器密度加倍
  • 采样周期:温度变化慢,1秒采样一次足够,但滤波要做

经验数据:一个13串48V电池模组,我通常布置6~8个NTC传感器。其中4个贴在电芯表面,2个测环境温度,2个测汇流排温度。

采样策略上,我习惯用滑动平均滤波。温度信号噪声不大,但容易受气流影响。滑动窗口取5~10个点,既能滤掉毛刺,又不会延迟太大。

// 温度滑动平均滤波
#define TEMP_FILTER_WINDOW 10

float Temperature_Filter(float new_temp) {
    static float buffer[TEMP_FILTER_WINDOW] = {0};
    static uint8_t index = 0;
    static uint8_t count = 0;
    
    buffer[index] = new_temp;
    index = (index + 1) % TEMP_FILTER_WINDOW;
    if (count < TEMP_FILTER_WINDOW) count++;
    
    float sum = 0;
    for (uint8_t i = 0; i < count; i++) {
        sum += buffer[i];
    }
    return sum / count;
}

警告:NTC的B值精度直接影响测温精度。我建议用B值精度±0.5%以内的NTC,并且每批来料都要抽检。曾经有个供应商给我送了B值偏差2%的NTC,整批货全退了。

嗯,关于温度还有一个容易被忽略的点——热平衡时间。电芯内部温度变化到表面,需要几十秒甚至几分钟。所以温度采样不需要太快,但滤波时间常数要匹配热响应。我一般设1秒采样一次,10秒滑动平均,效果不错。

好了,BMS数据采集这块,核心就是三个字:准、稳、快。准是精度,稳是抗干扰,快是实时性。三者缺一不可。

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