Browse Source

内短路取静置电压由之前的取一个点变为取前半小时的数据平均

qingfeng 3 years ago
parent
commit
6666ea553c

+ 208 - 34
LIB/MIDDLE/CellStateEstimation/BatSafetyWarning/V1_0_1/CBMSBatInterShort.py

@@ -100,6 +100,16 @@ class BatInterShort():
         else:
             cellvolt=pd.DataFrame()
         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
 
     #获取当前行所有电压数据........................................................................................
     def _cellvolt_get(self,num):
@@ -107,11 +117,11 @@ class BatInterShort():
         return cellvolt
 
     #获取当前行所有soc差...........................................................................................
-    def _celldeltsoc_get(self,num,dict_baltime,capacity): 
+    def _celldeltsoc_get(self,cellvolt_list,dict_baltime,capacity): 
         cellsoc=[]
         celldeltsoc=[]
         for j in range(1, self.param.CellVoltNums+1):   #获取每个电芯电压对应的SOC值
-            cellvolt=self.df_bms.loc[num,'单体电压' + str(j)]/1000
+            cellvolt=cellvolt_list[j+1]
             ocv_soc=np.interp(cellvolt,self.param.LookTab_OCV,self.param.LookTab_SOC)
             if j in dict_baltime.keys():
                 ocv_soc=ocv_soc+dict_baltime[j]*self.param.BalCurrent/(capacity*3600)   #补偿均衡电流
@@ -194,6 +204,87 @@ class BatInterShort():
                 celldeltAs.append(cellAs[j]-cellAsmean)
             
         return np.array(celldeltAs)
+    
+    #寻找DVDQ的峰值点,并返回..........................................................................................................................
+    def _dvdq_peak(self, time, soc, cellvolt, packcrnt):
+        cellvolt = self._np_move_avg(cellvolt, 3, mode="same")
+        Soc = 0
+        Ah = 0
+        Volt = cellvolt[0]
+        DV_Volt = []
+        DQ_Ah = []
+        DVDQ = []
+        time1 = []
+        soc1 = []
+        soc2 = []
+        xvolt=[]
+
+        for m in range(1, len(time)):
+            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.0015 and Ah>0:
+                DQ_Ah.append(Ah)
+                DV_Volt.append(cellvolt[m]-Volt)
+                DVDQ.append((DV_Volt[-1])/Ah)
+                xvolt.append(cellvolt[m])
+                Volt=cellvolt[m]
+                Ah = 0
+                soc1.append(Soc)
+                time1.append(time[m])
+                soc2.append(soc[m])
+
+        #切片,去除前后10min的数据
+        df_Data1 = pd.DataFrame({'time': time1,
+                                'SOC': soc2,
+                                'DVDQ': DVDQ,
+                                'AhSoc': soc1,
+                                '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(time1)-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']<self.param.PeakVoltUpLmt)]
+
+        # print(packcrnt[int(len(time)/2)], min(self.celltemp))
+        # ax1 = plt.subplot(3, 1, 1)
+        # plt.plot(df_Data1['SOC'],df_Data1['DQ_Ah'],'g*-')
+        # plt.xlabel('SOC/%')
+        # plt.ylabel('DQ_Ah')
+        # 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()
+
+        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) > 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) > 1 and df_Data1.loc[PeakIndex,'XVOLT']<self.param.PeakVoltUpLmt-0.015:
+                    return df_Data1['AhSoc'][PeakIndex]
+                else:
+                    return 0
+        else:
+            return 0
 
     #计算每个电芯的均衡时长..........................................................................................................................
     def _bal_time(self,dict_bal):
@@ -325,7 +416,7 @@ class BatInterShort():
 
                             if 2<cellvolt_min<4.5 and 2<cellvolt_max<4.5 and (45<cellsoc_max or cellsoc_max<30) and (45<cellsoc_min or cellsoc_min<30): 
                                 dict_baltime={}   #获取每个电芯的均衡时间
