import pandas as pd import numpy as np import datetime import bisect import matplotlib.pyplot as plt from LIB.MIDDLE.CellStateEstimation.Common import BatParam class BatSoh(): def __init__(self,sn,celltype,df_bms,df_accum,df_soh): #参数初始化 self.sn=sn self.celltype=celltype self.param=BatParam.BatParam(celltype) self.df_bms=df_bms 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[%]'] self.bmsstat=df_bms['充电状态'] self.bmstime= pd.to_datetime(df_bms['时间戳'], format='%Y-%m-%d %H:%M:%S') self.df_accum=df_accum self.accumtime=pd.to_datetime(df_accum['时间戳'], format='%Y-%m-%d %H:%M:%S') self.df_soh=df_soh self.cellvolt_name=['单体电压'+str(x) for x in range(1,self.param.CellVoltNums+1)] self.celltemp_name=['单体温度'+str(x) for x in range(1,self.param.CellTempNums+1)] def batsoh(self): if self.celltype==1 or self.celltype==2 or self.celltype==3 or self.celltype==4: df_res=self._ncmsoh_twopoint() return df_res elif self.celltype==99: df_res=self._lfpsoh() return df_res else: return pd.DataFrame() #定义滑动滤波函数......................................................................................................................... def _np_move_avg(self,a, n, mode="same"): return (np.convolve(a, np.ones((n,)) / n, mode=mode)) #筛选充电数据.............................................................................................................................. def _chrgdata(self): self.ChgStart=[] self.ChgEnd=[] if len(self.packvolt)>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=2400 elif min(celltemp)>=15: self.tempweight=0.6 self.StandardStandingTime=3600 elif min(celltemp)>=5: self.tempweight=0.3 self.StandardStandingTime=7200 else: self.tempweight=0.1 self.StandardStandingTime=10800 else: if min(celltemp)>=25: self.tempweight=1 self.StandardStandingTime=1800 elif min(celltemp)>=15: self.tempweight=0.8 self.StandardStandingTime=3600 elif min(celltemp)>=5: self.tempweight=0.3 self.StandardStandingTime=4800 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.7 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 = np.array(self.df_bms.loc[num,self.cellvolt_name])/1000 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,'单体电压' + s]/1000 return singlevolt else: singlevolt=self.df_bms['单体电压' + s]/1000 return singlevolt #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']2: 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)>1 and df_Data1.loc[PeakIndex,'XVOLT']40 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.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) > 1 and df_Data1.loc[PeakIndex,'XVOLT']40 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.14 return cellsoh_init else: return cellsoh_init else: return 0 else: return 0 else: return 0 #NCM充电数据soh计算......................................................................................................................... def _ncmsoh_chrg(self): self._chrgdata() ChgStartValid=[] ChgEndValid=[] tempweightlist=[] for i in range(min(len(self.ChgStart),len(self.ChgEnd))): self._celltemp_weight(self.ChgEnd[i]) #获取温度对应的静置时间及权重 for k in range(self.ChgStart[i],self.ChgEnd[i]): #去除电流0点 if self.packcrnt[k]<-0.5 and self.packcrnt[k+1]>-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(3,len(self.df_bms)-3): if abs(self.packcrnt[i]) < 0.1 and abs(self.packcrnt[i-1]) < 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: #静置时间满足要求 cellvolt_now=self._cellvolt_get(i) cellvolt_min=min(cellvolt_now) cellvolt_max=max(cellvolt_now) cellvolt_last=self._cellvolt_get(i-1) deltvolt=max(abs(cellvolt_now-cellvolt_last)) if 3len(standingpoint_sp): #开始时刻已获取,结束时刻未获取 minocv_socnow=np.interp(cellvolt_min,self.param.LookTab_OCV,self.param.LookTab_SOC) cellvolt_st=self._cellvolt_get(standingpoint_st[-1]) #获取开始时刻静置后的电压数据 minocv_socst=np.interp(min(cellvolt_st),self.param.LookTab_OCV,self.param.LookTab_SOC) if abs(minocv_socst-minocv_socnow)>=40: #当前时刻SOC与开始时刻SOC差>=40 if abs(self.packcrnt[i+2])>=0.1: #如果下一时刻电流>=0.5,则压入当前索引 standingpoint_sp.append(i) standingpoint_st.append(i) tempweightlist.append(self.tempweight) standingtime=0 continue else: if standingtime>3600 or i==len(self.df_bms)-2: #仍处于静置,但静置时间>1h,则直接获取sp时刻,或者到了数据末尾 standingpoint_sp.append(i) tempweightlist.append(self.tempweight) continue else: if abs(self.packcrnt[i+2])>=0.1: standingtime=0 if minocv_socst<50 and minocv_socnow=0.1: standingtime=0 if minocv_socst>=50 and minocv_socnow>minocv_socst: standingpoint_st[-1]=i continue else: continue else: if abs(self.packcrnt[i+2])>=0.1: standingpoint_st.append(i) standingtime=0 continue else: continue else: if abs(self.packcrnt[i+2])>0.1: standingpoint_st.append(i) standingtime=0 continue else: continue else: continue else: continue else: standingtime=0 continue #计算SOH...................................................................................................................... if standingpoint_sp: column_name=['time_st','time_sp','sn','method','bmssoh','packsoh','soh','cellsoh'] df_res=pd.DataFrame(columns=column_name) for i in range(len(standingpoint_sp)): cellocv_st=self._cellvolt_get(standingpoint_st[i]) #获取静置点所有电芯的电压 cellocv_sp=self._cellvolt_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 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_dis55 and cellsoh_init<120 and soh_weight>0.05: #判断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.05: #判断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: #静置时间满足要求 if abs(self.packcrnt[i+2])>=0.1: #下一时刻电流>0.1A standingtime=0 cellvolt_now=self._cellvolt_get(i) cellvolt_max=max(cellvolt_now) cellvolt_min=min(cellvolt_now) cellvolt_last=self._cellvolt_get(i-1) deltvolt=max(abs(cellvolt_now-cellvolt_last)) if 2len(standingpoint_sp): if self.packcrnt[standingpoint_st[-1]]<-1: #判断上一次静置点的是否为满充 standingpoint_sp.append(i) standingpoint_st.append(i) tempweightlist1.append(self.tempweight) else: standingpoint_st[-1]=i tempweightlist1[-1]=self.tempweight else: standingpoint_st.append(i) tempweightlist1.append(self.tempweight) else: standingpoint_st.append(i) tempweightlist1.append(self.tempweight) else: pass 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).tolist() if max(cellvolt_now)>self.param.CellFullChrgVolt: 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/2 and self.packcrnt[i+1]<-self.param.Capacity/2): #如果充电过程中时间间隔>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: column_name=['time_st','time_sp','sn','method','bmssoh','packsoh','soh','cellsoh','weight'] df_res=pd.DataFrame(columns=column_name) #两点法计算SOH........................................................................................................................................ if standingpoint_sp: for i in range(len(standingpoint_sp)): #判断为满充点或者下拐点 if self.packcrnt[standingpoint_sp[i]]<=-1: #计算单体电芯soh cellocv_st=self._cellvolt_get(standingpoint_st[i]) 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: cellocv_sp=self._cellvolt_get(standingpoint_sp[i]) 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) cellocv_sp=self._cellvolt_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]+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 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_accum_tatol 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