锂离子电池无论是在军用还是民用领域都得到了广泛的应用,在锂离子电池健康评估中主要关注的参数有SOH和RUL。准确对其进行健康状态(Stateof Health, SOH)评估及剩余使用寿命(Remaning Useful Life, RUL)预测对于提高电池安全性与使用寿命具有重要意义
后续源码仓库:https://github.com/Wuito/Estimation-of-residual-life-of-particle-filter-lithium-ion-battery
电池SOH
锂离子电池健康状态基本定义为:选择适当的放电条件下,对其进行充电,直到锂电池充满结束。然后再选择一定倍率对其进行放电,直到满足放电截止电压结束,此时电池的容量与其标称容量的比值。即为锂离子电池的健康状态,通常运用SOH表示电池的健康状态。锂离子电池的存储能力与快速充放电能力均会随着老化而不断下降,而SOH正是用于评价锂电池老化程度的量化指标,锂离子电池健康状态是表征锂电池存储电能的能力,和电池老化评价指标。锂电池的健康状态定义方式有多种,分别为基于容量定义的SOH、基于内阻定义的SOH、基于功率定义的SOH、基于自放电定义的SOH。
电池RUL
锂离子电池寿命是个广义的概念,它还可以具体分为很多种,如储存寿命,使用寿命和剩余循环寿命。锂离子电池的存储寿命表示锂离子电池在静态或非运行条件下退化到一定程度所需的时间。锂离子电池的RUL是指在某种充放电条件下,锂离子电池的当前可用容量衰减退化到某一规定的失效阈值所需要经历的循环周期数量。RUL预测是一个基于锂离子电池历史数据运用一定的数学手段对其残值寿命进行预测计算的过程。随着锂离子电池在各领域上的广泛应用,锂离子电池RUL预测技术得到了广泛的关注和研究。
常用锂离子电池寿命经验模型的数学表达式
锂离子电池结构
锂离子电池主要由以下几个部分组成:
(1)正极活性材料
正极活性材料是锂离子电池的核心组成部分,其决定了锂电池工作时锂离子的空间和扩散路径,由此决定了锂离子电池的基本性能。目前业内常见的正极材料有磷酸铁锂、锰酸锂、钴酸锂、以及由多种材料构成的三元锂,如镍钴锰、镍钴铝。
(2)负极活性材料
负极活性材料是以薄层状附着在铜基上的糊状物质,通常由碳材料、黏合材料以及有机溶剂混合制成。
(3)隔膜
隔膜是一种经过特殊工艺处理的高分子薄膜,通常使用聚丙烯或聚乙烯材料的微多孔膜制成,用于在正极和负极之间作为锂离子的移动通道,同时能够防止电子通过。
(4)电解液
电解液主要负责在充放电过程中锂离子的传送,通常为混有有机溶剂和添加剂的锂盐电解液。电解液需要能够在电池工作过程时的氧化还原反应中保持化学性能稳定。
基本性能参数
(1)电池电压
电动势:电池正极与负极之间的电位差。
工作电压(端电压):在电池两端接上负载后,在放电过程中显示的电压。开路电压:指电池处于开路状态,即电池不放电时电池正负极的电位差。
额定电压:指电池厂家规定的电池电压,是电池出厂的重要性能参数,电池正常工作时,电池工作电压应该长时间在电池额定电压附近变化。
终止电压:电池在一定标准所规定的充放电条件下对电池进行充放电,当电池不宜再继续充放电时,此时的工作电压称为终止电压。当电池的电压下降到终止电压后,再继续使用,因受到化学“活性物质”性能的限制,“活性物质”会遭到破坏。
(2)电池容量
理论容量:是假设活性物质全部参加电池的反应所给出的电量。它是根据活性物质的量按照法拉第定律计算求得的。实际电池放出的容量只是理论容量的一部分。
实际容量:是指在一定条件下,电池实际放出的电量,等于放电电流与放电时间的乘积。
剩余容量:指电池经过一段时间的放电之后电池还剩余多少电量,数值上等于电池在当前状态下以标准环境温度和标准放电电流放电至最小截止电压时释放的电量。
额定容量:是指设计和制造电池时,规定或保证电池在一定的放电条件下应该放出的最低限度的电量。
(3)电池自放电率
电池自放电率衡量了电池在静置状态时,对其自身电量的保持能力。通常电池自放电率越小越好,其大小与环境温度、电池材料和加工方式密切相关。一般而言,在电池适宜的温度范围内,环境温度越低,自放电率也越低,同时也应注意,温度过低或过高均有可能造成电池损坏而无法正常投入使用。
(4)放电深度:
放电深度是放电程度的一种度量,常用 DOD(depth of discharge)表示,它体现参与反应的活性材料所占的比例。
(5)电池内阻:
该指标是指电流通过电池内部时受到的阻力,包括欧姆内阻和极化内阻两部分。由于电池的内阻作用,使得电池在放电时端电压低于电动势和开路电压,在充电时端电高于电动势和开路电压。
锂离子电池的充电特征
电池经过长时间的放电后,需要对电池再次充电才能投入使用。电池过充电对电池性能影响很大,过度充电会对电池造成损坏,缩短使用寿命,因此,选择安全高效的电池充电方式对保护电池至关重要。目前,常用的电池充电方式有恒流充电法、恒压充电法、恒流恒压充电法(Constant Current-Constant Voltage ,CC-CV)以及脉冲式充电法。
恒流充电法是指在整个充电过程中,保持电池充电回路中电流保持不变的充电方法。通常可以利用调整电源输出电压或改变充电回路阻值的方式使得充电电流不变。该方法较为容易实施,充电时间短,但电池到了充电后期,对电流的接受能力逐渐下降,会造成了能量的浪费。
恒压充电法是在整个充电过程中,让电源输出电压保持不变的充电方法。使用该方法对电池进行充电时,充电回路中的电流会逐渐减小,从而减少能量浪费及防止电池过充电,但在充电初期,充电回路中的电流太大,会减少电池工作时间,电流过大时还有可能导致电池报废。
恒流恒压充电法是指电池先以恒流方式充电,使得电池电压逐步升高,当电池电压达到充电截止电压时,再将恒流充电方式转换为恒压充电方式。恒流恒压充电模式是普通锂离子电池最常用的充电方式,该方法能够快速充电,有效防止电池过充电,合理利用能量,延长电池的使用寿命。
上面图里的数据是从马里兰大学公开电池数据集得到的CS2电池组数据。马里兰大学寿命实验室
锂离子SOH定义
1)基于容量定义的健康状态
采用当前锂电池的额定容量比上初始是锂电池的容量,再乘上100%,即为锂离子电池的容量健康度。
式中,〖SOH〗_c为电池容量健康度,C_t为电池在t时刻的额定容量,C_0为电池的初始额定容量。
2)基于内阻定义的健康状态
式中,〖SOH〗_R为电池内阻(通常指电池的欧姆内阻)健康度,R_end为电池寿命终止时刻的内阻,R(t)为电池在t时刻的内阻,R_0为电池的初始内阻。
3)基于功率定义的健康状态
式中,〖SOH〗_P为电池功率健康度,P(0)锂离子电池的最开始的功率或铭牌功率(W),P(t)第t次充电后可供给的方均根(有效)功率(W)。
4)基于自放电定义的健康状态
式中,〖SOH〗_Rd为电池自放电健康度,R_d (end)为电池寿命终止时刻的自放电电阻,R_d (t)为采样t时刻的电池自放电电阻,R_d (0)代表电池在初始时刻的自放电电阻。
数据预处理代码
首先要明白马里兰大学数据集的结构:
数据是以xlsx表格的格式存储的
包含的数据主要有这几个类别,其中有用得比较多的就是电流电压和时间这几项。
这里要特别注意:充电和放电的数据是连续记录在表里的,要注意区分。NASA的数据则是充电和放电分开的。
===================================
废话不多说,我们上干货,具体代码作用看注释,写的比较清楚了。编程细节参考浙大的大佬python的数据处理,感谢大佬,让我们减轻了很多工作量。代码里SOH是用上面SOH定义的第一种计算方法得到的。
# 程序功能: 读取一种电池的数据解析计算
# SOH,CCCT,CVCT,resistance,capacity数据并存储为npy文件
# From: SWUST IPC14 Dai
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import glob
Battery_name = 'CS2_36' # 加载数据
dir_path = 'dataset/'
# 除去数据异常的较大值和较小值点
def drop_outlier(array, count, bins):
index = []
range_ = np.arange(1, count, bins) # 返回一个有终点和起点的固定步长的排列,起始为1,终值为count,步长为bins
for i in range_[:-1]:
array_lim = array[i:i+bins] # 从array中截取一个从i到i+bins的数组段
sigma = np.std(array_lim) # 计算该数组段的全局标准差
mean = np.mean(array_lim) # 计算数组段的平均值
th_max,th_min = mean + sigma*2, mean - sigma*2 # 以方差和平均值作为上下限取值
idx = np.where((array_lim < th_max) & (array_lim > th_min))
idx = idx[0] + i # 将当前的idx值+i后赋值到实际数组的角标
index.extend(list(idx)) # 在列尾增加一个list
return np.array(index)
Battery = {}
print('Load the data directory structure ' + Battery_name + ' ...')
path = glob.glob(dir_path + Battery_name + '/*.xlsx')
dates = []
for p in path:
df = pd.read_excel(p, sheet_name=1)
print('Load file sequence ' + str(p) + ' ...')
dates.append(df['Date_Time'][0])
idx = np.argsort(dates)
path_sorted = np.array(path)[idx]
print("The file structure was read successfully. There are {} files in total".format(len(path_sorted)))
count = 0
discharge_capacities = []
health_indicator = []
internal_resistance = []
CCCT = []
CVCT = []
for p in path_sorted:
df = pd.read_excel(p, sheet_name=1)
print('Load and Analytical data' + str(p) + ' ...')
cycles = list(set(df['Cycle_Index'])) # 按照每个循环次数读取
# 在单个表中按照Cycle_Index(实验次数)逐次取出每次的数据进行处理
for c in cycles:
df_lim = df[df['Cycle_Index'] == c]
# Charging
df_c = df_lim[(df_lim['Step_Index'] == 2) | (df_lim['Step_Index'] == 4)] # 第2步和第4步充电
c_v = df_c['Voltage(V)'] # 电压
c_c = df_c['Current(A)'] # 实时电流值
c_t = df_c['Test_Time(s)'] # 记录的测试时间
# CC or CV
df_cc = df_lim[df_lim['Step_Index'] == 2] # 第2步恒流充电
df_cv = df_lim[df_lim['Step_Index'] == 4] # 第4步恒压充电
CCCT.append(np.max(df_cc['Test_Time(s)']) - np.min(df_cc['Test_Time(s)'])) # 恒定电流充电时间
CVCT.append(np.max(df_cv['Test_Time(s)']) - np.min(df_cv['Test_Time(s)'])) # 恒定电压充电时间
# Discharging
df_d = df_lim[df_lim['Step_Index'] == 7] # 第7步时放电
d_v = df_d['Voltage(V)']
d_c = df_d['Current(A)']
d_t = df_d['Test_Time(s)'] # 步长时间
d_im = df_d['Internal_Resistance(Ohm)'] # 内阻
if len(list(d_c)) != 0:
time_diff = np.diff(list(d_t)) # 求时间差,np.diff:计算数组中n[a]-n[a-1]
d_c = np.array(list(d_c))[1:] # 读出电流值
discharge_capacity = time_diff * d_c / 3600 # 计算安培时(Ah)Q = A*h
# print("discharge_capacity shape[0] is:{}".format(discharge_capacity.shape[0]))
# 将所有第7步中的电池放电容量求和并正定
# discharge_capacity_sum = np.sum(discharge_capacity)
# discharge_capacities.append(-1 * discharge_capacity_sum)
discharge_capacity = [np.sum(discharge_capacity[:n]) for n in range(discharge_capacity.shape[0])]
discharge_capacities.append(-1 * discharge_capacity[-1])
dec = np.abs(np.array(d_v) - 3.8)[1:] # np.abs:求绝对值
# np.argmin:将数组展平返回最小值的下标
start = np.array(discharge_capacity)[np.argmin(dec)] # 取出当电压最接近3.8V时电池的放电量
dec = np.abs(np.array(d_v) - 3.4)[1:]
end = np.array(discharge_capacity)[np.argmin(dec)] # 取出电压最接近3.4V时的电池放电量
health_indicator.append((-1 * (end - start))) # 这里定义的SOH是电池从3.8V放电到3.4V的电池容量
internal_resistance.append(np.mean(np.array(d_im))) # 求放电阶段电池的的内阻平均值
count += 1
health_indicator = health_indicator/np.max(health_indicator) # 计算SOH
discharge_capacities = np.array(discharge_capacities)
SOC = discharge_capacities/1.1 # CS2电池的标准容量为1.1Ah
health_indicator = np.array(health_indicator)
internal_resistance = np.array(internal_resistance)
CCCT = np.array(CCCT)
CVCT = np.array(CVCT)
idx = drop_outlier(discharge_capacities, count, 40) # 以所有轮次中放电步骤的放电容量值为原始数据,以40为步长,对数据进行清洗处理
df_result = pd.DataFrame({'cycle': np.linspace(1, idx.shape[0], idx.shape[0]), # 步数
'capacity': SOC[idx], # 容量
'SoH': health_indicator[idx], # SOH
'resistance': internal_resistance[idx], # 电池内阻
'CCCT': CCCT[idx],
'CVCT': CVCT[idx]})
Battery[Battery_name] = df_result
np.save(dir_path + Battery_name, Battery)
print("Data parsing succeeded. The .npy file was saved to {}".format(dir_path + Battery_name + '.npy'))