-                                deltsoc_last, cellsoc_last=self._celldeltsoc_get(i,dict_baltime,capacity)
+                                deltsoc_last, cellsoc_last=self._celldeltsoc_get(cellvolt_now,dict_baltime,capacity)
                                 time_last=self.bmstime[i]
                                 firsttime=0
                                 df_ram_last.loc[0]=[self.sn,time_last,deltsoc_last,cellsoc_last]   #更新RAM信息
@@ -344,7 +435,7 @@ class BatInterShort():
                         
                         if 2<cellvolt_min<4.5 and 2<cellvolt_max<4.5 and (45<cellsoc_max or cellsoc_max<30) and (45<cellsoc_min or cellsoc_min<30):
                             dict_baltime=self._bal_time(dict_bal)   #获取每个电芯的均衡时间
-                            deltsoc_now, cellsoc_now=self._celldeltsoc_get(i,dict_baltime,capacity)
+                            deltsoc_now, cellsoc_now=self._celldeltsoc_get(cellvolt_now,dict_baltime,capacity)
                             time_now=self.bmstime[i]
                             if -5<max(cellsoc_now-cellsoc_last)<5:
                                 df_ram_last.loc[0]=[self.sn,time_now,deltsoc_now,cellsoc_now] #更新RAM信息
@@ -388,10 +479,10 @@ class BatInterShort():
                         # deltvolt1=max(abs(cellvolt_now1-cellvolt_last1))
                         cellsoc_now1=np.interp(cellvolt_max1,self.param.LookTab_OCV,self.param.LookTab_SOC)
 
-                        if cellsoc_now1>=self.param.FullChrgSoc-10 and 2<cellvolt_min1<4.5 and 2<cellvolt_max1<4.5:
+                        if cellsoc_now1>self.param.FullChrgSoc-10 and 2<cellvolt_min1<4.5 and 2<cellvolt_max1<4.5:
                             if firsttime1==1:
                                 dict_baltime1={}   #获取每个电芯的均衡时间
-                                deltsoc_last1, cellsoc_last1=self._celldeltsoc_get(i,dict_baltime1,capacity)
+                                deltsoc_last1, cellsoc_last1=self._celldeltsoc_get(cellvolt_now1,dict_baltime1,capacity)
                                 time_last1=self.bmstime[i]
                                 firsttime1=0
                                 df_ram_last1.loc[0]=[self.sn,time_last1,deltsoc_last1]    #更新RAM信息
@@ -399,7 +490,7 @@ class BatInterShort():
                                 dict_baltime1=self._bal_time(dict_bal1)   #获取每个电芯的均衡时间
                                 time_now1=self.bmstime[i]
                                 if (time_now1-time_last1).total_seconds()>3600*20:
-                                    deltsoc_now1, cellsoc_now1=self._celldeltsoc_get(i,dict_baltime1,capacity)
+                                    deltsoc_now1, cellsoc_now1=self._celldeltsoc_get(cellvolt_now1,dict_baltime1,capacity)
                                     df_ram_last1.loc[0]=[self.sn,time_now1,deltsoc_now1] #更新RAM信息
 
                                     list_sub1=deltsoc_now1-deltsoc_last1
@@ -538,7 +629,7 @@ class BatInterShort():
 
                             if cellsoc_max<self.param.SocInflexion1-2 and 12<cellsoc_min:
                                 dict_baltime={}  #获取每个电芯的均衡时间
-                                deltsoc_last, cellsoc_last=self._celldeltsoc_get(i,dict_baltime,capacity)
+                                deltsoc_last, cellsoc_last=self._celldeltsoc_get(cellvolt_now,dict_baltime,capacity)
                                 time_last=self.bmstime[i]
                                 firsttime=0
                                 df_ram_last.loc[0]=[self.sn,time_last,deltsoc_last,cellsoc_last]   #更新RAM信息
