|
@@ -3,8 +3,8 @@ import numpy as np
|
|
|
import datetime
|
|
|
import bisect
|
|
|
import matplotlib.pyplot as plt
|
|
|
-from LIB.MIDDLE.CellStateEstimation.SOH.V1_0_0 import BatParam
|
|
|
-from LIB.MIDDLE.CellStateEstimation.SOH.V1_0_0 import DBDownload
|
|
|
+# from LIB.MIDDLE.CellStateEstimation.SOH.V1_0_0 import BatParam
|
|
|
+# from LIB.MIDDLE.CellStateEstimation.SOH.V1_0_0 import DBDownload
|
|
|
import BatParam
|
|
|
import DBDownload
|
|
|
|
|
@@ -15,7 +15,7 @@ class BatSoh:
|
|
|
self.celltype=celltype
|
|
|
self.param=BatParam.BatParam(celltype)
|
|
|
self.df_bms=df_bms
|
|
|
- self.packcrnt=df_bms['总电流[A]']
|
|
|
+ self.packcrnt=df_bms['总电流[A]']*self.param.PackCrntDec
|
|
|
self.packvolt=df_bms['总电压[V]']
|
|
|
self.bms_soc=df_bms['SOC[%]']
|
|
|
self.bms_soh=df_bms['SOH[%]']
|
|
@@ -120,6 +120,107 @@ class BatSoh:
|
|
|
s = str(j)
|
|
|
cellvolt.append(self.df_bms.loc[num,'单体电压' + s]/1000)
|
|
|
return cellvolt
|
|
|
+
|
|
|
+ def _dvdq_soh(self, chrg_st, chrg_end,cellvolt): #dvdq方法计算soh
|
|
|
+ Ah = 0 #参数赋初始值
|
|
|
+ Volt = cellvolt[chrg_st]
|
|
|
+ DV_Volt=[]
|
|
|
+ DQ_Ah = []
|
|
|
+ DVDQ = []
|
|
|
+ time2 = []
|
|
|
+ soc2 = []
|
|
|
+ Ah_tatal=[0]
|
|
|
+ xvolt=[]
|
|
|
+ #计算DV和DQ值
|
|
|
+ for j in range(chrg_st,chrg_end):
|
|
|
+ Step=(self.bmstime[j+1]-self.bmstime[j]).total_seconds()
|
|
|
+ Ah=Ah-self.packcrnt[j]*Step/3600
|
|
|
+ if (cellvolt[j]-Volt)>0.0009 and Ah>0:
|
|
|
+ Ah_tatal.append(Ah_tatal[-1]+Ah)
|
|
|
+ DQ_Ah.append(Ah)
|
|
|
+ DV_Volt.append(cellvolt[j]-Volt)
|
|
|
+ DVDQ.append((DV_Volt[-1])/DQ_Ah[-1])
|
|
|
+ xvolt.append(cellvolt[j])
|
|
|
+ Volt=cellvolt[j]
|
|
|
+ Ah = 0
|
|
|
+ time2.append(self.bmstime[j])
|
|
|
+ soc2.append(self.bms_soc[j])
|
|
|
+
|
|
|
+ #切片,去除前后10min的数据
|
|
|
+ df_Data1 = pd.DataFrame({'time': time2,
|
|
|
+ 'SOC': soc2,
|
|
|
+ 'DVDQ': DVDQ,
|
|
|
+ 'Ah_tatal': Ah_tatal[:-1],
|
|
|
+ 'DQ_Ah':DQ_Ah,
|
|
|
+ 'DV_Volt':DV_Volt,
|
|
|
+ 'XVOLT':xvolt})
|
|
|
+ start_time=df_Data1.loc[0,'time']
|
|
|
+ start_time=start_time+datetime.timedelta(seconds=900)
|
|
|
+ end_time=df_Data1.loc[len(time2)-1,'time']
|
|
|
+ end_time=end_time-datetime.timedelta(seconds=1200)
|
|
|
+ if soc2[0]<40:
|
|
|
+ df_Data1=df_Data1[(df_Data1['SOC']>43) & (df_Data1['time']<end_time)]
|
|
|
+ else:
|
|
|
+ df_Data1=df_Data1[(df_Data1['time']>start_time) & (df_Data1['time']<end_time)]
|
|
|
+
|
|
|
+ # ax1 = plt.subplot(3, 1, 1)
|
|
|
+ # plt.plot(df_Data1['XVOLT'],df_Data1['DVDQ'],'r*-')
|
|
|
+ # plt.xlabel('Volt/V')
|
|
|
+ # plt.ylabel('DV/DQ')
|
|
|
+ # plt.legend()
|
|
|
+ # ax1 = plt.subplot(3, 1, 2)
|
|
|
+ # plt.plot(df_Data1['SOC'],df_Data1['XVOLT'],'y*-')
|
|
|
+ # plt.xlabel('SOC/%')
|
|
|
+ # plt.ylabel('Volt/V')
|
|
|
+ # plt.legend()
|
|
|
+ # ax1 = plt.subplot(3, 1, 3)
|
|
|
+ # plt.plot(df_Data1['SOC'], df_Data1['DVDQ'], 'r*-')
|
|
|
+ # plt.xlabel('SOC/%')
|
|
|
+ # plt.ylabel('DV/DQ')
|
|
|
+ # plt.legend()
|
|
|
+ # plt.show()
|
|
|
+
|
|
|
+ #寻找峰值并计算Soh
|
|
|
+ if len(df_Data1)>1:
|
|
|
+ PeakIndex=df_Data1['DVDQ'].idxmax()
|
|
|
+ #筛选峰值点附近±0.5%SOC内的数据
|
|
|
+ df_Data2=df_Data1[(df_Data1['SOC']>(df_Data1['SOC'][PeakIndex]-0.5)) & (df_Data1['SOC']<(df_Data1['SOC'][PeakIndex]+0.5))]
|
|
|
+ if len(df_Data2)>2:
|
|
|
+ Ah_tatal1 = df_Data1['Ah_tatal']
|
|
|
+ DVDQ = df_Data1['DVDQ']
|
|
|
+ soc2 = df_Data1['SOC']
|
|
|
+ xvolt = df_Data1['XVOLT']
|
|
|
+ if soc2[PeakIndex]>43 and soc2[PeakIndex]<90:
|
|
|
+ cellsoh_init=(Ah_tatal[-1]-Ah_tatal1[PeakIndex]) * 100 / ((self.param.FullChrgSoc - self.param.PeakSoc) * 0.01 * self.param.Capacity)
|
|
|
+ if cellsoh_init<95:
|
|
|
+ cellsoh_init=cellsoh_init*0.3926+58.14
|
|
|
+ return cellsoh_init
|
|
|
+ else:
|
|
|
+ return cellsoh_init
|
|
|
+ else:
|
|
|
+ return 0
|
|
|
+ else:
|
|
|
+ df_Data1=df_Data1.drop([PeakIndex])
|
|
|
+ PeakIndex = df_Data1['DVDQ'].idxmax()
|
|
|
+ df_Data2 = df_Data1[(df_Data1['SOC'] > (df_Data1['SOC'][PeakIndex] - 0.5)) & (df_Data1['SOC'] < (df_Data1['SOC'][PeakIndex] + 0.5))]
|
|
|
+ if len(df_Data2) > 2:
|
|
|
+ Ah_tatal1 = df_Data1['Ah_tatal']
|
|
|
+ DVDQ = df_Data1['DVDQ']
|
|
|
+ soc2 = df_Data1['SOC']
|
|
|
+ xvolt = df_Data1['XVOLT']
|
|
|
+ if soc2[PeakIndex]>40 and soc2[PeakIndex]<90:
|
|
|
+ cellsoh_init=(Ah_tatal[-1]-Ah_tatal1[PeakIndex]) * 100 / ((self.param.FullChrgSoc - self.param.PeakSoc) * 0.01 * self.param.Capacity)
|
|
|
+ if cellsoh_init<95:
|
|
|
+ cellsoh_init=cellsoh_init*0.3926+58.14
|
|
|
+ return cellsoh_init
|
|
|
+ else:
|
|
|
+ return cellsoh_init
|
|
|
+ else:
|
|
|
+ return 0
|
|
|
+ else:
|
|
|
+ return 0
|
|
|
+ else:
|
|
|
+ return 0
|
|
|
|
|
|
def _ncmsoh_chrg(self): #NCM充电数据soh计算
|
|
|
self._chrgdata()
|
|
@@ -587,129 +688,33 @@ class BatSoh:
|
|
|
if chrg_end:
|
|
|
for i in range(len(chrg_end)):
|
|
|
cellvolt_max = self.df_bms['单体电压' + str(cellmaxvolt_number2[i]+1)] / 1000 #获取最大电压
|
|
|
- cellvolt=self._np_move_avg(cellvolt_max, 3, mode="same") #对电压进行滑动平均滤波
|
|
|
-
|
|
|
- Ah = 0 #参数赋初始值
|
|
|
- Volt = cellvolt[chrg_start[i]]
|
|
|
- DV_Volt=[]
|
|
|
- DQ_Ah = []
|
|
|
- DVDQ = []
|
|
|
- time2 = []
|
|
|
- soc2 = []
|
|
|
- Ah_tatal=[0]
|
|
|
- xvolt=[]
|
|
|
- #计算DV和DQ值
|
|
|
- for j in range(chrg_start[i],chrg_end[i]):
|
|
|
- Step=(self.bmstime[j+1]-self.bmstime[j]).total_seconds()
|
|
|
- Ah=Ah-self.packcrnt[j]*Step/3600
|
|
|
- if (cellvolt[j]-Volt)>0.0009 and Ah>0:
|
|
|
- Ah_tatal.append(Ah_tatal[-1]+Ah)
|
|
|
- DQ_Ah.append(Ah)
|
|
|
- DV_Volt.append(cellvolt[j]-Volt)
|
|
|
- DVDQ.append((DV_Volt[-1])/DQ_Ah[-1])
|
|
|
- xvolt.append(cellvolt[j])
|
|
|
- Volt=cellvolt[j]
|
|
|
- Ah = 0
|
|
|
- time2.append(self.bmstime[j])
|
|
|
- soc2.append(self.bms_soc[j])
|
|
|
-
|
|
|
- #切片,去除前后10min的数据
|
|
|
- df_Data1 = pd.DataFrame({'time': time2,
|
|
|
- 'SOC': soc2,
|
|
|
- 'DVDQ': DVDQ,
|
|
|
- 'Ah_tatal': Ah_tatal[:-1],
|
|
|
- 'DQ_Ah':DQ_Ah,
|
|
|
- 'DV_Volt':DV_Volt,
|
|
|
- 'XVOLT':xvolt})
|
|
|
- start_time=df_Data1.loc[0,'time']
|
|
|
- start_time=start_time+datetime.timedelta(seconds=900)
|
|
|
- end_time=df_Data1.loc[len(time2)-1,'time']
|
|
|
- end_time=end_time-datetime.timedelta(seconds=1200)
|
|
|
- if soc2[0]<40:
|
|
|
- df_Data1=df_Data1[(df_Data1['SOC']>43) & (df_Data1['time']<end_time)]
|
|
|
- else:
|
|
|
- df_Data1=df_Data1[(df_Data1['time']>start_time) & (df_Data1['time']<end_time)]
|
|
|
-
|
|
|
- # ax1 = plt.subplot(3, 1, 1)
|
|
|
- # plt.plot(df_Data1['XVOLT'],df_Data1['DVDQ'],'r*-')
|
|
|
- # plt.xlabel('Volt/V')
|
|
|
- # plt.ylabel('DV/DQ')
|
|
|
- # plt.legend()
|
|
|
- # ax1 = plt.subplot(3, 1, 2)
|
|
|
- # plt.plot(df_Data1['SOC'],df_Data1['XVOLT'],'y*-')
|
|
|
- # plt.xlabel('SOC/%')
|
|
|
- # plt.ylabel('Volt/V')
|
|
|
- # plt.legend()
|
|
|
- # ax1 = plt.subplot(3, 1, 3)
|
|
|
- # plt.plot(df_Data1['SOC'], df_Data1['DVDQ'], 'r*-')
|
|
|
- # plt.xlabel('SOC/%')
|
|
|
- # plt.ylabel('DV/DQ')
|
|
|
- # plt.legend()
|
|
|
- # plt.show()
|
|
|
-
|
|
|
- #寻找峰值并计算Soh和置信度
|
|
|
- if len(df_Data1)>1:
|
|
|
- PeakIndex=df_Data1['DVDQ'].idxmax()
|
|
|
- #筛选峰值点附近±0.5%SOC内的数据
|
|
|
- df_Data2=df_Data1[(df_Data1['SOC']>(df_Data1['SOC'][PeakIndex]-0.5)) & (df_Data1['SOC']<(df_Data1['SOC'][PeakIndex]+0.5))]
|
|
|
- if len(df_Data2)>2:
|
|
|
- Ah_tatal1 = df_Data1['Ah_tatal']
|
|
|
- DVDQ = df_Data1['DVDQ']
|
|
|
- soc2 = df_Data1['SOC']
|
|
|
- xvolt = df_Data1['XVOLT']
|
|
|
- if soc2[PeakIndex]>43 and soc2[PeakIndex]<90:
|
|
|
- cellsoh_init=(Ah_tatal[-1]-Ah_tatal1[PeakIndex]) * 100 / ((self.param.FullChrgSoc - self.param.PeakSoc) * 0.01 * self.param.Capacity)
|
|
|
- if cellsoh_init<95:
|
|
|
- cellsoh_init=cellsoh_init*0.3926+58.14
|
|
|
- else:
|
|
|
- pass
|
|
|
- else:
|
|
|
- continue
|
|
|
- else:
|
|
|
- df_Data1=df_Data1.drop([PeakIndex])
|
|
|
- PeakIndex = df_Data1['DVDQ'].idxmax()
|
|
|
- df_Data2 = df_Data1[(df_Data1['SOC'] > (df_Data1['SOC'][PeakIndex] - 0.5)) & (df_Data1['SOC'] < (df_Data1['SOC'][PeakIndex] + 0.5))]
|
|
|
- if len(df_Data2) > 2:
|
|
|
- Ah_tatal1 = df_Data1['Ah_tatal']
|
|
|
- DVDQ = df_Data1['DVDQ']
|
|
|
- soc2 = df_Data1['SOC']
|
|
|
- xvolt = df_Data1['XVOLT']
|
|
|
- if soc2[PeakIndex]>40 and soc2[PeakIndex]<90:
|
|
|
- cellsoh_init=(Ah_tatal[-1]-Ah_tatal1[PeakIndex]) * 100 / ((self.param.FullChrgSoc - self.param.PeakSoc) * 0.01 * self.param.Capacity)
|
|
|
- if cellsoh_init<95:
|
|
|
- cellsoh_init=cellsoh_init*0.3926+58.14
|
|
|
- else:
|
|
|
- pass
|
|
|
- else:
|
|
|
- continue
|
|
|
- else:
|
|
|
- continue
|
|
|
-
|
|
|
- soh_weight=tempweightlist2[i]*0.25
|
|
|
- if cellsoh_init>65 and cellsoh_init<115: #判断soh值的有效区间
|
|
|
- if len(df_res)<1:
|
|
|
- if not self.df_soh.empty:
|
|
|
- cellsoh_last=self.df_soh.loc[len(self.df_soh)-1,'soh']
|
|
|
- if soh_weight>1/abs(cellsoh_init-cellsoh_last):
|
|
|
- soh_weight=1/abs(cellsoh_init-cellsoh_last)
|
|
|
- cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last*(1-soh_weight)
|
|
|
- else:
|
|
|
- cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last*(1-soh_weight)
|
|
|
- else:
|
|
|
- cellsoh_cal=cellsoh_init*soh_weight+100*(1-soh_weight)
|
|
|
- else:
|
|
|
- cellsoh_last=df_res.loc[len(df_res)-1,'soh']
|
|
|
+ cellvolt=self._np_move_avg(cellvolt_max, 3, mode="same") #对电压进行滑动平均滤
|
|
|
+
|
|
|
+ cellsoh_init=self._dvdq_soh(chrg_start[i],chrg_end[i],cellvolt) #dvdq计算soh
|
|
|
+
|
|
|
+ soh_weight=tempweightlist2[i]*0.25
|
|
|
+ if cellsoh_init>65 and cellsoh_init<115: #判断soh值的有效区间
|
|
|
+ if len(df_res)<1:
|
|
|
+ if not self.df_soh.empty:
|
|
|
+ cellsoh_last=self.df_soh.loc[len(self.df_soh)-1,'soh']
|
|
|
if soh_weight>1/abs(cellsoh_init-cellsoh_last):
|
|
|
soh_weight=1/abs(cellsoh_init-cellsoh_last)
|
|
|
cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last*(1-soh_weight)
|
|
|
else:
|
|
|
cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last*(1-soh_weight)
|
|
|
-
|
|
|
- cellsoh_cal=eval(format(cellsoh_cal,'.1f'))
|
|
|
- soh_list=[self.bmstime[chrg_start[i]], self.bmstime[chrg_end[i]], self.sn, 2, cellsoh_cal, str(cellsoh_cal)]
|
|
|
- df_res.loc[len(df_res)]=soh_list
|
|
|
+ else:
|
|
|
+ cellsoh_cal=cellsoh_init*soh_weight+100*(1-soh_weight)
|
|
|
else:
|
|
|
- continue
|
|
|
+ cellsoh_last=df_res.loc[len(df_res)-1,'soh']
|
|
|
+ if soh_weight>1/abs(cellsoh_init-cellsoh_last):
|
|
|
+ soh_weight=1/abs(cellsoh_init-cellsoh_last)
|
|
|
+ cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last*(1-soh_weight)
|
|
|
+ else:
|
|
|
+ cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last*(1-soh_weight)
|
|
|
+
|
|
|
+ cellsoh_cal=eval(format(cellsoh_cal,'.1f'))
|
|
|
+ soh_list=[self.bmstime[chrg_start[i]], self.bmstime[chrg_end[i]], self.sn, 2, cellsoh_cal, str(cellsoh_cal)]
|
|
|
+ df_res.loc[len(df_res)]=soh_list
|
|
|
else:
|
|
|
continue
|
|
|
else:
|