Browse Source

1.优化SOH和一致性算法,2.上传漏电流算法

qingfeng 3 years ago
parent
commit
692f8cba32

+ 4 - 2
LIB/MIDDLE/CellStateEstimation/Common/BatParam.py

@@ -84,8 +84,10 @@ class BatParam:
             self.CellVoltNums=20
             self.CellTempNums=4
             self.FullChrgSoc=98
-            self.PeakSoc=60.5
-            self.PeakCellVolt=[3.357,3.358,3.359,3.36,3.361]
+            self.PeakSoc=59
+            self.PeakVoltLowLmt=3.35
+            self.PeakVoltUpLmt=3.4
+            self.PeakCellVolt=[3.362,3.363,3.365,3.366,3.367]
             self.PackCrntDec=1
             self.BalCurrent=0.025
             self.LookTab_SOC = [0.00, 	2.40, 	6.38, 	10.37, 	14.35, 	18.33, 	22.32, 	26.30, 	30.28, 	35.26, 	40.24, 	45.22, 	50.20, 	54.19, 	58.17, 	60.16, 	65.14, 	70.12, 	75.10, 	80.08, 	84.06, 	88.05, 	92.03, 	96.02, 	100.00]

+ 1 - 1
LIB/MIDDLE/CellStateEstimation/Common/DBDownload.py

@@ -43,7 +43,7 @@ class DBDownload:
             else:
                 str=str+','+param[i]
         # self.cursor.execute("select %s from %s where time between '%s' and '%s'" %(str,tablename,st,sp))
-        self.cursor.execute("select %s from %s where sn='%s' order by add_time desc limit 1" %(str,tablename,sn))
+        self.cursor.execute("select %s from %s where sn='%s' order by id desc limit 1" %(str,tablename,sn))
         res = self.cursor.fetchall()
         df_res = pd.DataFrame(res, columns=param)
         df_res = df_res.reset_index(drop=True)

+ 59 - 53
LIB/MIDDLE/CellStateEstimation/InterShort/V1_0_0/CBMSBatInterShort.py

@@ -294,32 +294,35 @@ class BatInterShort:
                             dict_bal={}
 
                     #满电静置法计算内短路-开始.....................................................................................................................................................
-                    if standingtime1>self.StandardStandingTime and abs(self.packcrnt[i+2]) >= 0.1:  
-                        standingtime1=0
-                        cellvolt_now1=self._cellvolt_get(i)
-                        cellsoc_now1=np.interp(max(cellvolt_now1),self.param.LookTab_OCV,self.param.LookTab_SOC)
-                        if cellsoc_now1>=self.param.FullChrgSoc-3:
-                            if firsttime1==1:
-                                dict_baltime1=self._bal_time(dict_bal1)   #获取每个电芯的均衡时间
-                                deltsoc_last1=self._celldeltsoc_get(i,dict_baltime1,capacity)
-                                time_last1=self.bmstime[i]
-                                firsttime1=0
+                    if standingtime1>self.StandardStandingTime:  
+                        if abs(self.packcrnt[i+2]) >= 0.1:
+                            standingtime1=0
+                            cellvolt_now1=self._cellvolt_get(i)
+                            cellsoc_now1=np.interp(max(cellvolt_now1),self.param.LookTab_OCV,self.param.LookTab_SOC)
+                            if cellsoc_now1>=self.param.FullChrgSoc-3:
+                                if firsttime1==1:
+                                    dict_baltime1=self._bal_time(dict_bal1)   #获取每个电芯的均衡时间
+                                    deltsoc_last1=self._celldeltsoc_get(i,dict_baltime1,capacity)
+                                    time_last1=self.bmstime[i]
+                                    firsttime1=0
+                                else:
+                                    dict_baltime1=self._bal_time(dict_bal1)   #获取每个电芯的均衡时间
+                                    deltsoc_now1=self._celldeltsoc_get(i,dict_baltime1,capacity)
+                                    time_now1=self.bmstime[i]
+
+                                    list_sub1=[a-b for a, b in zip(deltsoc_now1, deltsoc_last1)]
+                                    list_pud1=[0.01*capacity*3600*1000/(time_now1-time_last1).total_seconds()]*self.param.CellVoltNums
+                                    leak_current1=[a*b for a,b in zip(list_sub1,list_pud1)]
+                                    leak_current1=np.array(leak_current1)
+                                    leak_current1=np.round(leak_current1,3)
+                                    leak_current1=list(leak_current1)
+                                    
+                                    df_res.loc[len(df_res)]=[time_last1,time_now1,self.sn,2,str(leak_current1),str(dict_baltime1)]  #计算结果存入Dataframe
+                                    time_last1=time_now1  #更新时间
+                                    deltsoc_last1=deltsoc_now1    #更新soc差
+                                    dict_bal1={}
                             else:
