Browse Source

新内短路算法部署,删除原有内短路短发

qingfeng 3 years ago
parent
commit
39b72355cc

+ 5 - 0
LIB/MIDDLE/CellStateEstimation/Common/BatParam.py

@@ -30,6 +30,7 @@ class BatParam:
             self.FullChrgSoc=98
             self.PeakSoc=57
             self.PackCrntDec=1
+            self.BalCurrent=0.025
             self.LookTab_SOC = [0,	    3.5348,	8.3581,	13.181,	18.004,	22.827,	27.651,	32.474,	37.297,	42.120,	46.944,	51.767,	56.590,	61.413,	66.237,	71.060,	75.883,	80.707,	85.530,	90.353,	95.176,	100,   105]
             self.LookTab_OCV = [3.3159,	3.4384,	3.4774,	3.5156,	3.5478,	3.5748,	3.6058,	3.6238,	3.638,	3.6535,	3.6715,	3.6951,	3.7279,	3.7757,	3.8126,	3.8529,	3.8969,	3.9446,	3.9946,	4.0491,	4.109,	4.183, 4.263]
         
@@ -42,6 +43,7 @@ class BatParam:
             self.FullChrgSoc=98
             self.PeakSoc=57
             self.PackCrntDec=1
+            self.BalCurrent=0.025
             self.LookTab_SOC = [0,	    3.5348,	8.3581,	13.181,	18.004,	22.827,	27.651,	32.474,	37.297,	42.120,	46.944,	51.767,	56.590,	61.413,	66.237,	71.060,	75.883,	80.707,	85.530,	90.353,	95.176,	100,   105]
             self.LookTab_OCV = [3.3159,	3.4384,	3.4774,	3.5156,	3.5478,	3.5748,	3.6058,	3.6238,	3.638,	3.6535,	3.6715,	3.6951,	3.7279,	3.7757,	3.8126,	3.8529,	3.8969,	3.9446,	3.9946,	4.0491,	4.109,	4.183, 4.263]
         
@@ -54,6 +56,7 @@ class BatParam:
             self.FullChrgSoc=98
             self.PeakSoc=57
             self.PackCrntDec=1
+            self.BalCurrent=0.025
             self.LookTab_SOC = [0,	    5,	    10,	    15,	    20,	    25,	    30,	    35,	    40,	    45,	    50,	    55,	    60,	    65,	    70,	    75,	    80,	    85,	    90,	    95,	    100,   105]
             self.LookTab_OCV = [3.357, 	3.455, 	3.493, 	3.540, 	3.577, 	3.605, 	3.622, 	3.638, 	3.655, 	3.677, 	3.707, 	3.757, 	3.815, 	3.866, 	3.920, 	3.976, 	4.036, 	4.099, 	4.166, 	4.237, 	4.325, 4.415]
         
@@ -66,6 +69,7 @@ class BatParam:
             self.FullChrgSoc=98
             self.PeakSoc=57
             self.PackCrntDec=-1
+            self.BalCurrent=0.025
             self.LookTab_SOC = [0,	    5,	    10,	    15,	    20,	    25,	    30,	    35,	    40,	    45,	    50,	    55,	    60,	    65,	    70,	    75,	    80,	    85,	    90,	    95,	    100,   105]
             self.LookTab_OCV = [3.152, 	3.397, 	3.438, 	3.481, 	3.523, 	3.560, 	3.586, 	3.604, 	3.620, 	3.638, 	3.661, 	3.693, 	3.748, 	3.803, 	3.853, 	3.903, 	3.953, 	4.006, 	4.063, 	4.121, 	4.183, 4.253]
         
@@ -83,6 +87,7 @@ class BatParam:
             self.PeakSoc=60.5
             self.PeakCellVolt=[3.357,3.358,3.359,3.36,3.361]
             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]
             self.LookTab_OCV = [2.7151,	3.0298,	3.1935,	3.2009,	3.2167,	3.2393,	3.2561,	3.2703,	3.2843,	3.2871,	3.2874,	3.2868,	3.2896,	3.2917,	3.2967,	3.3128,	3.3283,	3.3286,	3.3287,	3.3288,	3.3289,	3.3296,	3.3302,	3.3314,	3.3429]
         

+ 564 - 0
LIB/MIDDLE/CellStateEstimation/InterShort/V1_0_0/CBMSBatInterShort.py

