4、BMS数据采集详解:电池单体电压采集、电池组总电压与电流采集、温度传感器布局与采样策略
大家好,我是老张。在储能系统里摸爬滚打了十来年,今天咱们聊聊BMS数据采集这个核心话题。
说白了,BMS就是电池的“大脑”。它要是采集不准,后面所有算法都是白搭。我见过太多项目,算法模型建得漂漂亮亮,结果一上线就崩——查到最后,都是数据采集环节埋的雷。
这一章,咱们把BMS数据采集的四个关键点掰开揉碎讲清楚:单体电压、总电压与电流、温度传感器布局,还有采样策略。
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