-                                dict_baltime1=self._bal_time(dict_bal1)   #获取每个电芯的均衡时间
-                                deltsoc_now1=self._celldeltsoc_get(i,dict_baltime1,capacity)
-                                time_now1=self.bmstime[i]
-
-                                list_sub1=[a-b for a, b in zip(deltsoc_now1, deltsoc_last1)]
-                                list_pud1=[0.01*capacity*3600*1000/(time_now1-time_last1).total_seconds()]*self.param.CellVoltNums
-                                leak_current1=[a*b for a,b in zip(list_sub1,list_pud1)]
-                                leak_current1=np.array(leak_current1)
-                                leak_current1=np.round(leak_current1,3)
-                                leak_current1=list(leak_current1)
-                                
-                                df_res.loc[len(df_res)]=[time_last1,time_now1,self.sn,2,str(leak_current1),str(dict_baltime1)]  #计算结果存入Dataframe
-                                time_last1=time_now1  #更新时间
-                                deltsoc_last1=deltsoc_now1    #更新soc差
-                                dict_bal1={}
+                                pass
                         else:
                             pass
                     else:   
@@ -439,35 +442,38 @@ class BatInterShort:
                             dict_bal={}
 
                     #非平台区间静置法计算内短路-开始.....................................................................................................................................................
-                    if standingtime1>self.StandardStandingTime and abs(self.packcrnt[i+2]) >= 0.1:  
-                        standingtime1=0
-                        cellvolt_now1=self._cellvolt_get(i)
-                        if max(cellvolt_now1)<self.param.OcvInflexionBelow-0.002:
-                            if firsttime1==1:
-                                dict_baltime1=self._bal_time(dict_bal1)   #获取每个电芯的均衡时间
-                                deltsoc_last1=self._celldeltsoc_get(i,dict_baltime1,capacity)
-                                time_last1=self.bmstime[i]
-                                firsttime1=0
-                            else:
-                                dict_baltime1=self._bal_time(dict_bal1)   #获取每个电芯的均衡时间
-                                deltsoc_now1=self._celldeltsoc_get(i,dict_baltime1,capacity)
-                                time_now1=self.bmstime[i]
-
-                                if abs(max(deltsoc_now1)-max(deltsoc_last1))<10:
-                                    list_sub1=[a-b for a, b in zip(deltsoc_now1, deltsoc_last1)]
-                                    list_pud1=[0.01*capacity*3600*1000/(time_now1-time_last1).total_seconds()]*self.param.CellVoltNums
-                                    leak_current1=[a*b for a,b in zip(list_sub1,list_pud1)]
-                                    leak_current1=np.array(leak_current1)
-                                    leak_current1=np.round(leak_current1,3)
-                                    leak_current1=list(leak_current1)
-                                
-                                    
-                                    df_res.loc[len(df_res)]=[time_last1,time_now1,self.sn,2,str(leak_current1),str(dict_baltime1)]  #计算结果存入Dataframe
+                    if standingtime1>self.StandardStandingTime: 
+                        if abs(self.packcrnt[i+2]) >= 0.1: 
+                            standingtime1=0
+                            cellvolt_now1=self._cellvolt_get(i)
+                            if max(cellvolt_now1)<self.param.OcvInflexionBelow-0.002:
+                                if firsttime1==1:
+                                    dict_baltime1=self._bal_time(dict_bal1)   #获取每个电芯的均衡时间
+                                    deltsoc_last1=self._celldeltsoc_get(i,dict_baltime1,capacity)
+                                    time_last1=self.bmstime[i]
+                                    firsttime1=0
                                 else:
-                                    pass
-                                time_last1=time_now1  #更新时间
-                                deltsoc_last1=deltsoc_now1    #更新soc差
-                                dict_bal1={}
+                                    dict_baltime1=self._bal_time(dict_bal1)   #获取每个电芯的均衡时间
+                                    deltsoc_now1=self._celldeltsoc_get(i,dict_baltime1,capacity)
+                                    time_now1=self.bmstime[i]
+
+                                    if abs(max(deltsoc_now1)-max(deltsoc_last1))<10:
+                                        list_sub1=[a-b for a, b in zip(deltsoc_now1, deltsoc_last1)]
+                                        list_pud1=[0.01*capacity*3600*1000/(time_now1-time_last1).total_seconds()]*self.param.CellVoltNums
+                                        leak_current1=[a*b for a,b in zip(list_sub1,list_pud1)]
+                                        leak_current1=np.array(leak_current1)
+                                        leak_current1=np.round(leak_current1,3)
+                                        leak_current1=list(leak_current1)
+                                    
+                                        
+                                        df_res.loc[len(df_res)]=[time_last1,time_now1,self.sn,2,str(leak_current1),str(dict_baltime1)]  #计算结果存入Dataframe
+                                    else:
+                                        pass
+                                    time_last1=time_now1  #更新时间
+                                    deltsoc_last1=deltsoc_now1    #更新soc差
+                                    dict_bal1={}
+                            else:
+                                pass
                         else:
                             pass
                     else:   

+ 64 - 49
LIB/MIDDLE/CellStateEstimation/SOH/V1_0_0/CBMSBatSoh.py

