import random import pandas as pd import numpy as np import datetime import BatParam # from matplotlib import pyplot as plt class BatSoh(): def __init__(self,sn,celltype,df_bms,df_soh): #参数初始化 self.sn=sn self.celltype=celltype self.param=BatParam.BatParam(celltype) self.df_bms=df_bms self.packcrnt=df_bms['PackCrnt']*self.param.PackCrntDec self.bms_soc=df_bms['PackSOC'] self.bms_soh=df_bms['PackSOH'] self.bmsstat=df_bms['BMSStat'] self.df_bms['time']= pd.to_datetime(df_bms['time'], format='%Y-%m-%d %H:%M:%S') self.bmstime=self.df_bms['time'] self.df_soh=df_soh self.cellvolt_name=['CellVolt'+str(x) for x in range(1,self.param.CellVoltNums+1)] self.celltemp_name=['CellTemp'+str(x) for x in range(1,self.param.CellTempNums+1)] def batsoh(self): if self.celltype<50: df_res=self._ncmsoh_twopoint() return df_res else: df_res=self._lfpsoh() return df_res #定义滑动滤波函数......................................................................................................................... def _np_move_avg(self, a, n, mode): return (np.convolve(a, np.ones((n,)) / n, mode=mode)) #筛选充电数据.............................................................................................................................. def _chrgdata(self): self.ChgStart=[] self.ChgEnd=[] if len(self.df_bms)>100: for i in range(3, len(self.bmstime) - 3): if i==3 and self.bmsstat[i]==2 and self.bmsstat[i+1]==2 and self.bmsstat[i+2]==2: self.ChgStart.append(i) elif self.bmsstat[i-2]!=2 and self.bmsstat[i-1]!=2 and self.bmsstat[i]==2: self.ChgStart.append(i) elif self.bmsstat[i-1]==2 and self.bmsstat[i]!=2 and self.bmsstat[i+1]!=2: self.ChgEnd.append(i-1) elif i == (len(self.bmstime) - 4) and self.bmsstat[len(self.bmsstat)-1] == 2 and self.bmsstat[len(self.bmsstat)-2] == 2: self.ChgEnd.append(len(self.bmstime)-2) #寻找当前行数据的最小温度值................................................................................................................. def _celltemp_weight(self,num): celltemp = list(self.df_bms.loc[num,self.celltemp_name]) celltemp.remove(min(celltemp)) self.celltemp=celltemp if self.celltype>50: if min(celltemp)>=25: self.tempweight=1 self.StandardStandingTime=3500 elif min(celltemp)>=15: self.tempweight=0.5 self.StandardStandingTime=4800 elif min(celltemp)>=5: self.tempweight=0.2 self.StandardStandingTime=10700 else: self.tempweight=0 self.StandardStandingTime=10800 else: if min(celltemp)>=25: self.tempweight=1 self.StandardStandingTime=1800 elif min(celltemp)>=15: self.tempweight=0.8 self.StandardStandingTime=3200 elif min(celltemp)>=5: self.tempweight=0.3 self.StandardStandingTime=7200 else: self.tempweight=0.1 self.StandardStandingTime=7200 #获取SOC差对应的SOH权重值................................................................................................................... def _deltsoc_weight(self,deltsoc): if deltsoc>60: deltsoc_weight=1 elif deltsoc>50: deltsoc_weight=0.9 elif deltsoc>40: deltsoc_weight=0.3 elif deltsoc>30: deltsoc_weight=0 elif deltsoc>20: deltsoc_weight=0 else: deltsoc_weight=0 return deltsoc_weight #获取当前行所有电压数据...................................................................................................................... def _cellvolt_get(self,num): cellvolt = self.df_bms.loc[num,self.cellvolt_name] return cellvolt #获取单个电压值................................................................................................. def _singlevolt_get(self,num,series,mode): #mode==1取当前行单体电压值,mode==2取某个单体所有电压值 s=str(series) if mode==1: singlevolt=self.df_bms.loc[num,'CellVolt' + s] return singlevolt else: singlevolt=self.df_bms['CellVolt' + s] return singlevolt #获取前5min每个电压的平均值........................................................................................ def _avgvolt_get(self,num): time_now=self.df_bms.loc[num, 'time'] time_last=time_now-datetime.timedelta(seconds=300) df_volt=self.df_bms[(self.df_bms['time']>=time_last) & (self.df_bms['time']<=time_now)] df_volt=df_volt[self.cellvolt_name] df_volt=df_volt[(df_volt>2) & (df_volt<4.5)] df_volt=df_volt.dropna() cellvolt_std=df_volt.std(axis=0) if len(df_volt)>2 and max(cellvolt_std)<0.005: cellvolt_sum=df_volt.sum(0)-df_volt.max(0)-df_volt.min(0) cellvolt_mean=cellvolt_sum/(len(df_volt)-2) cellvolt=cellvolt_mean elif len(df_volt)==2: # df_volt=pd.DataFrame(df_volt,dtype=np.float) if max(abs(df_volt.iloc[1]-df_volt.iloc[0]))<0.003: cellvolt=df_volt.mean(0) else: cellvolt=pd.DataFrame() else: cellvolt=df_volt.iloc[0] return cellvolt #dvdq方法计算soh........................................................................................................................... def _dvdq_soh(self, chrg_st, chrg_end,cellvolt): 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.0015 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]<36: df_Data1=df_Data1[(df_Data1['SOC']>40) & (df_Data1['SOC']<80)] else: df_Data1=df_Data1[(df_Data1['time']>start_time) & (df_Data1['SOC']<80)] df_Data1=df_Data1[(df_Data1['XVOLT']>self.param.PeakVoltLowLmt) & (df_Data1['XVOLT']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)>0 and min(df_Data1['SOC'])+0.540 and soc2[PeakIndex]<80: 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.64 return cellsoh_init else: return cellsoh_init else: return 0 else: if min(df_Data1['SOC'])+0.5max(df_Data1['SOC'])-1: df_Data1=df_Data1[df_Data1['SOC']<(df_Data1['SOC'][PeakIndex]-1)] else: df_Data1=df_Data1[df_Data1['SOC']>(df_Data1['SOC'][PeakIndex]+0.5)] if len(df_Data1)>1: 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) > 1 and min(df_Data1['SOC'])+0.5-0.5 and self.packcrnt[k+2]>-0.5 and self.packcrnt[k+3]>-0.5: self.ChgEnd[i]=k #筛选满足2点法计算的数据 StandingTime=0 StandingTime1=0 if self.bms_soc[self.ChgEnd[i]]>70 and self.bms_soc[self.ChgStart[i]]<50: for m in range(min(len(self.packcrnt)-self.ChgEnd[i]-2,self.ChgStart[i]-2)): if abs(self.packcrnt[self.ChgStart[i] - m - 1]) < 0.5: StandingTime = StandingTime + (self.bmstime[self.ChgStart[i] - m] - self.bmstime[self.ChgStart[i] - m - 1]).total_seconds() if abs(self.packcrnt[self.ChgEnd[i] + m + 1]) < 0.5: StandingTime1 = StandingTime1 + (self.bmstime[self.ChgEnd[i] + m + 1] - self.bmstime[self.ChgEnd[i] + m]).total_seconds() if StandingTime > self.StandardStandingTime and StandingTime1>self.StandardStandingTime and ((self.bmstime[self.ChgEnd[i]]-self.bmstime[self.ChgStart[i]]).total_seconds())/(self.ChgEnd[i]-self.ChgStart[i])<60: #筛选静置时间>15min且慢充过程丢失数据少 if abs(self.packcrnt[self.ChgEnd[i] + m + 2])>0.5 or m==len(self.packcrnt)-self.ChgEnd[i]-3: #如果电流<0.5,继续寻找充电后的静置电压,直到末尾 ChgStartValid.append(self.ChgStart[i]) ChgEndValid.append(self.ChgEnd[i]+m) tempweightlist.append(self.tempweight) break if abs(self.packcrnt[self.ChgStart[i] - m - 2])>0.5 and abs(self.packcrnt[self.ChgEnd[i] + m + 2])>0.5: break if len(ChgStartValid)>0: #两点法计算Soh df_res=pd.DataFrame(columns=('time','sn','soh','soh1')) soh2=[] if not self.df_soh.empty: #获取数据库中上次计算的Soh值 soh_init=list(self.df_soh['soh'])[-1] else: soh_init=list(self.bms_soh)[-1] for i in range(len(ChgStartValid)): Ah=0 for j in range(ChgStartValid[i],ChgEndValid[i]): #计算Ah Step=(self.bmstime[j+1]-self.bmstime[j]).total_seconds() Ah=Ah-self.packcrnt[j+1]*Step/3600 for j in range(1, self.param.CellVoltNums+1): #计算每个电芯的Soh s = str(j) OCVStart=self.df_bms.loc[ChgStartValid[i]-2,'单体电压' + s]/1000 OCVEnd=self.df_bms.loc[ChgEndValid[i]-1,'单体电压' + s]/1000 #soh ocv_Soc1=np.interp(OCVStart,self.param.LookTab_OCV,self.param.LookTab_SOC) ocv_Soc2=np.interp(OCVEnd,self.param.LookTab_OCV,self.param.LookTab_SOC) soh2.append(Ah*100/((ocv_Soc2-ocv_Soc1)*0.01*self.param.Capacity)) soh1=np.mean(soh2) delt_ocv_soc=ocv_Soc2-ocv_Soc1 self._deltsoc_weight(delt_ocv_soc) soh_res=soh_init*(1-self.deltsoc_weight*tempweightlist[i])+soh1*self.deltsoc_weight*tempweightlist[i] soh_init=soh_res df_res.loc[i]=[self.bmstime[ChgStartValid[i]],self.sn,soh_res,soh1] return df_res return pd.DataFrame() #两点法计算三元SOH......................................................................................................................... def _ncmsoh_twopoint(self): standingpoint_st=[] standingpoint_sp=[] tempweightlist=[] standingtime=0 for i in range(2,len(self.df_bms)-2): if abs(self.packcrnt[i]) < 0.1 and abs(self.packcrnt[i-1]) < 0.1: #电流为0 delttime=(self.bmstime[i]-self.bmstime[i-1]).total_seconds() standingtime=standingtime+delttime self._celltemp_weight(i) #获取不同温度对应的静置时间 if standingtime>self.StandardStandingTime: #静置时间满足要求 if standingpoint_st: if len(standingpoint_st)>len(standingpoint_sp): #开始时刻已获取,结束时刻未获取 cellvolt_now=self._cellvolt_get(i) #获取当前行电压数据 minocv_socnow=np.interp(min(cellvolt_now),self.param.LookTab_OCV,self.param.LookTab_SOC) if 270) or (minocv_socst>70 and minocv_socnow<35): #当前时刻SOC与开始时刻SOC差>=40 if abs(self.packcrnt[i+1])>=0.1: #如果下一时刻电流>=0.5,则压入当前索引 standingpoint_sp.append(i) standingpoint_st.append(i) tempweightlist.append(self.tempweight) minocv_socst=minocv_socnow standingtime=0 continue else: if standingtime>2*self.StandardStandingTime or i==len(self.df_bms)-3: #仍处于静置,但静置时间>1h,则直接获取sp时刻,或者到了数据末尾 standingpoint_sp.append(i) continue else: if abs(self.packcrnt[i+1])>=0.1: standingtime=0 if minocv_socnow<35 and (minocv_socnow24*3600): standingpoint_st[-1]=i tempweightlist[-1]=self.tempweight minocv_socst=minocv_socnow elif minocv_socnow>=70 and (minocv_socnow>minocv_socst or (self.bmstime[i]-self.bmstime[standingpoint_st[-1]]).total_seconds()>24*3600): standingpoint_st[-1]=i tempweightlist[-1]=self.tempweight minocv_socst=minocv_socnow else: pass else: continue else: if abs(self.packcrnt[i+1])>=0.1: cellvolt_now=self._cellvolt_get(i) minocv_socst=np.interp(min(cellvolt_now),self.param.LookTab_OCV,self.param.LookTab_SOC) if 270): standingpoint_st.append(i) tempweightlist.append(self.tempweight) standingtime=0 continue else: continue else: if abs(self.packcrnt[i+1])>=0.1: cellvolt_now=self._cellvolt_get(i) minocv_socst=np.interp(min(cellvolt_now),self.param.LookTab_OCV,self.param.LookTab_SOC) if 270): standingpoint_st.append(i) tempweightlist.append(self.tempweight) standingtime=0 continue else: continue else: continue else: standingtime=0 continue #计算SOH...................................................................................................................... if standingpoint_sp: column_name=['time_st','time_sp','sn','method','bmssoh','packsoh','soh','cellsohmin','cellsohmax','sohmin_num','sohmax_num','cellsoh_diff','cellsoh'] df_res=pd.DataFrame(columns=column_name) for i in range(len(standingpoint_sp)): continue_flg=0 cellocv_st=self._avgvolt_get(standingpoint_st[i]) #获取静置点所有电芯的电压 cellocv_sp=self._avgvolt_get(standingpoint_sp[i]) # accumtime=self.accumtime.to_list() #累计量的时间列表 timepoint_bms_st=self.bmstime[standingpoint_st[i]] #获取静置点的时间 timepoint_bms_sp=self.bmstime[standingpoint_sp[i]] # timepoint_accum_st=bisect.bisect(accumtime,timepoint_bms_st) #获取最接近静置点时间的累计量时间点 # timepoint_accum_sp=bisect.bisect(accumtime,timepoint_bms_sp) # if timepoint_accum_sp>=len(accumtime): #防止指针超出数据范围 # timepoint_accum_sp=len(accumtime)-1 ah_packcrnt_dis=0 ah_packcrnt_chg=0 for j in range(standingpoint_st[i]+1,standingpoint_sp[i]): #计算累计Ah Step=(self.bmstime[j+1]-self.bmstime[j]).total_seconds() if Step<120: if self.packcrnt[j+1]>=0: ah_packcrnt_dis=ah_packcrnt_dis+self.packcrnt[j+1]*Step else: ah_packcrnt_chg=ah_packcrnt_chg-self.packcrnt[j+1]*Step elif 120<=Step<600 and self.packcrnt[j+1]<-5 and abs(self.packcrnt[j+1]-self.packcrnt[j])<3: ah_packcrnt_chg=ah_packcrnt_chg-self.packcrnt[j+1]*Step elif (abs(self.packcrnt[j+1]*Step/3600)>1 and abs(self.packcrnt[j+1])>1) or (abs(self.packcrnt[j]*Step/3600)>1 and abs(self.packcrnt[j])>5): if abs(self.bmssoc[j+1]-self.bmssoc[j])>2: continue_flg=1 else: pass if continue_flg==0: ah_packcrnt_chg=ah_packcrnt_chg/3600 ah_packcrnt_dis=ah_packcrnt_dis/3600 ah_packcrnt=ah_packcrnt_chg-ah_packcrnt_dis #两个静置点的总累计AH,负值代表放电,正值代表充电 # ah_accum_dis=self.df_accum.loc[timepoint_accum_sp,'累计放电电量']-self.df_accum.loc[timepoint_accum_st,'累计放电电量'] #两个静置点之间的放电电量 # ah_accum_chg=self.df_accum.loc[timepoint_accum_sp,'累计充电电量']-self.df_accum.loc[timepoint_accum_st,'累计充电电量'] #两个静置点之间的充电电量 # ah_accum_tatol=ah_accum_chg-ah_accum_dis #两个静置点的总累计AH,负值代表放电,正值代表充电 ah_accum=ah_packcrnt delt_days=(self.bmstime[standingpoint_sp[i]]-self.bmstime[standingpoint_st[i]]).total_seconds()/(3600*24) if delt_days<=1: #两次时间间隔对计算结果的影响 soh_weight1=1 elif delt_days<=2: soh_weight1=0.7 elif delt_days<=3: soh_weight1=0.4 else: soh_weight1=0 # if ah_packcrnt_dis60 and cellsoh_init<120 and soh_weight>0.1: #判断soh值的有效区间 if len(df_res)<1: if not self.df_soh.empty: cellsoh_last=eval(self.df_soh.loc[len(self.df_soh)-1,'cellsoh']) # if soh_weight>1/abs(cellsoh_init-cellsoh_last[j]): # soh_weight=1/abs(cellsoh_init-cellsoh_last[j]) # cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last[j]*(1-soh_weight) # else: cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last[j]*(1-soh_weight) else: cellsoh_cal=cellsoh_init else: cellsoh_last=eval(df_res.loc[len(df_res)-1,'cellsoh']) # if soh_weight>1/abs(cellsoh_init-cellsoh_last[j]): # soh_weight=1/abs(cellsoh_init-cellsoh_last[j]) # cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last[j]*(1-soh_weight) # else: cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last[j]*(1-soh_weight) cellsoh_cal=eval(format(cellsoh_cal,'.1f')) cellsoh.append(cellsoh_cal) else: cellsoh=[] break #计算电池包SOH ocv_soc1=np.interp(min(cellocv_st),self.param.LookTab_OCV,self.param.LookTab_SOC) ocv_soc2=np.interp(max(cellocv_sp),self.param.LookTab_OCV,self.param.LookTab_SOC) delt_ocv_soc=ocv_soc2-ocv_soc1 delt_ocv_soc_weight=self._deltsoc_weight(abs(delt_ocv_soc)) soh_weight=soh_weight1*tempweightlist[i]*delt_ocv_soc_weight*0.5 packsoh_init=ah_accum*100/((ocv_soc2-ocv_soc1)*0.01*self.param.Capacity) if packsoh_init>55 and packsoh_init<120 and soh_weight>0.1: #判断soh值的有效区间 if len(df_res)<1: if not self.df_soh.empty: packsoh_last=self.df_soh.loc[len(self.df_soh)-1,'packsoh'] # if soh_weight>1/abs(packsoh_init-packsoh_last): # soh_weight=1/abs(packsoh_init-packsoh_last) # packsoh=packsoh_init*soh_weight + packsoh_last*(1-soh_weight) # else: packsoh=packsoh_init*soh_weight + packsoh_last*(1-soh_weight) else: packsoh=packsoh_init else: packsoh_last=df_res.loc[len(df_res)-1,'packsoh'] # if soh_weight>1/abs(packsoh_init-packsoh_last): # soh_weight=1/abs(packsoh_init-packsoh_last) # packsoh=packsoh_init*soh_weight + packsoh_last*(1-soh_weight) # else: packsoh=packsoh_init*soh_weight + packsoh_last*(1-soh_weight) packsoh=eval(format(packsoh,'.1f')) else: packsoh=0 continue if cellsoh and 55self.StandardStandingTime: #静置时间满足要求 cellvolt_now=self._cellvolt_get(i) cellvolt_now=cellvolt_now[(cellvolt_now>2) & (cellvolt_now<3.8)] if (not cellvolt_now.empty) and 2len(standingpoint_sp): if self.packcrnt[standingpoint_st[-1]]<=-1: #判断上一次静置点的为满充 if abs(self.packcrnt[i+1])>=1: #下一时刻电流>0.1A standingtime=0 standingpoint_sp.append(i) standingpoint_st.append(i) tempweightlist1.append(self.tempweight) else: if standingtime>2*self.StandardStandingTime or i==len(self.df_bms)-3: standingpoint_sp.append(i) standingpoint_st.append(i) tempweightlist1.append(self.tempweight) else: if abs(self.packcrnt[i+1])>=1: #下一时刻电流>0.1A standingtime=0 standingpoint_st[-1]=i tempweightlist1[-1]=self.tempweight else: if abs(self.packcrnt[i+1])>=1: #下一时刻电流>0.1A standingtime=0 standingpoint_st.append(i) tempweightlist1.append(self.tempweight) else: if abs(self.packcrnt[i+1])>=1: #下一时刻电流>0.1A standingtime=0 standingpoint_st.append(i) tempweightlist1.append(self.tempweight) else: pass else: pass elif self.packcrnt[i]<=-1 and self.packcrnt[i-1]<=-1 and self.packcrnt[i+1]<=-1 and self.packcrnt[i+2]>-1: #判读满充状态 standingtime=0 self._celltemp_weight(i) cellvolt_now=self._cellvolt_get(i) cellvolt_now=cellvolt_now[(cellvolt_now>2) & (cellvolt_now<3.8)] if (not cellvolt_now.empty) and max(cellvolt_now)>self.param.CellFullChrgVolt: cellvolt_now=cellvolt_now.tolist() if standingpoint_st: if len(standingpoint_st)>len(standingpoint_sp): if abs(self.packcrnt[standingpoint_st[-1]])<0.5: #判断上一次静置点是否为下拐点 standingpoint_sp.append(i) standingpoint_st.append(i) tempweightlist1.append(self.tempweight) cellmaxvolt_number1.append(cellvolt_now.index(max(cellvolt_now))) #获取最大电压索引 cellmaxvolt_number1.append(cellvolt_now.index(max(cellvolt_now))) #获取最大电压索引 else: standingpoint_st[-1]=i tempweightlist1[-1]=self.tempweight cellmaxvolt_number1[-1]=cellvolt_now.index(max(cellvolt_now)) else: standingpoint_st.append(i) tempweightlist1.append(self.tempweight) cellmaxvolt_number1.append(cellvolt_now.index(max(cellvolt_now))) else: pass else: standingtime=0 pass #获取DVDQ算法所需数据——开始............................................................................................................. if charging==0: if self.packcrnt[i]<=-1 and self.packcrnt[i+1]<=-1 and self.packcrnt[i+2]<=-1 and self.bms_soc[i]<40: #充电开始 self._celltemp_weight(i) charging=1 if len(chrg_start)>len(chrg_end): chrg_start[-1]=i tempweightlist2[-1]=self.tempweight else: chrg_start.append(i) tempweightlist2.append(self.tempweight) else: pass else: #充电中 if (self.bmstime[i+1]-self.bmstime[i]).total_seconds()>180 or (self.packcrnt[i]<-self.param.Capacity-5 and self.packcrnt[i+1]<-self.param.Capacity-5): #如果充电过程中时间间隔>180s,则舍弃该次充电 chrg_start.remove(chrg_start[-1]) tempweightlist2.remove(tempweightlist2[-1]) charging=0 continue elif self.packcrnt[i]<=-1 and self.packcrnt[i+1]<=-1 and self.packcrnt[i+2]>-1: #判断电流波动时刻 cellvolt_now=self._cellvolt_get(i+1).tolist() if max(cellvolt_now)>self.param.CellFullChrgVolt: #电压>满充电压 chrg_end.append(i+1) cellmaxvolt_number2.append(cellvolt_now.index(max(cellvolt_now))) #获取最大电压索引 charging=0 continue else: pass elif self.packcrnt[i+1]>-0.1 and self.packcrnt[i+2]>-0.1: #判断充电结束 charging=0 if len(chrg_start)>len(chrg_end): chrg_start.remove(chrg_start[-1]) tempweightlist2.remove(tempweightlist2[-1]) continue else: continue elif i==len(self.packcrnt)-4 and self.packcrnt[i+1]<-1 and self.packcrnt[i+2]<-1: charging=0 if len(chrg_start)>len(chrg_end): cellvolt_now=self._cellvolt_get(i).tolist() if max(cellvolt_now)>self.param.CellFullChrgVolt: #电压>满充电压 chrg_end.append(i) cellmaxvolt_number2.append(cellvolt_now.index(max(cellvolt_now))) #获取最大电压索引 continue else: chrg_start.remove(chrg_start[-1]) tempweightlist2.remove(tempweightlist2[-1]) continue else: continue else: continue #开始计算SOH............................................................................................................................................. if standingpoint_sp or chrg_end: df_res=pd.DataFrame(columns=['time_st','time_sp','sn','method','bmssoh','packsoh','soh','cellsohmin','cellsohmax','sohmin_num','sohmax_num','cellsoh_diff','cellsoh','soh_weight']) #两点法计算SOH........................................................................................................................................ if standingpoint_sp: for i in range(len(standingpoint_sp)): #判断为满充点或者下拐点 continue_flg=0 if self.packcrnt[standingpoint_sp[i]]<=-1: #计算单体电芯soh cellocv_st=self._avgvolt_get(standingpoint_st[i]) if not cellocv_st.empty: ocv_soc1=np.interp(cellocv_st[cellmaxvolt_number1[i]],self.param.LookTab_OCV,self.param.LookTab_SOC) ocv_packsoc1=np.interp(min(cellocv_st),self.param.LookTab_OCV,self.param.LookTab_SOC) ocv_soc2=self.param.FullChrgSoc ocv_packsoc2=ocv_soc2 else: ocv_soc1=100 ocv_soc2=99 else: cellocv_sp=self._avgvolt_get(standingpoint_sp[i]) if not cellocv_sp.empty: ocv_soc1=self.param.FullChrgSoc ocv_packsoc1=ocv_soc1 ocv_soc2=np.interp(cellocv_sp[cellmaxvolt_number1[i]],self.param.LookTab_OCV,self.param.LookTab_SOC) ocv_packsoc2=np.interp(min(cellocv_sp),self.param.LookTab_OCV,self.param.LookTab_SOC) else: ocv_soc1=100 ocv_soc2=99 # accumtime=self.accumtime.to_list() #累计量的时间列表 timepoint_bms_st=self.bmstime[standingpoint_st[i]] #获取静置点的时间 timepoint_bms_sp=self.bmstime[standingpoint_sp[i]] # timepoint_accum_st=bisect.bisect(accumtime,timepoint_bms_st) #获取最接近静置点时间的累计量时间点 # timepoint_accum_sp=bisect.bisect(accumtime,timepoint_bms_sp) # if timepoint_accum_sp>=len(accumtime): #防止指针超出数据范围 # timepoint_accum_sp=len(accumtime)-1 ah_packcrnt_dis=0 ah_packcrnt_chg=0 for j in range(standingpoint_st[i]+1,standingpoint_sp[i]+1): #计算累计Ah Step=(self.bmstime[j+1]-self.bmstime[j]).total_seconds() if Step<120: if self.packcrnt[j+1]>=0: ah_packcrnt_dis=ah_packcrnt_dis+self.packcrnt[j+1]*Step else: ah_packcrnt_chg=ah_packcrnt_chg-self.packcrnt[j+1]*Step elif 120<=Step<1000 and self.packcrnt[j+1]<-5 and abs(self.packcrnt[j+1]-self.packcrnt[j])<3: ah_packcrnt_chg=ah_packcrnt_chg-self.packcrnt[j+1]*Step elif (abs(self.packcrnt[j+1]*Step/3600)>1 and abs(self.packcrnt[j+1])>1) or (abs(self.packcrnt[j]*Step/3600)>1 and abs(self.packcrnt[j])>5): continue_flg=1 else: pass if continue_flg==0: ah_packcrnt_chg=ah_packcrnt_chg/3600 ah_packcrnt_dis=ah_packcrnt_dis/3600 ah_packcrnt=ah_packcrnt_chg-ah_packcrnt_dis #两个静置点的总累计AH,负值代表放电,正值代表充电 # ah_accum_dis=self.df_accum.loc[timepoint_accum_sp,'累计放电电量']-self.df_accum.loc[timepoint_accum_st,'累计放电电量'] #两个静置点之间的放电电量 # ah_accum_chg=self.df_accum.loc[timepoint_accum_sp,'累计充电电量']-self.df_accum.loc[timepoint_accum_st,'累计充电电量'] #两个静置点之间的充电电量 # ah_accum_tatol=ah_accum_chg-ah_accum_dis #两个静置点的总累计AH,负值代表放电,正值代表充电 ah_accum=ah_packcrnt delt_days=(self.bmstime[standingpoint_sp[i]]-self.bmstime[standingpoint_st[i]]).total_seconds()/(3600*24) if delt_days<=1: #两次时间间隔对计算结果的影响 soh_weight=1 elif delt_days<=2: soh_weight=0.7 elif delt_days<=3: soh_weight=0.4 else: soh_weight=0 # if self.param.Capacity*0.65*0.7 < abs(ah_packcrnt) < self.param.Capacity: #累计量的权重 # if abs(ah_accum_tatol-ah_packcrnt)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) packsoh=packsoh_init*soh_weight + packsoh_last*(1-soh_weight) else: cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last*(1-soh_weight) packsoh=packsoh_init*soh_weight + packsoh_last*(1-soh_weight) else: cellsoh_cal=cellsoh_init packsoh=packsoh_init cellsoh_cal=eval(format(cellsoh_cal,'.1f')) packsoh=eval(format(packsoh,'.1f')) if 551/abs(cellsoh_init-cellsoh_last): soh_weight=1/abs(cellsoh_init-cellsoh_last) cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last*(1-soh_weight) packsoh=packsoh_init*soh_weight + packsoh_last*(1-soh_weight) else: cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last*(1-soh_weight) packsoh=packsoh_init*soh_weight + packsoh_last*(1-soh_weight) cellsoh_cal=eval(format(cellsoh_cal,'.1f')) packsoh=eval(format(packsoh,'.1f')) if 55