第3章:电池数据采集与预处理
大家好,我是你们的老朋友。今天咱们聊聊电池数据采集与预处理。说实话,这部分工作看着不起眼,但我在项目里吃过不少亏。数据质量不行,后面建模再花哨也是白搭。
3.1 数据采集系统搭建
先说说硬件。我个人习惯用NI的采集卡,配合电流电压传感器。为什么?因为稳定。实验室里我见过有人用Arduino做采集,结果采样率一高就丢包,数据断断续续的,根本没法用。
采集系统的基本架构其实不复杂:
- 传感器:电流传感器(霍尔效应型)、电压传感器(差分放大型)、温度传感器(热电偶或PT100)
- 信号调理:滤波、放大、隔离
- ADC模块:至少16位分辨率,采样率看需求
- 数据记录:本地存储或云端上传
嗯,这里要注意一点。传感器和ADC之间的线缆一定要用屏蔽线。我曾经在项目里图省事用了普通杜邦线,结果50Hz工频干扰直接淹没了信号,花了三天才排查出来。
3.2 采样频率选择
采样频率怎么选?说白了就是看你的电池动态特性。锂离子电池的电压响应时间常数大概在秒级,所以采样频率不需要太高。
我一般遵循这个原则:
| 应用场景 | 推荐采样频率 | 说明 |
|---|---|---|
| 静态容量测试 | 0.1 Hz | 每10秒采一次就够了 |
| 动态工况测试 | 1-10 Hz | 比如UDDS工况 |
| 脉冲测试 | 100-1000 Hz | 捕捉瞬时电压降 |
| EIS测试 | 10 kHz以上 | 高频阻抗测量 |
你想想看,如果采样频率太低,电压平台期的微小变化就捕捉不到。但太高了也不行,数据量爆炸,存储和计算都吃不消。
3.3 数据清洗
数据清洗,说白了就是去脏数据。我见过太多人拿到原始数据直接建模,结果模型一塌糊涂。
3.3.1 异常值处理
异常值怎么判断?我常用3σ原则。假设数据服从正态分布,超过均值±3倍标准差的值就是异常。
import numpy as np
import pandas as pd
def detect_outliers(data, column, threshold=3):
mean = data[column].mean()
std = data[column].std()
outliers = data[np.abs(data[column] - mean) > threshold * std]
return outliers
# 示例:检测电压异常值
df = pd.read_csv('battery_data.csv')
voltage_outliers = detect_outliers(df, 'voltage')
print(f"发现 {len(voltage_outliers)} 个异常电压值")
还有一种情况,传感器突然跳变。比如电压从3.7V瞬间跳到4.5V又跳回来。这种我一般用差分法检测:
def detect_spikes(data, column, max_diff=0.5):
diff = data[column].diff().abs()
spikes = data[diff > max_diff]
return spikes
处理异常值,我通常用插值法。线性插值简单有效,但如果是连续多个异常点,我会用前后各5个点的均值来填充。
3.3.2 缺失值处理
缺失值很常见。采集卡偶尔掉线、通信中断,都会产生NaN。我的处理策略分三种:
- 删除法:缺失比例小于1%时,直接删掉那几行
- 前向填充:电池电压变化缓慢,用上一个有效值填充
- 插值法:时间序列数据,用前后值线性插值
# 前向填充
df['voltage'].fillna(method='ffill', inplace=True)
# 线性插值
df['current'].interpolate(method='linear', inplace=True)
3.4 数据归一化
归一化,说白了就是把不同量纲的数据拉到同一个尺度。电压是3-4V,电流是0-100A,温度是20-60°C,不归一化的话,模型会天然偏向数值大的特征。
我常用的两种方法:
3.4.1 Min-Max归一化
把数据映射到[0,1]区间。适合数据分布比较均匀的情况。
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
df[['voltage', 'current', 'temperature']] = scaler.fit_transform(
df[['voltage', 'current', 'temperature']]
)
3.4.2 Z-score标准化
把数据变成均值为0、标准差为1的分布。适合有异常值的情况。
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
df[['voltage', 'current', 'temperature']] = scaler.fit_transform(
df[['voltage', 'current', 'temperature']]
)
我个人习惯用Min-Max。为什么?因为电池数据范围相对固定,电压不会超过0-5V,电流也不会无限大。Min-Max后数据解释性更强。
3.5 本章知识体系
下面这张图是我自己画的,把整个数据采集与预处理流程串起来了。你跟着这个流程走,基本不会出大问题。
好了,这一章的内容就到这里。数据采集和预处理是基础中的基础,但也是最容易出问题的地方。你把这些步骤做扎实了,后面建模会顺畅很多。