@@ -74,15 +74,16 @@ class BatSoh:
             s = str(j)
             celltemp.append(self.df_bms.loc[num,'单体温度' + s])
         celltemp.remove(min(celltemp))
+        self.celltemp=celltemp
         if self.celltype==99:
             if min(celltemp)>=20:
                 self.tempweight=1
                 self.StandardStandingTime=1800
             elif min(celltemp)>=10:
-                self.tempweight=0.6
+                self.tempweight=0.5
                 self.StandardStandingTime=3600
             elif min(celltemp)>=5:
-                self.tempweight=0.1
+                self.tempweight=0
                 self.StandardStandingTime=7200
             else:
                 self.tempweight=0
@@ -140,7 +141,7 @@ class BatSoh:
         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:
+            if (cellvolt[j]-Volt)>0.0019 and Ah>0:
                 Ah_tatal.append(Ah_tatal[-1]+Ah)
                 DQ_Ah.append(Ah)
                 DV_Volt.append(cellvolt[j]-Volt)
@@ -163,11 +164,14 @@ class BatSoh:
         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)]
+        if soc2[0]<36:
+            df_Data1=df_Data1[(df_Data1['SOC']>39.5) & (df_Data1['SOC']<80)]
         else:
-            df_Data1=df_Data1[(df_Data1['time']>start_time) & (df_Data1['time']<end_time)]
+            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']<self.param.PeakVoltUpLmt)]
 
+        # self._celltemp_weight(int((chrg_st+chrg_end)/2))
+        # print(self.packcrnt[int((chrg_st+chrg_end)/2)], min(self.celltemp))
         # ax1 = plt.subplot(3, 1, 1)
         # plt.plot(df_Data1['XVOLT'],df_Data1['DVDQ'],'r*-')
         # plt.xlabel('Volt/V')
@@ -190,12 +194,12 @@ class BatSoh:
             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:
+            if len(df_Data2)>1 and df_Data1.loc[PeakIndex,'XVOLT']<self.param.PeakVoltUpLmt-0.019:
                 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:
+                if soc2[PeakIndex]>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
@@ -208,12 +212,12 @@ class BatSoh:
                 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:
+                if len(df_Data2) > 1 and df_Data1.loc[PeakIndex,'XVOLT']<self.param.PeakVoltUpLmt-0.019:
                     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:
+                    if soc2[PeakIndex]>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
@@ -312,7 +316,7 @@ class BatSoh:
                             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差>=20
+                            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)
@@ -325,14 +329,16 @@ class BatSoh:
                                         tempweightlist.append(self.tempweight)
                                         continue
                             else:
-                                if minocv_socst<50 and minocv_socnow<minocv_socst and abs(self.packcrnt[i+2])>=0.3:
-                                    standingpoint_st[-1]=i
+                                if abs(self.packcrnt[i+2])>=0.1:
                                     standingtime=0
-                                    continue
-                                elif minocv_socst>=50 and minocv_socnow>minocv_socst and abs(self.packcrnt[i+2])>=0.3:
-                                    standingpoint_st[-1]=i
+                                    if  minocv_socst<50 and minocv_socnow<minocv_socst:
+                                        standingpoint_st[-1]=i
+                                        continue
+                                elif abs(self.packcrnt[i+2])>=0.1:
                                     standingtime=0
-                                    continue
+                                    if minocv_socst>=50 and minocv_socnow>minocv_socst:
+                                        standingpoint_st[-1]=i
+                                        continue
                                 else:
                                     continue
                         else:
@@ -400,7 +406,7 @@ class BatSoh:
                     soh_weight1=0
                 
                 if ah_packcrnt_dis<self.param.Capacity: #放电ah数对结果的影响
-                    soh_weight1=(1-ah_packcrnt_dis/self.param.Capacity*1.5)*soh_weight1
+                    soh_weight1=(1-ah_packcrnt_dis/(self.param.Capacity*1.5))*soh_weight1
                 else:
                     soh_weight1=0.1
             
@@ -413,7 +419,7 @@ class BatSoh:
                         soh_weight1=soh_weight1*0.5
                 else:
                     if self.param.Capacity*0.7*0.4< abs(ah_packcrnt) <self.param.Capacity:
-                        soh_weight1=soh_weight1*0.5
+                        soh_weight1=soh_weight1*0.3
                     else:
                         soh_weight1=0
 
@@ -423,15 +429,15 @@ class BatSoh:
                     ocv_soc2=np.interp(cellocv_sp[j],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
+                    soh_weight=soh_weight1*tempweightlist[i]*delt_ocv_soc_weight*0.5
                     cellsoh_init=ah_accum*100/((ocv_soc2-ocv_soc1)*0.01*self.param.Capacity)
 
                     if cellsoh_init>55 and cellsoh_init<120:    #判断soh值的有效区间
                         if len(df_res)<1:
-                            if not self.df_soh.empty:
+                            if not self.df_soh.empty and 55<self.df_soh.loc[len(self.df_soh)-1,'soh']<120:
                                 cellsoh_last=eval(self.df_soh.loc[len(self.df_soh)-1,'cellsoh'])
-                                if soh_weight>1/abs(cellsoh_init-cellsoh_last):
-                                    soh_weight=1/abs(cellsoh_init-cellsoh_last)
+                                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)
@@ -449,7 +455,7 @@ class BatSoh:
                     else:
                         cellsoh=[]
                         break