@@ -559,7 +650,7 @@ class BatInterShort():
 
                         if cellsoc_max<self.param.SocInflexion1-2 and 12<cellsoc_min:
                             dict_baltime=self._bal_time(dict_bal)   #获取每个电芯的均衡时间
-                            deltsoc_now, cellsoc_now=self._celldeltsoc_get(i, dict_baltime,capacity)    #获取每个电芯的SOC差
+                            deltsoc_now, cellsoc_now=self._celldeltsoc_get(cellvolt_now, dict_baltime,capacity)    #获取每个电芯的SOC差
                             time_now=self.bmstime[i]
                             if -5<max(cellsoc_now-cellsoc_last)<5:
                                 df_ram_last.loc[0]=[self.sn,time_now,deltsoc_now,cellsoc_now]   #更新RAM信息
@@ -609,13 +700,13 @@ class BatInterShort():
                         if cellsoc_max1<self.param.SocInflexion1-2 and 12<cellsoc_min1:
                             if firsttime1==1:
                                 dict_baltime1=self._bal_time(dict_bal1)   #获取每个电芯的均衡时间
-                                deltsoc_last1, cellsoc_last1=self._celldeltsoc_get(i,dict_baltime1,capacity)
+                                deltsoc_last1, cellsoc_last1=self._celldeltsoc_get(cellvolt_now1,dict_baltime1,capacity)
                                 time_last1=self.bmstime[i]
                                 firsttime1=0
                                 df_ram_last1.loc[0]=[self.sn,time_last1,deltsoc_last1]    #更新RAM信息
                             else:
                                 dict_baltime1=self._bal_time(dict_bal1)   #获取每个电芯的均衡时间
-                                deltsoc_now1, cellsoc_now1=self._celldeltsoc_get(i,dict_baltime1,capacity)
+                                deltsoc_now1, cellsoc_now1=self._celldeltsoc_get(cellvolt_now1,dict_baltime1,capacity)
                                 time_now1=self.bmstime[i]
                                 df_ram_last1.loc[0]=[self.sn,time_now1,deltsoc_now1]    #更新RAM信息
 
@@ -664,7 +755,7 @@ class BatInterShort():
             #判断充电状态
             if self.packcrnt[i]<=-1 and self.packcrnt[i+1]<=-1 and self.packcrnt[i-1]<=-1:
                 if charging==0:
-                    if self.bms_soc[i]<40:
+                    if self.bms_soc[i]<41:
                         cellvolt_now=self._cellvolt_get(i)
                         if min(cellvolt_now)<self.param.CellFullChrgVolt-0.15:
                             charging=1
@@ -676,42 +767,125 @@ class BatInterShort():
 
                 else: #充电中
                     cellvolt_now=self._cellvolt_get(i)
-                    if (self.bmstime[i+1]-self.bmstime[i]).total_seconds()>180 or (self.packcrnt[i]>self.param.Capacity/3 and self.packcrnt[i+1]>self.param.Capacity/3):  #如果充电过程中时间间隔>180s,则舍弃该次充电
+                    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,则舍弃该次充电
                         charging=0
                         continue