@@ -0,0 +1,564 @@
+import pandas as pd
+import numpy as np
+import matplotlib.pyplot as plt
+from pymysql import paramstyle
+from LIB.MIDDLE.CellStateEstimation.Common import BatParam
+from LIB.MIDDLE.CellStateEstimation.Common import DBDownload
+
+class BatInterShort:
+    def __init__(self,sn,celltype,df_bms, host, port, db, user, password, tablename):  #参数初始化
+
+        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.bmstime= pd.to_datetime(df_bms['时间戳'], format='%Y-%m-%d %H:%M:%S')
+
+        self.host=host
+        self.port=port
+        self.db=db
+        self.user=user
+        self.password=password
+        self.tablename=tablename
+    
+    def intershort(self):
+        if self.celltype==1 or self.celltype==2 or self.celltype==3 or self.celltype==4:
+            df_res=self._ncm_intershort()
+            return df_res
+            
+        elif self.celltype==99:
+            df_res=self._lfp_intershort()
+            return df_res
+        
+        else:
+            return pd.DataFrame()
+    
+    #获取预算结果库的结果...............................................................................
+    def getdata(self):  
+        DBManager=DBDownload.DBDownload(self.host, self.port, self.db, self.user, self.password)
+        with DBManager as DBManager:
+            self.df_soh=DBManager.getdata('time_st','time_sp','sn','method','soh','cellsoh', tablename='soh_result', sn=self.sn)
+
+    #定义滑动滤波函数....................................................................................
+    def _np_move_avg(self,a, n, mode="same"): 
+        return (np.convolve(a, np.ones((n,)) / n, mode=mode))
+    
+    #寻找当前行数据的最小温度值.............................................................................
+    def _celltemp_weight(self,num):   
+        celltemp = []
+        for j in range(1, self.param.CellTempNums+1):
+            s = str(j)
+            celltemp.append(self.df_bms.loc[num,'单体温度' + s])
+        celltemp=np.mean(celltemp)
+        self.celltemp=celltemp
+        if self.celltype==99:
+            if celltemp>=20:
+                self.tempweight=1
+                self.StandardStandingTime=3600
+            elif celltemp>=10:
+                self.tempweight=0.6
+                self.StandardStandingTime=7200
+            elif celltemp>=5:
+                self.tempweight=0.
+                self.StandardStandingTime=7200
+            else:
+                self.tempweight=0.1
+                self.StandardStandingTime=10800
+        else:
+            if celltemp>=20:
+                self.tempweight=1
+                self.StandardStandingTime=3600
+            elif celltemp>=10:
+                self.tempweight=0.8
+                self.StandardStandingTime=3600
+            elif celltemp>=5:
+                self.tempweight=0.6
+                self.StandardStandingTime=7200
+            else:
+                self.tempweight=0.2
+                self.StandardStandingTime=10800
+
+    #获取当前行所有电压数据........................................................................................
+    def _cellvolt_get(self,num): 
+        cellvolt=[]
+        for j in range(1, self.param.CellVoltNums+1): 
+            s = str(j)
+            cellvolt.append(self.df_bms.loc[num,'单体电压' + s]/1000)
+        return cellvolt
+
+    #获取当前行所有soc差...........................................................................................
+    def _celldeltsoc_get(self,num,dict_baltime,capacity): 
+        cellsoc=[]
+        celldeltsoc=[]
+        for j in range(1, self.param.CellVoltNums+1):   #获取每个电芯电压对应的SOC值
+            cellvolt=self.df_bms.loc[num,'单体电压' + str(j)]/1000
+            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)   #补偿均衡电流
+            else:
+                pass
+            cellsoc.append(ocv_soc)
+        
+        if self.celltype==1 or self.celltype==2:
+            consum_num=7
+            cellsoc1=cellsoc[:self.param.CellVoltNums-consum_num]    #切片,将bms耗电的电芯和非耗电的电芯分离开
+            cellsocmean1=(sum(cellsoc1)-max(cellsoc1)-min(cellsoc1))/(len(cellsoc1)-2)
+            cellsoc2=cellsoc[self.param.CellVoltNums-consum_num:]
+            cellsocmean2=(sum(cellsoc2)-max(cellsoc2)-min(cellsoc2))/(len(cellsoc2)-2)
+            
+            for j in range(len(cellsoc)):   #计算每个电芯的soc差
+                if j<self.param.CellVoltNums-consum_num:
+                    celldeltsoc.append(cellsoc[j]-cellsocmean1)
+                else:
+                    celldeltsoc.append(cellsoc[j]-cellsocmean2)
+            return celldeltsoc
+
+        else:
+            cellsocmean=(sum(cellsoc)-max(cellsoc)-min(cellsoc))/(len(cellsoc)-2)
+            for j in range(len(cellsoc)):   #计算每个电芯的soc差
+                celldeltsoc.append(cellsoc[j]-cellsocmean)
+            return celldeltsoc
+ 
+    #获取所有电芯的As差
+    def _cellDeltAs_get(self,chrg_st,chrg_end,dict_baltime):
+        cellAs=[]
+        celldeltAs=[]
+        for j in range(1, self.param.CellVoltNums+1):   #获取每个电芯电压>峰值电压的充入As数
+            if j in dict_baltime.keys():    #补偿均衡电流
+                As=-self.param.BalCurrent*dict_baltime[j]
+            else:    
+                As=0
+            As_tatol=0
+            symbol=0
+            for m in range(chrg_st+1,chrg_end):
+                As=As-self.packcrnt[m]*(self.bmstime[m]-self.bmstime[m-1]).total_seconds()
+                if symbol<5:
+                    if self.df_bms.loc[m,'单体电压'+str(j)]/1000>self.param.PeakCellVolt[symbol]:
+                        As_tatol=As_tatol+As
+                        symbol=symbol+1
+                    else:
+                        continue
+                else:
+                    cellAs.append(As_tatol/5)
+                    break
+        
+        if self.celltype==99:
+            consum_num=10
+            cellAs1=cellAs[:self.param.CellVoltNums-consum_num]    #切片,将bms耗电的电芯和非耗电的电芯分离开
+            cellAsmean1=(sum(cellAs1)-max(cellAs1)-min(cellAs1))/(len(cellAs1)-2)
+            cellAs2=cellAs[self.param.CellVoltNums-consum_num:]
+            cellAsmean2=(sum(cellAs2)-max(cellAs2)-min(cellAs2))/(len(cellAs2)-2)
+            
+            for j in range(len(cellAs)):   #计算每个电芯的soc差
+                if j<self.param.CellVoltNums-consum_num:
+                    celldeltAs.append(cellAs[j]-cellAsmean1)
+                else:
+                    celldeltAs.append(cellAs[j]-cellAsmean2)
+        else:
+            cellAsmean=(sum(cellAs)-max(cellAs)-min(cellAs))/(len(cellAs)-2)
+            for j in range(len(cellAs)):   #计算每个电芯的soc差
+                celldeltAs.append(cellAs[j]-cellAsmean)
+            
+        return celldeltAs
+
+    #计算每个电芯的均衡时长..........................................................................................................................
+    def _bal_time(self,dict_bal):
+        dict_baltime={}
+        dict_baltime1={}
+        for key in dict_bal:
+            count=1
+            x=eval(key)
+            while x>0:
+                if x & 1==1:    #判断最后一位是否为1
+                    if count in dict_baltime.keys():
+                        dict_baltime[count] = dict_baltime[count] + dict_bal[key]
+                    else:
+                        dict_baltime[count] = dict_bal[key]
+                else:
+                    pass
+                count += 1
+                x >>= 1    #右移一位
+        
+        dict_baltime=dict(sorted(dict_baltime.items(),key=lambda dict_baltime:dict_baltime[0]))
+        for key in dict_baltime:    #解析均衡的电芯编号
+            if self.celltype==1:    #科易6040
+                if key<14:
+                    dict_baltime1[key]=dict_baltime[key]
+                elif key<18:
+                    dict_baltime1[key-1]=dict_baltime[key]
+                else:
+                    dict_baltime1[key-3]=dict_baltime[key]
+            elif self.celltype==1:    #科易4840
+                if key<4:
+                    dict_baltime1[key-1]=dict_baltime[key]
+                elif key<8:
+                    dict_baltime1[key-1]=dict_baltime[key]
+                elif key<14:
+                    dict_baltime1[key-3]=dict_baltime[key]
+                elif key<18:
+                    dict_baltime1[key-4]=dict_baltime[key]
+                else:
+                    dict_baltime1[key-6]=dict_baltime[key]
+            else:
+                dict_baltime1=dict_baltime
+        return dict_baltime1
+
+    #三元电池的内短路电流计算...........................................................................................................................................................
+    def _ncm_intershort(self):
+        column_name=['time_st', 'time_sp', 'sn', 'method','short_current','baltime']
+        df_res=pd.DataFrame(columns=column_name)
+        
+        if not self.df_bms.empty:
+            self.getdata()  #获取电池包的soh
+            if self.df_soh.empty:
+                batsoh=self.df_bms.loc[0,'SOH[%]']
+                capacity=self.param.Capacity*batsoh/100
+            else:
+                batsoh=self.df_soh.loc[len(self.df_soh)-1,'soh']
+                capacity=self.param.Capacity*batsoh/100
+            standingtime=0
+            standingtime1=0
+            firsttime=1
+            firsttime1=1
+            dict_bal={}
+            dict_bal1={}
+
+            for i in range(2,len(self.df_bms)-2):
+
+                if firsttime1==0:   #满电静置算法--计算均衡状态对应的均衡时间
+                    try:
+                        balstat=int(self.df_bms.loc[i,'单体均衡状态'])
+                        if balstat>0.5:
+                            bal_step=(self.bmstime[i+1]-self.bmstime[i]).total_seconds()  #均衡步长
+                            bal_step=int(bal_step)
+                            if str(balstat) in dict_bal1.keys():
+                                dict_bal1[str(balstat)]=dict_bal1[str(balstat)]+bal_step
+                            else:
+                                dict_bal1[str(balstat)]=bal_step
+                        else:
+                            pass
+                    except:
+                        dict_bal1={}
+                else:
+                    pass
+
+                if abs(self.packcrnt[i]) < 0.1 and abs(self.packcrnt[i-1]) < 0.1:     
+                    delttime=(self.bmstime[i]-self.bmstime[i-1]).total_seconds()
+                    standingtime=standingtime+delttime
+                    standingtime1=standingtime1+delttime
+                    self._celltemp_weight(i)
+
+                    #静置法计算内短路-开始.....................................................................................................................................
+                    if firsttime==1:    
+                        if standingtime>self.StandardStandingTime:      #静置时间满足要求
+                            dict_baltime=self._bal_time(dict_bal)   #获取每个电芯的均衡时间
+                            deltsoc_last=self._celldeltsoc_get(i,dict_baltime,capacity)
+                            time_last=self.bmstime[i]
+                            firsttime=0
+                            standingtime=0
+                        else:
+                            pass                
+                    elif standingtime>3600*12:
+                        standingtime=0
+                        dict_baltime=self._bal_time(dict_bal)   #获取每个电芯的均衡时间
+                        deltsoc_now=self._celldeltsoc_get(i,dict_baltime,capacity)
+                        time_now=self.bmstime[i]
+                        
+                        list_sub=[a-b for a, b in zip(deltsoc_now, deltsoc_last)]
+                        list_pud=[0.01*capacity*3600*1000/(time_now-time_last).total_seconds()]*self.param.CellVoltNums
+                        leak_current=[a*b for a,b in zip(list_sub,list_pud)]
+                        leak_current=np.array(leak_current)
+                        leak_current=np.round(leak_current,3)
+                        leak_current=list(leak_current)
+                        
+                        df_res.loc[len(df_res)]=[time_last,time_now,self.sn,1,str(leak_current),str(dict_baltime)]  #计算结果存入Dataframe
+                        time_last=time_now  #更新时间
+                        deltsoc_last=deltsoc_now    #更新soc差
+                        dict_bal={}
+                    else: 
+                        try:  
+                            balstat=int(self.df_bms.loc[i,'单体均衡状态'])
+                            if balstat>0.5:
+                                bal_step=(self.bmstime[i+1]-self.bmstime[i]).total_seconds()  #均衡步长
+                                bal_step=int(bal_step)
+                                if str(balstat) in dict_bal.keys():
+                                    dict_bal[str(balstat)]=dict_bal[str(balstat)]+bal_step
+                                else:
+                                    dict_bal[str(balstat)]=bal_step
+                            else:
+                                pass
+                        except:
+                            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
+                            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:
+                            pass
+                    else:   
+                        pass
+
+                else:
+                    dict_bal={} 
+                    firsttime=1
+                    standingtime=0
+                    standingtime1=0
+                    pass
+
+        if df_res.empty:    #返回计算结果
+            return pd.DataFrame()
+        else:
+            return df_res
+
+    #磷酸铁锂电池内短路计算程序.............................................................................................................................
+    def _lfp_intershort(self):
+        column_name=['time_st', 'time_sp', 'sn', 'method','short_current','baltime']
+        df_res=pd.DataFrame(columns=column_name)
+        if not self.df_bms.empty:
+            self.getdata()  #获取电池包的soh
+            if self.df_soh.empty:
+                batsoh=self.df_bms.loc[0,'SOH[%]']
+                capacity=self.param.Capacity*batsoh/100
+            else:
+                batsoh=self.df_soh.loc[len(self.df_soh)-1,'soh']
+                capacity=self.param.Capacity*batsoh/100
+            standingtime=0
+            standingtime1=0
+            firsttime=1
+            firsttime1=1
+            dict_bal={}
+            dict_bal1={}
+
+            chrg_start=[]
+            chrg_end=[]
+            dict_bal_list=[]
+            charging=0
+            dict_bal3={}
+
+            for i in range(3,len(self.df_bms)-3):
+
+                #静置法计算内短路..........................................................................................................................
+                if firsttime1==0:   #满电静置算法--计算均衡状态对应的均衡时间
+                    try:
+                        balstat=int(self.df_bms.loc[i,'单体均衡状态'])
+                        if balstat>0.5:
+                            bal_step=(self.bmstime[i+1]-self.bmstime[i]).total_seconds()  #均衡步长
+                            bal_step=int(bal_step)
+                            if str(balstat) in dict_bal1.keys():
+                                dict_bal1[str(balstat)]=dict_bal1[str(balstat)]+bal_step
+                            else:
+                                dict_bal1[str(balstat)]=bal_step
+                        else:
+                            pass
+                    except:
+                        dict_bal1={}
+                else:
+                    pass
+
+                if abs(self.packcrnt[i]) < 0.1 and abs(self.packcrnt[i-1]) < 0.1:     
+                    delttime=(self.bmstime[i]-self.bmstime[i-1]).total_seconds()
+                    standingtime=standingtime+delttime
+                    standingtime1=standingtime1+delttime
+                    self._celltemp_weight(i)
+
+                    #静置法计算内短路-开始.....................................................................................................................................
+                    if firsttime==1:    
+                        if standingtime>self.StandardStandingTime:      #静置时间满足要求
+                            cellvolt=self._cellvolt_get(i)
+                            if max(cellvolt)<self.param.OcvInflexionBelow-0.002:
+                                dict_baltime=self._bal_time(dict_bal)   #获取每个电芯的均衡时间
+                                deltsoc_last=self._celldeltsoc_get(i,dict_baltime,capacity)
+                                time_last=self.bmstime[i]
+                                firsttime=0
+                                standingtime=0
+                            else:
+                                pass
+                        else:
+                            pass                
+                    elif standingtime>3600*12:
+                        cellvolt=self._cellvolt_get(i)
+                        if max(cellvolt)<self.param.OcvInflexionBelow-0.002:
+                            standingtime=0
+                            dict_baltime=self._bal_time(dict_bal)   #获取每个电芯的均衡时间
+                            deltsoc_now=self._celldeltsoc_get(i, dict_baltime,capacity)    #获取每个电芯的SOC差
+                            time_now=self.bmstime[i]
+
+                            list_sub=[a-b for a, b in zip(deltsoc_now, deltsoc_last)]
+                            list_pud=[0.01*capacity*3600*1000/(time_now-time_last).total_seconds()]*self.param.CellVoltNums
+                            leak_current=[a*b for a,b in zip(list_sub,list_pud)]
+                            leak_current=np.array(leak_current)
+                            leak_current=np.round(leak_current,3)
+                            leak_current=list(leak_current)
+                            
+                            df_res.loc[len(df_res)]=[time_last,time_now,self.sn,1,str(leak_current),str(dict_baltime)]  #计算结果存入Dataframe
+                            time_last=time_now  #更新时间
+                            deltsoc_last=deltsoc_now    #更新soc差
+                            dict_bal={}
+                        else:
+                            pass
+                    else: 
+                        try:  
+                            balstat=int(self.df_bms.loc[i,'单体均衡状态'])
+                            if balstat>0.5:
+                                bal_step=(self.bmstime[i+1]-self.bmstime[i]).total_seconds()  #均衡步长
+                                bal_step=int(bal_step)
+                                if str(balstat) in dict_bal.keys():
+                                    dict_bal[str(balstat)]=dict_bal[str(balstat)]+bal_step
+                                else:
+                                    dict_bal[str(balstat)]=bal_step
+                            else:
+                                pass
+                        except:
+                            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
+                                else:
+                                    pass
+                                time_last1=time_now1  #更新时间
+                                deltsoc_last1=deltsoc_now1    #更新soc差
+                                dict_bal1={}
+                        else:
+                            pass
+                    else:   
+                        pass
+
+                else:
+                    dict_bal={} 
+                    firsttime=1
+                    standingtime=0
+                    pass
+
+                #获取充电数据——开始..............................................................................................................
+                try:
+                    balstat=int(self.df_bms.loc[i,'单体均衡状态'])  #统计均衡状态
+                    if balstat>0.5:
+                        bal_step=(self.bmstime[i+1]-self.bmstime[i]).total_seconds()  #均衡步长
+                        bal_step=int(bal_step)
+                        if str(balstat) in dict_bal3.keys():
+                            dict_bal3[str(balstat)]=dict_bal3[str(balstat)]+bal_step
+                        else:
+                            dict_bal3[str(balstat)]=bal_step
+                    else:
+                        pass
+                except:
+                    dict_bal3={}
+
+                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:     #判断充电开始
+                        cellvolt_now=self._cellvolt_get(i)
+                        if min(cellvolt_now)<self.param.CellFullChrgVolt-0.15:
+                            charging=1
+                            if len(chrg_start)>len(chrg_end):
+                                chrg_start[-1]=i
+                            else:
+                                chrg_start.append(i)
+                        else:
+                            pass
+                    else:
+                        pass
+
+                else: #充电中
+                    if (self.bmstime[i+1]-self.bmstime[i]).total_seconds()>180:  #如果充电过程中时间间隔>180s,则舍弃该次充电
+                        chrg_start.remove(chrg_start[-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)
+                        if min(cellvolt_now)>self.param.CellFullChrgVolt-0.13:   #电压>满充电压-0.13V,即3.37V
+                            self._celltemp_weight(i)
+                            if i-chrg_start[-1]>10 and self.celltemp>10:
+                                chrg_end.append(i+1)
+                                dict_bal_list.append(dict_bal3)
+                                dict_bal3={}
+                                charging=0                       
+                                continue
+                            else:
+                                chrg_start.remove(chrg_start[-1])
+                                charging=0
+                                continue
+                        else:
+                            pass
+                    else:
+                        pass   
+            
+            #基于充电数据计算单体电芯的漏电流..........................................................................................................
+            if len(chrg_end)>1:    
+                for i in range(len(chrg_end)):
+                    if i<1:
+                        dict_baltime={}
+                        deltAs_last=self._cellDeltAs_get(chrg_start[i],chrg_end[i],dict_baltime)
+                        time_last=self.bmstime[chrg_end[i]]
+                    else:
+                        dict_baltime=self._bal_time(dict_bal_list[i])   #获取每个电芯的均衡时间
+                        deltAs_now=self._cellDeltAs_get(chrg_start[i],chrg_end[i],dict_baltime)  #获取每个电芯的As差
+                        time_now=self.bmstime[chrg_end[i]]
+
+                        list_sub=[a-b for a, b in zip(deltAs_now, deltAs_last)]
+                        list_pud=[-1000/(time_now-time_last).total_seconds()]*self.param.CellVoltNums
+                        leak_current=[a*b for a,b in zip(list_sub,list_pud)]
+                        leak_current=np.array(leak_current)
+                        leak_current=np.round(leak_current,3)
+                        leak_current=list(leak_current)
+
+                        df_res.loc[len(df_res)]=[time_last,time_now,self.sn,3,str(leak_current),str(dict_baltime)]  #计算结果存入Dataframe
+                        deltAs_last=deltAs_now
+                        time_last=time_now
+            else:
+                pass
+
+        if df_res.empty:
+            return pd.DataFrame()
+        else:
+            return df_res

BIN
LIB/MIDDLE/CellStateEstimation/InterShort/V1_0_0/InterShort表单.xlsx


+ 80 - 0
LIB/MIDDLE/CellStateEstimation/InterShort/main.py

@@ -0,0 +1,80 @@
+import CBMSBatInterShort
+import log
+
+#coding=utf-8
+import sys
+import datetime
+import pandas as pd
+from LIB.BACKEND import DBManager, Log
+from sqlalchemy import create_engine
+import time, datetime
+
+host='rm-bp10j10qy42bzy0q77o.mysql.rds.aliyuncs.com'
+port=3306
+db='qx_cas'
+user='qx_read'
+password='Qx@123456'
+tablename='soh_result'
+
+dbManager = DBManager.DBManager()
+if __name__ == "__main__":
+    excelpath=r'D:\Platform\platform_python\data_analyze_platform\USER\01qixiang\sn-20210903.xlsx'
+    SNdata_6060 = pd.read_excel(excelpath, sheet_name='科易6060')
+    SNdata_6040 = pd.read_excel(excelpath, sheet_name='科易6040')
+    SNdata_4840 = pd.read_excel(excelpath, sheet_name='科易4840')
+    SNdata_L7255 = pd.read_excel(excelpath, sheet_name='格林美-力信7255')
+    SNdata_C7255 = pd.read_excel(excelpath, sheet_name='格林美-CATL7255')
+    SNdata_U7255 = pd.read_excel(excelpath, sheet_name='优旦7255')
+    SNnums_6060=SNdata_6060['SN号'].tolist()
+    SNnums_6040=SNdata_6040['SN号'].tolist()
+    SNnums_4840=SNdata_4840['SN号'].tolist()
+    SNnums_L7255=SNdata_L7255['SN号'].tolist()
+    SNnums_C7255=SNdata_C7255['SN号'].tolist()
+    SNnums_U7255=SNdata_U7255['SN号'].tolist()
+    SNnums= SNnums_L7255 + SNnums_C7255 + SNnums_6040 + SNnums_4840 + SNnums_6060 + SNnums_U7255
+    
+    now_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
+    now_time=datetime.datetime.strptime(now_time,'%Y-%m-%d %H:%M:%S')
+    start_time=now_time-datetime.timedelta(days=30)
+    end_time=str(now_time)
+    start_time=str(start_time)
+
+    #log信息配置
+    mylog=log.Mylog('log.txt','error')
+    mylog.logcfg()
+
+    for sn in SNnums:
+        try:
+            if 'PK500' in sn:
+                celltype=1 #6040三元电芯
+            elif 'PK502' in sn:
+                celltype=2 #4840三元电芯
+            elif 'K504B' in sn:
+                celltype=99    #60ah林磷酸铁锂电芯
+            elif 'MGMLXN750' in sn:
+                celltype=3 #力信50ah三元电芯
+            elif 'MGMCLN750' or 'UD' in sn: 
+                celltype=4 #CATL 50ah三元电芯
+            else:
+                print('SN:{},未找到对应电池类型!!!'.format(sn))
+                continue
+                # sys.exit()
+            
+            # sn='MGMCLN750N215H001'
+            # celltype=2
+            start_time='2021-08-02 09:12:26'
+            end_time='2021-09-03 19:12:26'
+
+            dbManager = DBManager.DBManager()
+            df_data = dbManager.get_data(sn=sn, start_time=start_time, end_time=end_time, data_groups=['bms'])
+            df_bms = df_data['bms']
+            # df_bms.to_csv(r'D:\Platform\platform_python\data_analyze_platform\USER\01qixiang\99Result\\''BMS_'+sn+'.csv',encoding='GB18030')
+            
+            BatInterShort=CBMSBatInterShort.BatInterShort(sn,celltype,df_bms,host, port, db, user, password, tablename)
+            df_res=BatInterShort.intershort()
+            df_res.to_csv(r'D:\Platform\platform_python\data_analyze_platform\USER\01qixiang\99Result\\'+'CBMS_Short_'+sn+'_1.csv',encoding='GB18030')
+        
+        except Exception as e:
+            print(repr(e))
+            mylog.logopt(sn,e)
+            pass

+ 0 - 160
LIB/MIDDLE/LeakCurrent/LFPLeakCurrent20210812.py

@@ -1,160 +0,0 @@
-# 获取数据
-from LIB.BACKEND import DBManager
-
-import os
-import pandas as pd
-import numpy as np
-import bisect
-import datetime
-# import matplotlib.pyplot as plt
-
-#参数输入
-Capacity = 53.6
-PackFullChrgVolt=69.99
-CellFullChrgVolt=3.37
-CellVoltNums=20
-CellTempNums=4
-FullChrgSoc=98
-CellVoltPort=[3.357,3.358,3.359,3.36,3.361]
-PeakSoc=57
-# #40Ah-OCV
-# LookTab_SOC = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100]
-# LookTab_OCV = [3.3159, 3.4502, 3.4904, 3.5277, 3.5590, 3.5888, 3.6146, 3.6312, 3.6467, 3.6642, 3.6865, 3.7171, 3.7617,
-#                3.8031, 3.8440, 3.8888, 3.9376, 3.9891, 4.0451, 4.1068, 4.1830]
-#55Ah-OCV
-LookTab_SOC = [0,  10,  20,  30,  40,  50,  60,  70,  80,  90,  100]
-LookTab_OCV = [3.1820, 3.2250, 3.2730, 3.2840, 3.2860, 3.2920, 3.3210, 3.3260, 3.3270, 3.3270, 3.3640]
-
-# 获取数据时间段
-def cal_LFPLeakCurrent(sn, end_time, start_time):
-    end_time = end_time
-    strat_time = start_time
-
-    sn = sn
-    st = strat_time
-    et = end_time
-
-    dbManager = DBManager.DBManager()
-    df_data = dbManager.get_data(sn=sn, start_time=st, end_time=et, data_groups=['bms'])
-    df_bms = df_data['bms']
-
-    #寻找电压最大值
-    packcrnt=df_bms['总电流[A]']
-    SOC=df_bms['SOC[%]']
-    bmsstat=df_bms['充电状态']
-    time= pd.to_datetime(df_bms['时间戳'], format='%Y-%m-%d %H:%M:%S')
-
-    #第一步:筛选充电数据
-    ChgStart=[]
-    ChgEnd=[]
-    for i in range(3, len(time) - 3):
-        if i==3 and bmsstat[i]==2 and bmsstat[i+1]==2 and bmsstat[i+2]==2:
-            ChgStart.append(i)
-        elif bmsstat[i-2]!=2 and bmsstat[i-1]!=2 and bmsstat[i]==2:
-            ChgStart.append(i)
-        elif bmsstat[i-1]==2 and bmsstat[i]!=2 and bmsstat[i+1]!=2:
-            ChgEnd.append(i)
-        elif i == (len(time) - 4) and bmsstat[len(bmsstat)-1] == 2 and bmsstat[len(bmsstat)-2] == 2:
-            ChgEnd.append(len(time)-1)
-
-    #第二步:筛选充电起始Soc<45%,且单体最小电压>3.37V的数据
-    ChgStartValid=[]
-    ChgEndValid=[]
-    if ChgStart:
-        for i in range(len(ChgEnd)):
-            #寻找最小电压值
-            cellvolt = []
-            for j in range(1, CellVoltNums+1):
-                s = str(j)
-                volt = df_bms['单体电压' + s]/1000
-                cellvolt.append(max(volt[ChgStart[i]:ChgEnd[i]]))
-            if min(cellvolt)>CellFullChrgVolt and SOC[ChgStart[i]]<40 and (ChgEnd[i]-ChgStart[i])>10:
-                if ((time[ChgEnd[i]]-time[ChgStart[i]]).total_seconds())/(ChgEnd[i]-ChgStart[i])<30:
-                    ChgStartValid.append(ChgStart[i])
-                    ChgEndValid.append(ChgEnd[i])
-
-    #第三步:计算充电每个单体到达3.368V的Ah差
-    #定义寻找电压3.368V的数据点
-    def data_search(data1,data2,data3,data4):
-        Soc=0
-        for m in range(1,len(data1)):
-            t=(data2[m]-data2[m-1]).total_seconds()
-            Soc=Soc-data3[m]*t/(3600*Capacity)
-            if data1[m]>data4:
-                DetaT=(data2[m]-data2[0]).total_seconds()
-                return Soc,m
-                break
-    
-    if ChgStartValid:
-        df_DetaTime=pd.DataFrame()
-        df_DetaTime1=pd.DataFrame()
-        df_detatime=pd.DataFrame()
-        for i in range(len(ChgStartValid)):
-            DetaSoc1=[]
-            DetaSoc2 = []
-            DetaSoc=[]
-            a=list(range(5))
-            b=list(range(5))
-            #计算1-10号电芯到达特定电压值得时间和SOC
-            for j in range(1, CellVoltNums-9):
-                s = str(j)
-                cellvolt = df_bms['单体电压' + s]/1000
-                cellvolt=list(cellvolt[ChgStartValid[i]:ChgEndValid[i]])
-                Time=list(time[ChgStartValid[i]:ChgEndValid[i]])
-                Packcrnt=list(packcrnt[ChgStartValid[i]:ChgEndValid[i]])
-                for k in range(len(CellVoltPort)):
-                    a[k],b[k]=data_search(cellvolt,Time,Packcrnt,CellVoltPort[k])
-                DetaSoc1.append(np.mean(a))  #计算到达3.368V的时长
-                # DetaT.append((Time[b]-Time[0]).total_seconds())
-
-            #计算1-10号电芯到达特定电压值的平均Soc
-            Socmean1=(sum(DetaSoc1)-max(DetaSoc1)-min(DetaSoc1))/(len(DetaSoc1)-2)
-            # Tmean=np.mean(DetaT)
-
-            ##计算11-20号电芯到达特定电压值得时间和SOC
-            for j in range(11, CellVoltNums+1):
-                s = str(j)
-                cellvolt = df_bms['单体电压' + s]/1000
-                cellvolt=list(cellvolt[ChgStartValid[i]:ChgEndValid[i]])
-                Time=list(time[ChgStartValid[i]:ChgEndValid[i]])
-                Packcrnt=list(packcrnt[ChgStartValid[i]:ChgEndValid[i]])
-                for k in range(len(CellVoltPort)):
-                    a[k],b[k]=data_search(cellvolt,Time,Packcrnt,CellVoltPort[k])
-                DetaSoc2.append(np.mean(a))  #计算到达3.368V的时长
-
-            #计算11-20号电芯到达特定电压值的平均Soc
-            Socmean2=(sum(DetaSoc2)-max(DetaSoc2)-min(DetaSoc2))/(len(DetaSoc2)-2)
-
-            #计算每个电芯的Soc差
-
-            DetaSoc3=DetaSoc1+DetaSoc2
-            for j in range(len(DetaSoc3)):
-                if j<10:
-                    Socmean=Socmean1
-                else:
-                    Socmean=Socmean2
-                DetaSoc.append(DetaSoc3[j]-Socmean)
-                # DetaSoc.append((DetaT[j]-Tmean)*9.5/(Capacity*3600))
-            df_DetaTime[time[ChgStartValid[i]]]=DetaSoc
-        #漏电流计算
-        column=[]
-        time1=[]
-        sn1=[]
-
-        for index, row in df_DetaTime.iteritems():
-            column.append(index) #提取列名称
-
-        for  i in range(1,len(column)):#计算漏电流值
-            df_DetaTime1[column[i]] = df_DetaTime.apply(lambda x: (x[column[i-1]] -  x[column[i]])*1000*Capacity*3600/((column[i]-column[i-1]).total_seconds()), axis=1)
-            time1.append(column[i])
-            sn1.append(sn)
-        df_detatime['time']=time1
-        df_detatime['sn']=sn1
-
-        for i in range(CellVoltNums):
-            cell=[]
-            for j in range(1,len(column)):
-                cell.append(df_DetaTime1[column[j]][i])
-            df_detatime['cell'+str(i+1)]=cell
-        return df_detatime
-    return pd.DataFrame()

+ 0 - 23
LIB/MIDDLE/LeakCurrent/LeakCurrent表头及数据类型.xlsx

@@ -1,23 +0,0 @@
-ąí͡	ĂűłĆ	ĘýžÝŔŕĐÍ
-time	time	timestamps
-SN	sn	str
-cell1	cell1	float64
-cell2	cell2	float64
-cell3	cell3	float64
-cell4	cell4	float64
-cell5	cell5	float64
-cell6	cell6	float64
-cell7	cell7	float64
-cell8	cell8	float64
-cell9	cell9	float64
-cell10	cell10	float64
-cell11	cell11	float64
-cell12	cell12	float64
-cell13	cell13	float64
-cell14	cell14	float64
-cell15	cell15	float64
-cell16	cell16	float64
-cell17	cell17	float64
-cell18	cell18	float64
-cell19	cell19	float64
-cell20	cell20	float64

+ 0 - 27
LIB/MIDDLE/LeakCurrent/main.py

@@ -1,27 +0,0 @@
-#coding=utf-8
-import os
-import datetime
-import pandas as pd
-from LIB.BACKEND import DBManager, Log
-from LIB.MIDDLE import SignalMonitor
-from sqlalchemy import create_engine
-from sqlalchemy.orm import sessionmaker
-import time, datetime
-import traceback
-import LFPLeakCurrent20210812 as LFPLeakCurrent
-
-from urllib import parse
-
-dbManager = DBManager.DBManager()
-if __name__ == "__main__":
-    SNdata_6060 = pd.read_excel('骑享资产梳理-20210621.xlsx', sheet_name='6060')
-    SNnums_6060=SNdata_6060['SN号']
-    now_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
-    now_time=datetime.datetime.strptime(now_time,'%Y-%m-%d %H:%M:%S')
-    start_time=now_time-datetime.timedelta(days=31)
-    end_time=str(now_time)
-    start_time=str(start_time)
-
-    for sn in SNnums_6060.tolist():
-        res = LFPLeakCurrent.cal_LFPLeakCurrent(sn, end_time, start_time)
-        res.to_csv('BMS_LeakCurrent_'+sn+'.csv',encoding='GB18030')