-                if cellsoh:
+                if cellsoh and 55<min(cellsoh)<120:
                     soh=min(cellsoh)
                     soh_list=[timepoint_bms_st, timepoint_bms_sp, self.sn, 1, soh, str(cellsoh)]
                     df_res.loc[len(df_res)]=soh_list
@@ -482,25 +488,28 @@ class BatSoh:
                 standingtime=standingtime+delttime
                 self._celltemp_weight(i)     #获取不同温度对应的静置时间
 
-                if standingtime>self.StandardStandingTime and abs(self.packcrnt[i+2])>=0.1:  #静置时间满足要求,且下一时刻电流>0.1A
-                    standingtime=0
-                    cellvolt_now=self._cellvolt_get(i)
-                    if max(cellvolt_now)<self.param.OcvInflexionBelow:      #当前最大电芯电压<OCV下拐点
-                        if standingpoint_st:
-                            if len(standingpoint_st)>len(standingpoint_sp):
-                                if self.packcrnt[standingpoint_st[-1]]<-1:     #判断上一次静置点的是否为满充
-                                    standingpoint_sp.append(i)
+                if standingtime>self.StandardStandingTime:  #静置时间满足要求
+                    if abs(self.packcrnt[i+2])>=0.1:  #下一时刻电流>0.1A
+                        standingtime=0
+                        cellvolt_now=self._cellvolt_get(i)
+                        if max(cellvolt_now)<self.param.OcvInflexionBelow:      #当前最大电芯电压<OCV下拐点
+                            if standingpoint_st:
+                                if len(standingpoint_st)>len(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[-1]=i
-                                    tempweightlist1[-1]=self.tempweight
                             else:
                                 standingpoint_st.append(i)
                                 tempweightlist1.append(self.tempweight)
                         else:
-                            standingpoint_st.append(i)
-                            tempweightlist1.append(self.tempweight)
+                            pass
                     else:
                         pass
                 else:
@@ -536,7 +545,7 @@ class BatSoh:
 
             #获取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]<45:     #充电开始
+                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):
@@ -651,7 +660,7 @@ class BatSoh:
                             soh_weight=soh_weight*0.5
                     else:
                         if self.param.Capacity*0.65*0.7 < abs(ah_accum) < self.param.Capacity:
-                            soh_weight=soh_weight*0.5
+                            soh_weight=soh_weight*0.3
                         else:
                             soh_weight=0
 
@@ -660,9 +669,9 @@ class BatSoh:
                     soh_weight=soh_weight*tempweightlist1[i]*delt_ocv_soc_weight*0.5
                     cellsoh_init=ah_accum*100/((ocv_soc2-ocv_soc1)*0.01*self.param.Capacity)
 
-                    if cellsoh_init>65 and cellsoh_init<115:    #判断soh值的有效区间
+                    if cellsoh_init>60 and cellsoh_init<115:    #判断soh值的有效区间
                         if len(df_res)<1:
-                            if not self.df_soh.empty:
+                            if not self.df_soh.empty and 60<self.df_soh.loc[len(self.df_soh)-1,'soh']<115:
                                 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)
@@ -679,9 +688,12 @@ class BatSoh:
                             else:
                                 cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last*(1-soh_weight)
                         
-                        cellsoh_cal=eval(format(cellsoh_cal,'.1f'))
-                        soh_list=[timepoint_bms_st, timepoint_bms_sp, self.sn, 1, cellsoh_cal, str(cellsoh_cal)]
-                        df_res.loc[len(df_res)]=soh_list
+                        if 60<cellsoh_cal<115:
+                            cellsoh_cal=eval(format(cellsoh_cal,'.1f'))
+                            soh_list=[timepoint_bms_st, timepoint_bms_sp, self.sn, 1, cellsoh_cal, str(cellsoh_cal)]
+                            df_res.loc[len(df_res)]=soh_list
+                        else:
+                            pass
                     else:
                         continue
             else:
@@ -696,9 +708,9 @@ class BatSoh:
                     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 cellsoh_init>60 and cellsoh_init<115:    #判断soh值的有效区间
                         if len(df_res)<1:
-                            if not self.df_soh.empty:
+                            if not self.df_soh.empty and 60<self.df_soh.loc[len(self.df_soh)-1,'soh']<115:
                                 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)
@@ -715,9 +727,12 @@ class BatSoh:
                             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
+                        if 60<cellsoh_cal<115:
+                            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:
+                            pass
                     else:
                         continue
             else:

+ 102 - 93
LIB/MIDDLE/CellStateEstimation/Uniform/V1_0_0/CBMSBatUniform.py

