'''2024.3.28更新,这些是已经可以跑通的代码,大家自行取用
CALCE放电过程:CALCE电池数据CS2_35放电过程的IC曲线处理代码--对于异常值处理方式是直接舍弃
CALCE充电过程:CALCE电池数据CS2_35充电过程的IC曲线处理代码--对于异常值处理方式是使用前一个循环的数据进行替代
MIT放电过程:
NASA充电过程:
Oxford充电过程:
这些对某一块电池进行的数据处理,不同电池不同处理方式,还需要自己理解后根据实际情况处理
'''
之前处理的MIT数据集的IC曲线主要是从放电阶段的数据中提取的,这是由于其充电阶段为多阶段的快速充电策略,无法满足IC曲线导出的CCCV条件,而一些更老的数据集如NASA与Oxford电池数据集则是传统的CCCV策略,由此此篇博客我们开始从他们的充电阶段中提取出IC曲线,并讲解一些mat文件读取的注意事项。
NASA电池数据集
每个电池存储为单个的mat文件, 数据存储为充放电混存,因此需要提前将充电和放电周期分开,而每个周期内的数据有“Voltage_measured”,“Current_measured”,“Temperature_measured”,“Current_charge”,“Voltage_charge”,“Time”六个变量,数据结构读取为(B0005.cycle(1).data.Voltage_measured),了解这种结构后方便后续我们读取操作。由于我们只提取IC曲线和放电容量,所以只需用到实际传感器采集的“Voltage_measured”,“Current_measured”和“Time”变量,而放电容量在放电片段直接有记录,无需复杂提取。
开始python部分的数据处理,使用loadmat读取mat数据,这里有个值得注意的是,当读取到“cycle”结构后,并不是如matlab中直接以矩阵结构展示,而是读取成了一个(1,1)的矩阵,我们需要进入矩阵才能索引列变量,所以有[0,0][0]的处理。
#data getin
matFilename = './dataset/B0005.mat'
Battery = scipy.io.loadmat(matFilename)
list(Battery.keys())
# 获取锂电池充电或放电时的测试数据
cycle_data=Battery['B0005']['cycle'][0,0][0]
charge=[]
for cycle in cycle_data:
if cycle['type'] == 'charge':
charge.append(cycle['data'])
print("充电循环次数:",len(charge))
#提取放电容量数据
capacity = []
for cycle in cycle_data:
if cycle['type'] == 'discharge':
capacity.append(cycle['data'][0,0]['Capacity'][0])
print("放电循环次数:",len(capacity))
plt.plot(capacity)
#与充电循环存在两个cycle差距,舍弃充电数据的第一个(电池准备操作,存在大的异常)和最后一个循环(这个循环没有放电数据)
得到的放电容量图如下,NASA的电池具有明显的容量增生情况,如果大家需要减少这种情况,可以采用核滤波或者EMD分解(这个比较常见用于处理容量增生情况)。
然后进行IC曲线的提取,这里我们设定一个最低的dV值,避免由于采样点过于密集导致dV过小,出现较大的异常值噪声,我们一般设置为0.004V,dQ使用梯形近似积分逼近实际情况,以下代码展示直接从源数据提取出的IC曲线情况。
#查看原始的IC曲线
plt.plot(figsize=(10,5))
for cyc in range (len(charge)):
v=charge[cyc]['Voltage_measured'][0,0].T
c=charge[cyc]['Current_measured'][0,0].T
t=charge[cyc]['Time'][0,0].T
v,c,t=np.squeeze(v),np.squeeze(c),np.squeeze(t)
v,c,t=v.reshape(-1),c.reshape(-1),t.reshape(-1)
#print(v.shape,c.shape,t.shape)
step = 0.004 # 电压微分最小值,防止dV过小导致的噪声阶跃
numV = len(v) # 索引
i = 0
#补充一些边缘点的值,防止数值过大
dV = [1000]
Vind = [3.10]
dQ = [0]
while i < (numV - 2):
diff = 0
j = 0
# 寻找符合电压微分最小值的间隔点
while (diff < step and (i + j) < (numV - 1)):
j += 1
diff = abs(v[i + j] - v[i])
# 检查是否到达下限,末尾反复波动,截止电压为3.4V
#选择结束末尾的插值点
if (diff < step or v[i] > 4.194):
i += numV - 2
continue
else:
dt = np.diff(t[i:i + j + 1])/3600 # 单位h小时
ch_c1 = c[i:i + j + 1]
dc = ch_c1[:-1] + np.diff(ch_c1) * 0.5 # 电流微分,每两个点取一个均值,单位A
dQ.append(np.sum(dc * dt))
dV.append(diff)
Vind.append(v[i] * 0.5 + v[i + j] * 0.5)#取两个点的均值
i += 1
continue
dV.append(dV[-1])
Vind.append(4.20)
dQ.append(dQ[-1])
if (min(Vind)<3):
continue
dQdV = np.array(dQ) / np.array(dV)
#去除相同V值对应的dQdV
unique_V, unique_indices = np.unique(Vind, return_index=True)
unique_dQdV = []
for i in range(len(unique_V)):
indices = np.where(Vind == unique_V[i])[0]
mean_dQdV = np.mean(dQdV[indices])
unique_dQdV.append(mean_dQdV)
plt.plot(unique_V,unique_dQdV)
#print(diff_v.shape,diff_t.shape,diff_c.shape)
#plt.plot(range(len(dQdV)),dQdV)
可以看到IC曲线的特征较为明显的被处理出来了, 但部分循环存在异常,对于图中这种情况,只需对于V为4的点做一个限制,若dQ/dV<1,则使用前一个循环进行替代由此处理异常情况。
最终处理后的结果为,当然若觉得不够光滑,可自己选择合适的滤波窗口进行处理,尽量在特征保留和平滑中取得一个平衡
Oxford数据集
Oxford在python中读取仍有NASA读取时的问题,类似的处理方式进行操作就行,按照Oxford的数据结构进行处理即可。类似的处理后结果如图
欢迎批评指正,如果本文对您有帮助,顺手点赞收藏关注博主,谢谢您的阅读。
本文仅供参考,引用请标注来源,禁止copy。