-                    elif min(cellvolt_now)>self.param.CellFullChrgVolt-0.13:   #电压>满充电压-0.13V,即3.37V
+                    # elif min(cellvolt_now)>self.param.CellFullChrgVolt-0.13:   #电压>满充电压-0.13V,即3.37V
+                    #     self._celltemp_weight(i)
+                    #     if i-chrg_start>10 and self.celltemp>20:
+                    #         chrg_end=i+1
+                    #         charging=0
+
+                    #         #计算漏电流值...................................................................
+                    #         if firsttime2==1:
+                    #             dict_baltime={}
+                    #             deltAs_last2=self._cellDeltAs_get(chrg_start,chrg_end,dict_baltime)
+                    #             time_last2=self.bmstime[chrg_end]
+                    #             df_ram_last2.loc[0]=[self.sn,time_last2,deltAs_last2]    #更新RAM信息
+                    #         else:
+                    #             dict_baltime=self._bal_time(dict_bal2)   #获取每个电芯的均衡时间
+                    #             deltAs_now2=self._cellDeltAs_get(chrg_start,chrg_end,dict_baltime)  #获取每个电芯的As差
+                    #             time_now2=self.bmstime[chrg_end]
+                    #             df_ram_last2.loc[0]=[self.sn,time_now2,deltAs_now2]    #更新RAM信息
+
+                    #             list_sub2=deltAs_now2-deltAs_last2
+                    #             list_pud2=-1000/(time_now2-time_last2).total_seconds()
+                    #             leak_current2=list_sub2*list_pud2
+                    #             # leak_current=np.array(leak_current)
+                    #             leak_current2=np.round(leak_current2,3)
+                    #             leak_current2=list(leak_current2)
+
+                    #             df_res.loc[len(df_res)]=[time_last2,time_now2,self.sn,3,str(leak_current2),str(dict_baltime)]  #计算结果存入Dataframe
+                    #             deltAs_last2=deltAs_now2
+                    #             time_last2=time_now2
+                    #             dict_bal2={}
+
+                    #     else:
+                    #         charging=0
+                    #         continue
+                    elif min(cellvolt_now)>self.param.CellFullChrgVolt-0.1:   #电压>满充电压
                         self._celltemp_weight(i)
-                        if i-chrg_start>10 and self.celltemp>20:
+                        if i-chrg_start>10 and self.celltemp>10:
                             chrg_end=i+1
                             charging=0
 
                             #计算漏电流值...................................................................
                             if firsttime2==1:
                                 dict_baltime={}
-                                deltAs_last2=self._cellDeltAs_get(chrg_start,chrg_end,dict_baltime)
-                                time_last2=self.bmstime[chrg_end]
-                                df_ram_last2.loc[0]=[self.sn,time_last2,deltAs_last2]    #更新RAM信息
+                                peaksoc_list=[]
+                                for j in range(1, self.param.CellVoltNums + 1):
+                                    cellvolt = self._singlevolt_get(i,j,2)  #取单体电压j的所有电压值
+                                    cellvolt = list(cellvolt[chrg_start:chrg_end])
+                                    time = list(self.bmstime[chrg_start:chrg_end])
+                                    packcrnt = list(self.packcrnt[chrg_start:chrg_end])
+                                    soc = list(self.bms_soc[chrg_start:chrg_end])
+                                    peaksoc = self._dvdq_peak(time, soc, cellvolt, packcrnt)
+                                    if peaksoc>1:
+                                        peaksoc_list.append(peaksoc)
+                                    else:
+                                        break
+                                if len(peaksoc_list)==self.param.CellVoltNums:
+                                    celldeltsoc=[]
+                                    consum_num=10
+                                    cellsoc1=peaksoc_list[:self.param.CellVoltNums-consum_num]    #切片,将bms耗电的电芯和非耗电的电芯分离开
+                                    cellsocmean1=(sum(cellsoc1)-max(cellsoc1)-min(cellsoc1))/(len(cellsoc1)-2)
+                                    cellsoc2=peaksoc_list[self.param.CellVoltNums-consum_num:]
+                                    cellsocmean2=(sum(cellsoc2)-max(cellsoc2)-min(cellsoc2))/(len(cellsoc2)-2)
+                                    
+                                    for j in range(len(peaksoc_list)):   #计算每个电芯的soc差
+                                        if j<self.param.CellVoltNums-consum_num:
+                                            celldeltsoc.append(peaksoc_list[j]-cellsocmean1)
+                                        else:
+                                            celldeltsoc.append(peaksoc_list[j]-cellsocmean2)
+                                    deltsoc_last2=celldeltsoc
+                                    time_last2=self.bmstime[chrg_end]
+                                    df_ram_last2.loc[0]=[self.sn,time_last2,deltsoc_last2]    #更新RAM信息
                             else:
                                 dict_baltime=self._bal_time(dict_bal2)   #获取每个电芯的均衡时间