@@ -40,33 +40,34 @@ class BatUniform:
             s = str(j)
             celltemp.append(self.df_bms.loc[num,'单体温度' + s])
         celltemp.remove(min(celltemp))
+        self.celltemp=celltemp
         if self.celltype==99:
             if min(celltemp)>=20:
                 self.tempweight=1
-                self.StandardStandingTime=600
+                self.StandardStandingTime=1800
             elif min(celltemp)>=10:
                 self.tempweight=0.6
-                self.StandardStandingTime=900
+                self.StandardStandingTime=3600
             elif min(celltemp)>=5:
                 self.tempweight=0.
-                self.StandardStandingTime=1800
+                self.StandardStandingTime=3600
             else:
                 self.tempweight=0.1
-                self.StandardStandingTime=3600
+                self.StandardStandingTime=7200
         else:
             if min(celltemp)>=20:
                 self.tempweight=1
-                self.StandardStandingTime=300
+                self.StandardStandingTime=1200
             elif min(celltemp)>=10:
                 self.tempweight=0.8
-                self.StandardStandingTime=600
+                self.StandardStandingTime=1800
             elif min(celltemp)>=5:
                 self.tempweight=0.6
-                self.StandardStandingTime=1800
+                self.StandardStandingTime=3600
             else:
                 self.tempweight=0.2
-                self.StandardStandingTime=3600
-
+                self.StandardStandingTime=7200
+        
     #获取当前行所有电压数据............................................................................................................................
     def _cellvolt_get(self,num):
         cellvolt=[]
@@ -76,11 +77,11 @@ class BatUniform:
         return(cellvolt)
 
     #寻找DVDQ的峰值点,并返回..........................................................................................................................
-    def _dvdq_peak(self, time, soc, cellvolt, packcrnt):    
-        cellvolt1 = self._np_move_avg(cellvolt, 5, mode="same")
+    def _dvdq_peak(self, time, soc, cellvolt, packcrnt):
+        cellvolt = self._np_move_avg(cellvolt, 3, mode="same")
         Soc = 0
         Ah = 0
-        Volt = cellvolt1[0]
+        Volt = cellvolt[0]
         DV_Volt = []
         DQ_Ah = []
         DVDQ = []
@@ -93,11 +94,11 @@ class BatUniform:
             Step = (time[m] - time[m - 1]).total_seconds()
             Soc = Soc - packcrnt[m] * Step * 100 / (3600 * self.param.Capacity)
             Ah = Ah - packcrnt[m] * Step / 3600
-            if (cellvolt[m]-Volt)>0.99 and Ah>0:
+            if (cellvolt[m]-Volt)>0.0019 and Ah>0:
                 DQ_Ah.append(Ah)
                 DV_Volt.append(cellvolt[m]-Volt)
                 DVDQ.append((DV_Volt[-1])/DQ_Ah[-1])
-                xvolt.append(cellvolt[m]/1000)
+                xvolt.append(cellvolt[m])
                 Volt=cellvolt[m]
                 Ah = 0
                 soc1.append(Soc)
@@ -113,20 +114,18 @@ class BatUniform:
                                 'DV_Volt':DV_Volt,
                                 'XVOLT':xvolt})
         start_time=df_Data1.loc[0,'time']
-        start_time=start_time+datetime.timedelta(seconds=600)
+        start_time=start_time+datetime.timedelta(seconds=900)
         end_time=df_Data1.loc[len(time1)-1,'time']
         end_time=end_time-datetime.timedelta(seconds=1200)
-        if soc2[0]<40 and soc2[-1]>93:
-            df_Data1=df_Data1[(df_Data1['SOC']>44) & (df_Data1['SOC']<90)]
-        elif soc2[0]<40 and soc2[-1]<=93:
-            df_Data1=df_Data1[(df_Data1['SOC']>44) & (df_Data1['time']<end_time)]
-        elif soc2[0]>=40 and soc2[-1]>93:
-            df_Data1=df_Data1[(df_Data1['time']>start_time) & (df_Data1['SOC']<90)]
+        if soc2[0]<36:
+            df_Data1=df_Data1[(df_Data1['SOC']>39.5) & (df_Data1['SOC']<80)]
         else:
-            df_Data1=df_Data1[(df_Data1['time']>start_time) & (df_Data1['time']<end_time)]
+            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']<self.param.PeakVoltUpLmt)]
 
+        # print(packcrnt[int(len(time)/2)], min(self.celltemp))
         # ax1 = plt.subplot(3, 1, 1)
-        # plt.plot(df_Data1['XVOLT'],df_Data1['DVDQ'],'r*-')
+        # plt.plot(df_Data1['XVOLT'],df_Data1['DVDQ'],'g*-')
         # plt.xlabel('Volt/V')
         # plt.ylabel('DV/DQ')
         # plt.legend()
@@ -140,18 +139,18 @@ class BatUniform:
         # plt.xlabel('SOC/%')
         # plt.ylabel('DV/DQ')
         # plt.legend()
-        # plt.show()
+        # # plt.show()
 
         if len(df_Data1)>2:     #寻找峰值点,且峰值点个数>2
             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:
+            if len(df_Data2) > 1 and df_Data1.loc[PeakIndex,'XVOLT']<self.param.PeakVoltUpLmt-0.015:
                 return df_Data1['AhSoc'][PeakIndex]
             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:
+                if len(df_Data2) > 1 and df_Data1.loc[PeakIndex,'XVOLT']<self.param.PeakVoltUpLmt-0.015:
                     return df_Data1['AhSoc'][PeakIndex]
                 else:
                     return 0
@@ -177,43 +176,46 @@ class BatUniform:
                         cellvolt_now=self._cellvolt_get(i)     #获取当前行电压数据
                         cellvolt_min=min(cellvolt_now)
                         cellvolt_max=max(cellvolt_now)
-                        cellmin_num=cellvolt_now.index(cellvolt_min)+1
-                        cellmax_num=cellvolt_now.index(cellvolt_max)+1
-                        cellsoc_min=np.interp(cellvolt_min,self.param.LookTab_OCV,self.param.LookTab_SOC)
-                        cellsoc_max=np.interp(cellvolt_max,self.param.LookTab_OCV,self.param.LookTab_SOC)
-                        cellvolt_diff=(cellvolt_max-cellvolt_min)*1000
-                        cellsoc_diff=cellsoc_max-cellsoc_min
-                        cellsoc_diff=eval(format(cellsoc_diff,'.1f'))
-                        cellvolt_diff=eval(format(cellvolt_diff,'.0f'))
-                        df_res.loc[len(df_res)]=[self.bmstime[i], self.sn, cellsoc_diff, cellvolt_diff, cellmin_num, cellmax_num]
+                        if 3<cellvolt_min<4.5 and 3<cellvolt_max<4.5:
+                            cellmin_num=cellvolt_now.index(cellvolt_min)+1
+                            cellmax_num=cellvolt_now.index(cellvolt_max)+1
+                            cellsoc_min=np.interp(cellvolt_min,self.param.LookTab_OCV,self.param.LookTab_SOC)
+                            cellsoc_max=np.interp(cellvolt_max,self.param.LookTab_OCV,self.param.LookTab_SOC)
+                            cellvolt_diff=(cellvolt_max-cellvolt_min)*1000
+                            cellsoc_diff=cellsoc_max-cellsoc_min
+                            cellsoc_diff=eval(format(cellsoc_diff,'.1f'))
+                            cellvolt_diff=eval(format(cellvolt_diff,'.0f'))
+                            df_res.loc[len(df_res)]=[self.bmstime[i], self.sn, cellsoc_diff, cellvolt_diff, cellmin_num, cellmax_num]
                     elif standingtime>3600*12:
                         standingtime=0                    
                         cellvolt_now=self._cellvolt_get(i)     #获取当前行电压数据
                         cellvolt_min=min(cellvolt_now)
                         cellvolt_max=max(cellvolt_now)
-                        cellmin_num=cellvolt_now.index(cellvolt_min)+1
-                        cellmax_num=cellvolt_now.index(cellvolt_max)+1
-                        cellsoc_min=np.interp(cellvolt_min,self.param.LookTab_OCV,self.param.LookTab_SOC)
-                        cellsoc_max=np.interp(cellvolt_max,self.param.LookTab_OCV,self.param.LookTab_SOC)
-                        cellvolt_diff=(cellvolt_max-cellvolt_min)*1000
-                        cellsoc_diff=cellsoc_max-cellsoc_min
-                        cellsoc_diff=eval(format(cellsoc_diff,'.1f'))
-                        cellvolt_diff=eval(format(cellvolt_diff,'.0f'))
-                        df_res.loc[len(df_res)]=[self.bmstime[i], self.sn, cellsoc_diff, cellvolt_diff, cellmin_num, cellmax_num]
+                        if 3<cellvolt_min<4.5 and 3<cellvolt_max<4.5:
+                            cellmin_num=cellvolt_now.index(cellvolt_min)+1
+                            cellmax_num=cellvolt_now.index(cellvolt_max)+1
+                            cellsoc_min=np.interp(cellvolt_min,self.param.LookTab_OCV,self.param.LookTab_SOC)
+                            cellsoc_max=np.interp(cellvolt_max,self.param.LookTab_OCV,self.param.LookTab_SOC)
+                            cellvolt_diff=(cellvolt_max-cellvolt_min)*1000
+                            cellsoc_diff=cellsoc_max-cellsoc_min
+                            cellsoc_diff=eval(format(cellsoc_diff,'.1f'))
+                            cellvolt_diff=eval(format(cellvolt_diff,'.0f'))
+                            df_res.loc[len(df_res)]=[self.bmstime[i], self.sn, cellsoc_diff, cellvolt_diff, cellmin_num, cellmax_num]
                     elif i>=len(self.df_bms)-4:
                         standingtime=0
                         cellvolt_now=self._cellvolt_get(i)     #获取当前行电压数据
                         cellvolt_min=min(cellvolt_now)
                         cellvolt_max=max(cellvolt_now)
-                        cellmin_num=cellvolt_now.index(cellvolt_min)+1
-                        cellmax_num=cellvolt_now.index(cellvolt_max)+1
-                        cellsoc_min=np.interp(cellvolt_min,self.param.LookTab_OCV,self.param.LookTab_SOC)
-                        cellsoc_max=np.interp(cellvolt_max,self.param.LookTab_OCV,self.param.LookTab_SOC)
-                        cellvolt_diff=(cellvolt_max-cellvolt_min)*1000
-                        cellsoc_diff=cellsoc_max-cellsoc_min
-                        cellsoc_diff=eval(format(cellsoc_diff,'.1f'))
-                        cellvolt_diff=eval(format(cellvolt_diff,'.0f'))
-                        df_res.loc[len(df_res)]=[self.bmstime[i], self.sn, cellsoc_diff, cellvolt_diff, cellmin_num, cellmax_num]
+                        if 3<cellvolt_min<4.5 and 3<cellvolt_max<4.5:
+                            cellmin_num=cellvolt_now.index(cellvolt_min)+1
+                            cellmax_num=cellvolt_now.index(cellvolt_max)+1
+                            cellsoc_min=np.interp(cellvolt_min,self.param.LookTab_OCV,self.param.LookTab_SOC)
+                            cellsoc_max=np.interp(cellvolt_max,self.param.LookTab_OCV,self.param.LookTab_SOC)
+                            cellvolt_diff=(cellvolt_max-cellvolt_min)*1000
+                            cellsoc_diff=cellsoc_max-cellsoc_min
+                            cellsoc_diff=eval(format(cellsoc_diff,'.1f'))
+                            cellvolt_diff=eval(format(cellvolt_diff,'.0f'))
+                            df_res.loc[len(df_res)]=[self.bmstime[i], self.sn, cellsoc_diff, cellvolt_diff, cellmin_num, cellmax_num]
                         break
                     else:
                         continue
@@ -249,28 +251,30 @@ class BatUniform:
                     cellvolt_now=self._cellvolt_get(i)     #获取当前行电压数据
                     cellvolt_min=min(cellvolt_now)
                     cellvolt_max=max(cellvolt_now)
-                    if abs(self.packcrnt[i+2]) >= 0.1 and cellvolt_max < self.param.OcvInflexionBelow:     
-                        standingtime=0                   
-                        cellmin_num=cellvolt_now.index(cellvolt_min)+1
-                        cellmax_num=cellvolt_now.index(cellvolt_max)+1
-                        cellsoc_min=np.interp(cellvolt_min,self.param.LookTab_OCV,self.param.LookTab_SOC)
-                        cellsoc_max=np.interp(cellvolt_max,self.param.LookTab_OCV,self.param.LookTab_SOC)
-                        cellvolt_diff=(cellvolt_max-cellvolt_min)*1000
-                        cellsoc_diff=cellsoc_max-cellsoc_min
-                        cellsoc_diff=eval(format(cellsoc_diff,'.1f'))
-                        cellvolt_diff=eval(format(cellvolt_diff,'.0f'))
-                        df_res.loc[len(df_res)]=[self.bmstime[i], self.sn, cellsoc_diff, cellvolt_diff, cellmin_num, cellmax_num]
-                    elif i>=len(self.df_bms)-4 and cellvolt_max < self.param.OcvInflexionBelow:
+                    if abs(self.packcrnt[i+2]) >= 0.1:     
+                        standingtime=0  
+                        if 2 < cellvolt_max < self.param.OcvInflexionBelow:                 
+                            cellmin_num=cellvolt_now.index(cellvolt_min)+1
+                            cellmax_num=cellvolt_now.index(cellvolt_max)+1
+                            cellsoc_min=np.interp(cellvolt_min,self.param.LookTab_OCV,self.param.LookTab_SOC)
+                            cellsoc_max=np.interp(cellvolt_max,self.param.LookTab_OCV,self.param.LookTab_SOC)
+                            cellvolt_diff=(cellvolt_max-cellvolt_min)*1000
+                            cellsoc_diff=cellsoc_max-cellsoc_min
+                            cellsoc_diff=eval(format(cellsoc_diff,'.1f'))
+                            cellvolt_diff=eval(format(cellvolt_diff,'.0f'))
+                            df_res.loc[len(df_res)]=[self.bmstime[i], self.sn, cellsoc_diff, cellvolt_diff, cellmin_num, cellmax_num]
+                    elif i>=len(self.df_bms)-4:
                         standingtime=0