-                                deltAs_now2=self._cellDeltAs_get(chrg_start,chrg_end,dict_baltime)  #获取每个电芯的As差
-                                time_now2=self.bmstime[chrg_end]
-                                df_ram_last2.loc[0]=[self.sn,time_now2,deltAs_now2]    #更新RAM信息
-
-                                list_sub2=deltAs_now2-deltAs_last2
-                                list_pud2=-1000/(time_now2-time_last2).total_seconds()
-                                leak_current2=list_sub2*list_pud2
-                                # leak_current=np.array(leak_current)
-                                leak_current2=np.round(leak_current2,3)
-                                leak_current2=list(leak_current2)
-
-                                df_res.loc[len(df_res)]=[time_last2,time_now2,self.sn,3,str(leak_current2),str(dict_baltime)]  #计算结果存入Dataframe
-                                deltAs_last2=deltAs_now2
-                                time_last2=time_now2
-                                dict_bal2={}
-
+                                peaksoc_list=[]
+                                for j in range(1, self.param.CellVoltNums + 1):
+                                    cellvolt = self._singlevolt_get(i,j,2)  #取单体电压j的所有电压值
+                                    cellvolt = list(cellvolt[chrg_start:chrg_end])
+                                    time = list(self.bmstime[chrg_start:chrg_end])
+                                    packcrnt = list(self.packcrnt[chrg_start:chrg_end])
+                                    soc = list(self.bms_soc[chrg_start:chrg_end])
+                                    peaksoc = self._dvdq_peak(time, soc, cellvolt, packcrnt)
+                                    if peaksoc>1:
+                                        peaksoc_list.append(peaksoc)
+                                    else:
+                                        break
+                                if len(peaksoc_list)==self.param.CellVoltNums:
+                                    celldeltsoc=[]
+                                    consum_num=10
+                                    cellsoc1=peaksoc_list[:self.param.CellVoltNums-consum_num]    #切片,将bms耗电的电芯和非耗电的电芯分离开
+                                    cellsocmean1=(sum(cellsoc1)-max(cellsoc1)-min(cellsoc1))/(len(cellsoc1)-2)
+                                    cellsoc2=peaksoc_list[self.param.CellVoltNums-consum_num:]
+                                    cellsocmean2=(sum(cellsoc2)-max(cellsoc2)-min(cellsoc2))/(len(cellsoc2)-2)
+                                    
+                                    for j in range(len(peaksoc_list)):   #计算每个电芯的soc差
+                                        if j<self.param.CellVoltNums-consum_num:
+                                            celldeltsoc.append(peaksoc_list[j]-cellsocmean1)
+                                        else:
+                                            celldeltsoc.append(peaksoc_list[j]-cellsocmean2)
+                                    deltsoc_now2=celldeltsoc
+                                    time_now2=self.bmstime[chrg_end]
+                                    df_ram_last2.loc[0]=[self.sn,time_now2,deltsoc_now2]    #更新RAM信息
+
+                                    list_sub2=deltsoc_now2-deltsoc_last2
+                                    list_pud2=(0.01*capacity*3600*1000)/(time_now2-time_last2).total_seconds()
+                                    leak_current2=list_sub2*list_pud2
+                                    leak_current2=np.round(leak_current2,3)
+                                    leak_current2=list(leak_current2)
+
+                                    df_res.loc[len(df_res)]=[time_last2,time_now2,self.sn,3,str(leak_current2),str(dict_baltime)]  #计算结果存入Dataframe
+                                    deltsoc_last2=deltsoc_now2
+                                    time_last2=time_now2
+                                    dict_bal2={}
+                        
                         else:
                             charging=0
                             continue
+
                     elif i==len(self.df_bms)-2:  #数据中断后仍在充电,将前段充电数据写入RAM
                         df_ram_lfp=self.df_bms.iloc[chrg_start:]
                         df_ram_lfp['sn']=self.sn