-                        cellmin_num=cellvolt_now.index(cellvolt_min)+1
-                        cellmax_num=cellvolt_now.index(cellvolt_max)+1
-                        cellsoc_min=np.interp(cellvolt_min,self.param.LookTab_OCV,self.param.LookTab_SOC)
-                        cellsoc_max=np.interp(cellvolt_max,self.param.LookTab_OCV,self.param.LookTab_SOC)
-                        cellvolt_diff=(cellvolt_max-cellvolt_min)*1000
-                        cellsoc_diff=cellsoc_max-cellsoc_min
-                        cellsoc_diff=eval(format(cellsoc_diff,'.1f'))
-                        cellvolt_diff=eval(format(cellvolt_diff,'.0f'))
-                        df_res.loc[len(df_res)]=[self.bmstime[i], self.sn, cellsoc_diff, cellvolt_diff, cellmin_num, cellmax_num]
+                        if 2 < cellvolt_max < self.param.OcvInflexionBelow:
+                            cellmin_num=cellvolt_now.index(cellvolt_min)+1
+                            cellmax_num=cellvolt_now.index(cellvolt_max)+1
+                            cellsoc_min=np.interp(cellvolt_min,self.param.LookTab_OCV,self.param.LookTab_SOC)
+                            cellsoc_max=np.interp(cellvolt_max,self.param.LookTab_OCV,self.param.LookTab_SOC)
+                            cellvolt_diff=(cellvolt_max-cellvolt_min)*1000
+                            cellsoc_diff=cellsoc_max-cellsoc_min
+                            cellsoc_diff=eval(format(cellsoc_diff,'.1f'))
+                            cellvolt_diff=eval(format(cellvolt_diff,'.0f'))
+                            df_res.loc[len(df_res)]=[self.bmstime[i], self.sn, cellsoc_diff, cellvolt_diff, cellmin_num, cellmax_num]
                     else:
                         pass
                 else:
@@ -281,7 +285,7 @@ class BatUniform:
 
             #获取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]<45:     #充电开始
+                if self.packcrnt[i]<=-1 and self.packcrnt[i+1]<=-1 and self.packcrnt[i+2]<=-1 and self.bms_soc[i]<40:     #充电开始
                     charging=1
                     if len(chrg_start)>len(chrg_end):
                         chrg_start[-1]=i
@@ -331,26 +335,31 @@ class BatUniform:
             peaksoc_list=[]
             for i in range(len(chrg_end)):
                 peaksoc_list = []
-                for j in range(1, self.param.CellVoltNums + 1):
-                    s = str(j)
-                    cellvolt = self.df_bms['单体电压' + s]
-                    cellvolt = list(cellvolt[chrg_start[i]:chrg_end[i]])
-                    time = list(self.bmstime[chrg_start[i]:chrg_end[i]])
-                    packcrnt = list(self.packcrnt[chrg_start[i]:chrg_end[i]])
-                    soc = list(self.bms_soc[chrg_start[i]:chrg_end[i]])
-                    peaksoc = self._dvdq_peak(time, soc, cellvolt, packcrnt)
-                    if peaksoc>1:
-                        peaksoc_list.append(peaksoc)    #计算到达峰值点的累计Soc
+                self._celltemp_weight(chrg_start[i])
+                if min(self.celltemp)>10:
+                    for j in range(1, self.param.CellVoltNums + 1):
+                        s = str(j)
+                        cellvolt = self.df_bms['单体电压' + s]/1000
+                        cellvolt = list(cellvolt[chrg_start[i]:chrg_end[i]])
+                        time = list(self.bmstime[chrg_start[i]:chrg_end[i]])
+                        packcrnt = list(self.packcrnt[chrg_start[i]:chrg_end[i]])
+                        soc = list(self.bms_soc[chrg_start[i]:chrg_end[i]])
+                        peaksoc = self._dvdq_peak(time, soc, cellvolt, packcrnt)
+                        if peaksoc>1:
+                            peaksoc_list.append(peaksoc)    #计算到达峰值点的累计Soc
+                        else:
+                            pass
+                    if len(peaksoc_list)>self.param.CellVoltNums/2:
+                        peaksoc_max=max(peaksoc_list)
+                        peaksoc_min=min(peaksoc_list)
+                        peaksoc_maxnum=peaksoc_list.index(peaksoc_min)+1
+                        peaksoc_minnum=peaksoc_list.index(peaksoc_max)+1
+                        cellsoc_diff=peaksoc_max-peaksoc_min
+                        cellsoc_diff=eval(format(cellsoc_diff,'.1f'))
+                        df_res.loc[len(df_res)]=[self.bmstime[chrg_start[i]], self.sn, cellsoc_diff, 0, peaksoc_minnum, peaksoc_maxnum]
                     else:
                         pass
-                if len(peaksoc_list)>11:
-                    peaksoc_max=max(peaksoc_list)
-                    peaksoc_min=min(peaksoc_list)
-                    peaksoc_maxnum=peaksoc_list.index(peaksoc_min)+1
-                    peaksoc_minnum=peaksoc_list.index(peaksoc_max)+1
-                    cellsoc_diff=peaksoc_max-peaksoc_min
-                    cellsoc_diff=eval(format(cellsoc_diff,'.1f'))
-                    df_res.loc[len(df_res)]=[self.bmstime[chrg_start[i]], self.sn, cellsoc_diff, 0, peaksoc_minnum, peaksoc_maxnum]
+                    # plt.show()
                 else:
                     pass