ソースを参照

Merge remote-tracking branch 'origin/dev' into pro

lmstack 3 年 前
コミット
c97011dc7f

+ 30 - 14
LIB/MIDDLE/CellStateEstimation/SOH/V1_0_0/BatParam.py

@@ -29,6 +29,7 @@ class BatParam:
             self.CellTempNums=4
             self.FullChrgSoc=98
             self.PeakSoc=57
+            self.PackCrntDec=1
             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]
             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]
         
@@ -40,9 +41,34 @@ class BatParam:
             self.CellTempNums=4
             self.FullChrgSoc=98
             self.PeakSoc=57
+            self.PackCrntDec=1
             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]
             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]
-       
+        
+        elif celltype==3:   #力信50ah三元电芯
+            self.Capacity = 51
+            self.PackFullChrgVolt=80
+            self.CellFullChrgVolt=4.2
+            self.CellVoltNums=20
+            self.CellTempNums=4
+            self.FullChrgSoc=98
+            self.PeakSoc=57
+            self.PackCrntDec=1
+            self.LookTab_SOC = [0,	    5,	    10,	    15,	    20,	    25,	    30,	    35,	    40,	    45,	    50,	    55,	    60,	    65,	    70,	    75,	    80,	    85,	    90,	    95,	    100]
+            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]
+        
+        elif celltype==4:   #CATL 50ah三元电芯
+            self.Capacity = 50
+            self.PackFullChrgVolt=80
+            self.CellFullChrgVolt=4.2
+            self.CellVoltNums=20
+            self.CellTempNums=2
+            self.FullChrgSoc=98
+            self.PeakSoc=57
+            self.PackCrntDec=-1
+            self.LookTab_SOC = [0,	    5,	    10,	    15,	    20,	    25,	    30,	    35,	    40,	    45,	    50,	    55,	    60,	    65,	    70,	    75,	    80,	    85,	    90,	    95,	    100]
+            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]
+        
         elif celltype==99:   #60ah磷酸铁锂电芯
             self.Capacity = 54
             self.PackFullChrgVolt=69.99
@@ -54,22 +80,12 @@ class BatParam:
             self.CellVoltNums=20
             self.CellTempNums=4
             self.FullChrgSoc=98
-            self.PeakSoc=57
+            self.PeakSoc=60.5
+            self.PackCrntDec=1
             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]
         
-        elif celltype==3:
-            self.Capacity = 51
-            self.PackFullChrgVolt=80
-            self.CellFullChrgVolt=4.2
-            self.CellVoltNums=20
-            self.CellTempNums=4
-            self.FullChrgSoc=98
-            self.PeakSoc=57
-            self.LookTab_SOC = [0,	    5,	    10,	    15,	    20,	    25,	    30,	    35,	    40,	    45,	    50,	    55,	    60,	    65,	    70,	    75,	    80,	    85,	    90,	    95,	    100]
-            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]
-        
         else:
             print('未找到对应电池编号!!!')
-            sys.exit()
+            # sys.exit()
 

+ 155 - 129
LIB/MIDDLE/CellStateEstimation/SOH/V1_0_0/CBMSBatSoh.py

@@ -5,6 +5,8 @@ import bisect
 import matplotlib.pyplot as plt
 from LIB.MIDDLE.CellStateEstimation.SOH.V1_0_0 import BatParam
 from LIB.MIDDLE.CellStateEstimation.SOH.V1_0_0 import DBDownload
+import BatParam
+import DBDownload
 
 class BatSoh:
     def __init__(self,sn,celltype,df_bms,df_accum, host, port, db, user, password, tablename):  #参数初始化
@@ -13,7 +15,7 @@ class BatSoh:
         self.celltype=celltype
         self.param=BatParam.BatParam(celltype)
         self.df_bms=df_bms
-        self.packcrnt=df_bms['总电流[A]']
+        self.packcrnt=df_bms['总电流[A]']*self.param.PackCrntDec
         self.packvolt=df_bms['总电压[V]']
         self.bms_soc=df_bms['SOC[%]']
         self.bms_soh=df_bms['SOH[%]']
@@ -31,7 +33,7 @@ class BatSoh:
         self.tablename=tablename
 
     def batsoh(self):
-        if self.celltype==1 or self.celltype==2:
+        if self.celltype==1 or self.celltype==2 or self.celltype==3 or self.celltype==4:
             df_res=self._ncmsoh_twopoint()
             return df_res
             
@@ -39,8 +41,10 @@ class BatSoh:
             df_res=self._lfpsoh()
             return df_res
 
-    def getdata(self):  #获取已有soh结果
+        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)
@@ -115,7 +119,108 @@ class BatSoh:
         for j in range(1, self.param.CellVoltNums+1): 
             s = str(j)
             cellvolt.append(self.df_bms.loc[num,'单体电压' + s]/1000)
-        return(cellvolt)
+        return cellvolt
+    
+    def _dvdq_soh(self, chrg_st, chrg_end,cellvolt):    #dvdq方法计算soh
+        Ah = 0  #参数赋初始值
+        Volt = cellvolt[chrg_st]
+        DV_Volt=[]
+        DQ_Ah = []
+        DVDQ = []
+        time2 = []
+        soc2 = []
+        Ah_tatal=[0]
+        xvolt=[]
+        #计算DV和DQ值
+        for j in range(chrg_st,chrg_end):
+            Step=(self.bmstime[j+1]-self.bmstime[j]).total_seconds()
+            Ah=Ah-self.packcrnt[j]*Step/3600
+            if (cellvolt[j]-Volt)>0.0009 and Ah>0:
+                Ah_tatal.append(Ah_tatal[-1]+Ah)
+                DQ_Ah.append(Ah)
+                DV_Volt.append(cellvolt[j]-Volt)
+                DVDQ.append((DV_Volt[-1])/DQ_Ah[-1])
+                xvolt.append(cellvolt[j])
+                Volt=cellvolt[j]
+                Ah = 0
+                time2.append(self.bmstime[j])
+                soc2.append(self.bms_soc[j])
+
+        #切片,去除前后10min的数据
+        df_Data1 = pd.DataFrame({'time': time2,
+                                'SOC': soc2,
+                                'DVDQ': DVDQ,
+                                'Ah_tatal': Ah_tatal[:-1],
+                                'DQ_Ah':DQ_Ah,
+                                'DV_Volt':DV_Volt,
+                                'XVOLT':xvolt})
+        start_time=df_Data1.loc[0,'time']
+        start_time=start_time+datetime.timedelta(seconds=900)
+        end_time=df_Data1.loc[len(time2)-1,'time']
+        end_time=end_time-datetime.timedelta(seconds=1200)
+        if soc2[0]<40:
+            df_Data1=df_Data1[(df_Data1['SOC']>43) & (df_Data1['time']<end_time)]
+        else:
+            df_Data1=df_Data1[(df_Data1['time']>start_time) & (df_Data1['time']<end_time)]
+
+        # ax1 = plt.subplot(3, 1, 1)
+        # plt.plot(df_Data1['XVOLT'],df_Data1['DVDQ'],'r*-')
+        # plt.xlabel('Volt/V')
+        # plt.ylabel('DV/DQ')
+        # 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()
+
+        #寻找峰值并计算Soh
+        if len(df_Data1)>1:
+            PeakIndex=df_Data1['DVDQ'].idxmax()
+            #筛选峰值点附近±0.5%SOC内的数据
+            df_Data2=df_Data1[(df_Data1['SOC']>(df_Data1['SOC'][PeakIndex]-0.5)) & (df_Data1['SOC']<(df_Data1['SOC'][PeakIndex]+0.5))]
+            if len(df_Data2)>2:
+                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:
+                    cellsoh_init=(Ah_tatal[-1]-Ah_tatal1[PeakIndex]) * 100 / ((self.param.FullChrgSoc - self.param.PeakSoc) * 0.01 * self.param.Capacity)
+                    if cellsoh_init<95:
+                        cellsoh_init=cellsoh_init*0.3926+58.14
+                        return cellsoh_init
+                    else:
+                        return cellsoh_init
+                else:
+                    return 0
+            else:
+                df_Data1=df_Data1.drop([PeakIndex])
+                PeakIndex = df_Data1['DVDQ'].idxmax()
+                df_Data2 = df_Data1[(df_Data1['SOC'] > (df_Data1['SOC'][PeakIndex] - 0.5)) & (df_Data1['SOC'] < (df_Data1['SOC'][PeakIndex] + 0.5))]
+                if len(df_Data2) > 2:
+                    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:
+                        cellsoh_init=(Ah_tatal[-1]-Ah_tatal1[PeakIndex]) * 100 / ((self.param.FullChrgSoc - self.param.PeakSoc) * 0.01 * self.param.Capacity)
+                        if cellsoh_init<95:
+                            cellsoh_init=cellsoh_init*0.3926+58.14
+                            return cellsoh_init
+                        else:
+                            return cellsoh_init
+                    else:
+                        return 0
+                else:
+                    return 0
+        else:
+            return 0
                 
     def _ncmsoh_chrg(self):     #NCM充电数据soh计算 
         self._chrgdata()
@@ -188,7 +293,7 @@ class BatSoh:
         for i in range(3,len(self.df_bms)-3):
 
             if abs(self.packcrnt[i]) < 0.3:     #电流为0
-                delttime=(self.bmstime[i+1]-self.bmstime[1]).total_seconds()
+                delttime=(self.bmstime[i]-self.bmstime[i-1]).total_seconds()
                 standingtime=standingtime+delttime
                 self._celltemp_weight(i)     #获取不同温度对应的静置时间
 
@@ -297,17 +402,12 @@ class BatSoh:
                     elif abs(ah_accum_tatol-ah_packcrnt) < self.param.Capacity/10:
                         soh_weight1=soh_weight1*0.8
                     else:
-                        soh_weight1=0.5
+                        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
                     else:
                         soh_weight1=0
-                
-                if ah_packcrnt_chg + ah_packcrnt_dis > self.param.Capacity:    #总Ah数对结果的影响
-                    soh_weight1=soh_weight1*0.6
-                else:
-                    soh_weight1=soh_weight1
 
                 cellsoh=[]
                 for j in range(self.param.CellVoltNums):    #计算每个电芯的SOH值
@@ -322,16 +422,21 @@ class BatSoh:
                         if len(df_res)<1:
                             if not self.df_soh.empty:
                                 cellsoh_last=eval(self.df_soh.loc[len(self.df_soh)-1,'cellsoh'])
-                                cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last[j]*(1-soh_weight)
+                                if soh_weight>1/abs(cellsoh_init-cellsoh_last):
+                                    soh_weight=1/abs(cellsoh_init-cellsoh_last)
+                                    cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last[j]*(1-soh_weight)
+                                else:
+                                    cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last[j]*(1-soh_weight)
                             else:
                                 cellsoh_cal=cellsoh_init*soh_weight+100*(1-soh_weight)
                         else:
                             cellsoh_last=eval(df_res.loc[len(df_res)-1,'cellsoh'])
-                            if abs(cellsoh_init-cellsoh_last[j])<10:
-                                cellsoh_cal=cellsoh_init*soh_weight*0.5 + cellsoh_last[j]*(1-soh_weight*0.5)
+                            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:
-                                soh_weight=soh_weight*0.2
-                                cellsoh_cal=cellsoh_init*soh_weight*0.5 + cellsoh_last[j]*(1-soh_weight*0.5)
+                                cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last[j]*(1-soh_weight)
+                        cellsoh_cal=eval(format(cellsoh_cal,'.1f'))
                         cellsoh.append(cellsoh_cal)
                     else:
                         cellsoh=[]
@@ -364,7 +469,7 @@ class BatSoh:
 
             #获取两点法法所需数据-开始
             if abs(self.packcrnt[i]) < 0.2:     #判断非平台区静置状态
-                delttime=(self.bmstime[i+1]-self.bmstime[i]).total_seconds()
+                delttime=(self.bmstime[i]-self.bmstime[i-1]).total_seconds()
                 standingtime=standingtime+delttime
                 self._celltemp_weight(i)     #获取不同温度对应的静置时间
 
@@ -529,7 +634,7 @@ class BatSoh:
                     if delt_days<=1: #两次时间间隔对计算结果的影响
                         soh_weight=1
                     elif delt_days<=2:
-                        soh_weight=0.9
+                        soh_weight=0.7
                     elif delt_days<=3:
                         soh_weight=0.4
                     else:
@@ -547,10 +652,6 @@ class BatSoh:
                             soh_weight=soh_weight*0.5
                         else:
                             soh_weight=0
-                    if ah_accum_dis+ah_accum_chg>self.param.Capacity:
-                        soh_weight=soh_weight*0.6
-                    else:
-                        soh_weight=soh_weight
 
                     delt_ocv_soc=ocv_soc2-ocv_soc1
                     delt_ocv_soc_weight=self._deltsoc_weight(abs(delt_ocv_soc))
@@ -560,17 +661,23 @@ class BatSoh:
                     if cellsoh_init>65 and cellsoh_init<115:    #判断soh值的有效区间
                         if len(df_res)<1:
                             if not self.df_soh.empty:
-                                cellsoh_cal=cellsoh_init*soh_weight + list(self.df_soh['soh'])[-1]*(1-soh_weight)
+                                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)
+                                    cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last*(1-soh_weight)
+                                else:
+                                    cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last*(1-soh_weight)
                             else:
                                 cellsoh_cal=cellsoh_init*soh_weight+100*(1-soh_weight)
                         else:
                             cellsoh_last=df_res.loc[len(df_res)-1,'soh']
-                            if abs(cellsoh_init-cellsoh_last)<10:
+                            if soh_weight>1/abs(cellsoh_init-cellsoh_last):
+                                soh_weight=1/abs(cellsoh_init-cellsoh_last)
                                 cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last*(1-soh_weight)
                             else:
-                                soh_weight=soh_weight*0.1
                                 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
                     else:
@@ -581,114 +688,33 @@ class BatSoh:
             if chrg_end:
                 for i in range(len(chrg_end)):
                     cellvolt_max = self.df_bms['单体电压' + str(cellmaxvolt_number2[i]+1)] / 1000     #获取最大电压
-                    cellvolt=self._np_move_avg(cellvolt_max, 3, mode="same")     #对电压进行滑动平均滤波
-                    
-                    Ah = 0  #参数赋初始值
-                    Volt = cellvolt[chrg_start[i]]
-                    DV_Volt=[]
-                    DQ_Ah = []
-                    DVDQ = []
-                    time2 = []
-                    soc2 = []
-                    Ah_tatal=[0]
-                    xvolt=[]
-                    #计算DV和DQ值
-                    for j in range(chrg_start[i],chrg_end[i]):
-                        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:
-                            Ah_tatal.append(Ah_tatal[-1]+Ah)
-                            DQ_Ah.append(Ah)
-                            DV_Volt.append(cellvolt[j]-Volt)
-                            DVDQ.append((DV_Volt[-1])/DQ_Ah[-1])
-                            xvolt.append(cellvolt[j])
-                            Volt=cellvolt[j]
-                            Ah = 0
-                            time2.append(self.bmstime[j])
-                            soc2.append(self.bms_soc[j])
-
-                    #切片,去除前后10min的数据
-                    df_Data1 = pd.DataFrame({'time': time2,
-                                            'SOC': soc2,
-                                            'DVDQ': DVDQ,
-                                            'Ah_tatal': Ah_tatal[:-1],
-                                            'DQ_Ah':DQ_Ah,
-                                            'DV_Volt':DV_Volt,
-                                            'XVOLT':xvolt})
-                    start_time=df_Data1.loc[0,'time']
-                    start_time=start_time+datetime.timedelta(seconds=900)
-                    end_time=df_Data1.loc[len(time2)-1,'time']
-                    end_time=end_time-datetime.timedelta(seconds=1500)
-                    if soc2[0]<40:
-                        df_Data1=df_Data1[(df_Data1['SOC']>43) & (df_Data1['time']<end_time)]
-                    else:
-                        df_Data1=df_Data1[(df_Data1['time']>start_time) & (df_Data1['time']<end_time)]
-            
-                    # ax1 = plt.subplot(3, 1, 1)
-                    # plt.plot(df_Data1['XVOLT'],df_Data1['DVDQ'],'r*-')
-                    # ax1 = plt.subplot(3, 1, 2)
-                    # plt.plot(df_Data1['SOC'],df_Data1['XVOLT'],'y*-')
-                    # ax1 = plt.subplot(3, 1, 3)
-                    # plt.plot(df_Data1['SOC'], df_Data1['DVDQ'], 'r*-')
-                    # plt.show()
-
-                    #寻找峰值并计算Soh和置信度
-                    if len(df_Data1)>1:
-                        PeakIndex=df_Data1['DVDQ'].idxmax()
-                        #筛选峰值点附近±0.5%SOC内的数据
-                        df_Data2=df_Data1[(df_Data1['SOC']>(df_Data1['SOC'][PeakIndex]-0.5)) & (df_Data1['SOC']<(df_Data1['SOC'][PeakIndex]+0.5))]
-                        if len(df_Data2)>2:
-                            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:
-                                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
+                    cellvolt=self._np_move_avg(cellvolt_max, 3, mode="same")     #对电压进行滑动平均滤
+
+                    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 len(df_res)<1:
+                            if not self.df_soh.empty:
+                                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)
+                                    cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last*(1-soh_weight)
                                 else:
-                                    pass
+                                    cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last*(1-soh_weight)
                             else:
-                                continue
+                                cellsoh_cal=cellsoh_init*soh_weight+100*(1-soh_weight)
                         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:
-                                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:
-                                    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
-                                    else:
-                                        pass
-                                else:
-                                    continue
+                            cellsoh_last=df_res.loc[len(df_res)-1,'soh']
+                            if soh_weight>1/abs(cellsoh_init-cellsoh_last):
+                                soh_weight=1/abs(cellsoh_init-cellsoh_last)
+                                cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last*(1-soh_weight)
                             else:
-                                continue
+                                cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last*(1-soh_weight)
                         
-                        soh_weight=tempweightlist2[i]*0.5
-                        if cellsoh_init>65 and cellsoh_init<115:    #判断soh值的有效区间
-                            if len(df_res)<1:
-                                if not self.df_soh.empty and self.df_soh.shape[1]>10:
-                                    cellsoh_cal=cellsoh_init*soh_weight + list(self.df_soh['soh'])[-1]*(1-soh_weight)
-                                else:
-                                    cellsoh_cal=cellsoh_init*soh_weight+100*(1-soh_weight)
-                            else:
-                                cellsoh_last=df_res.loc[len(df_res)-1,'soh']
-                                if abs(cellsoh_init-cellsoh_last)<10:
-                                    cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last*(1-soh_weight)
-                                else:
-                                    soh_weight=soh_weight*0.2
-                                    cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last*(1-soh_weight)
-                            
-                            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:
-                            continue
+                        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:
                         continue
             else:

BIN
LIB/MIDDLE/CellStateEstimation/SOH/V1_0_0/骑享资产梳理-20210621.xlsx


+ 0 - 2
LIB/MIDDLE/CellStateEstimation/SOH/main.py

@@ -10,8 +10,6 @@ from LIB.BACKEND import DBManager, Log
 from sqlalchemy import create_engine
 from sqlalchemy.orm import sessionmaker
 import time, datetime
-from LIB.MIDDLE.soh import NCMSoh_20210716 as NCMSoh
-from LIB.MIDDLE.soh import LFPSoh_20210711 as LFPSoh
 from urllib import parse
 
 host='rm-bp10j10qy42bzy0q77o.mysql.rds.aliyuncs.com'

+ 30 - 14
LIB/MIDDLE/CellStateEstimation/Uniform/V1_0_0/BatParam.py

@@ -29,6 +29,7 @@ class BatParam:
             self.CellTempNums=4
             self.FullChrgSoc=98
             self.PeakSoc=57
+            self.PackCrntDec=1
             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]
             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]
         
@@ -40,9 +41,34 @@ class BatParam:
             self.CellTempNums=4
             self.FullChrgSoc=98
             self.PeakSoc=57
+            self.PackCrntDec=1
             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]
             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]
-       
+        
+        elif celltype==3:   #力信50ah三元电芯
+            self.Capacity = 51
+            self.PackFullChrgVolt=80
+            self.CellFullChrgVolt=4.2
+            self.CellVoltNums=20
+            self.CellTempNums=4
+            self.FullChrgSoc=98
+            self.PeakSoc=57
+            self.PackCrntDec=1
+            self.LookTab_SOC = [0,	    5,	    10,	    15,	    20,	    25,	    30,	    35,	    40,	    45,	    50,	    55,	    60,	    65,	    70,	    75,	    80,	    85,	    90,	    95,	    100]
+            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]
+        
+        elif celltype==4:   #CATL 50ah三元电芯
+            self.Capacity = 50
+            self.PackFullChrgVolt=80
+            self.CellFullChrgVolt=4.2
+            self.CellVoltNums=20
+            self.CellTempNums=2
+            self.FullChrgSoc=98
+            self.PeakSoc=57
+            self.PackCrntDec=-1
+            self.LookTab_SOC = [0,	    5,	    10,	    15,	    20,	    25,	    30,	    35,	    40,	    45,	    50,	    55,	    60,	    65,	    70,	    75,	    80,	    85,	    90,	    95,	    100]
+            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]
+        
         elif celltype==99:   #60ah磷酸铁锂电芯
             self.Capacity = 54
             self.PackFullChrgVolt=69.99
@@ -54,22 +80,12 @@ class BatParam:
             self.CellVoltNums=20
             self.CellTempNums=4
             self.FullChrgSoc=98
-            self.PeakSoc=57
+            self.PeakSoc=60.5
+            self.PackCrntDec=1
             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]
         
-        elif celltype==3:
-            self.Capacity = 51
-            self.PackFullChrgVolt=80
-            self.CellFullChrgVolt=4.2
-            self.CellVoltNums=20
-            self.CellTempNums=4
-            self.FullChrgSoc=98
-            self.PeakSoc=57
-            self.LookTab_SOC = [0,	    5,	    10,	    15,	    20,	    25,	    30,	    35,	    40,	    45,	    50,	    55,	    60,	    65,	    70,	    75,	    80,	    85,	    90,	    95,	    100]
-            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]
-        
         else:
             print('未找到对应电池编号!!!')
-            sys.exit()
+            # sys.exit()
 

+ 33 - 29
LIB/MIDDLE/CellStateEstimation/Uniform/V1_0_0/CBMSBatUniform.py

@@ -3,6 +3,7 @@ import numpy as np
 import datetime
 import bisect
 import matplotlib.pyplot as plt
+import BatParam
 from LIB.MIDDLE.CellStateEstimation.SOH.V1_0_0 import BatParam
 
 class BatUniform:
@@ -12,19 +13,22 @@ class BatUniform:
         self.celltype=celltype
         self.param=BatParam.BatParam(celltype)
         self.df_bms=df_bms
-        self.packcrnt=df_bms['总电流[A]']
+        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')
 
     def batuniform(self):
-        if self.celltype==1 or self.celltype==2:
+        if self.celltype==1 or self.celltype==2 or self.celltype==3 or self.celltype==4:
             df_res=self._ncm_uniform()
             return df_res
             
         elif self.celltype==99:
             df_res=self._lfp_uniform()
             return df_res
+        
+        else:
+            return pd.DataFrame()
     
     def _np_move_avg(self,a, n, mode="same"): #定义滑动滤波函数
         return (np.convolve(a, np.ones((n,)) / n, mode=mode))
@@ -118,22 +122,22 @@ class BatUniform:
         else:
             df_Data1=df_Data1[(df_Data1['time']>start_time) & (df_Data1['time']<end_time)]
 
-        ax1 = plt.subplot(3, 1, 1)
-        plt.plot(df_Data1['XVOLT'],df_Data1['DVDQ'],'r*-')
-        plt.xlabel('Volt/V')
-        plt.ylabel('DV/DQ')
-        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()
+        # ax1 = plt.subplot(3, 1, 1)
+        # plt.plot(df_Data1['XVOLT'],df_Data1['DVDQ'],'r*-')
+        # plt.xlabel('Volt/V')
+        # plt.ylabel('DV/DQ')
+        # 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()
@@ -175,8 +179,8 @@ class BatUniform:
                         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=format(cellsoc_diff,'.1f')
-                        cellvolt_diff=format(cellvolt_diff,'.0f')
+                        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                    
@@ -189,8 +193,8 @@ class BatUniform:
                         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=format(cellsoc_diff,'.1f')
-                        cellvolt_diff=format(cellvolt_diff,'.0f')
+                        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
@@ -203,8 +207,8 @@ class BatUniform:
                         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=format(cellsoc_diff,'.1f')
-                        cellvolt_diff=format(cellvolt_diff,'.0f')
+                        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:
@@ -248,8 +252,8 @@ class BatUniform:
                         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=format(cellsoc_diff,'.1f')
-                        cellvolt_diff=format(cellvolt_diff,'.0f')
+                        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:
                         standingtime=0
@@ -259,8 +263,8 @@ class BatUniform:
                         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=format(cellsoc_diff,'.1f')
-                        cellvolt_diff=format(cellvolt_diff,'.0f')
+                        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
@@ -346,7 +350,7 @@ class BatUniform:
                     peaksoc_maxnum=peaksoc_list.index(peaksoc_min)+1
                     peaksoc_minnum=peaksoc_list.index(peaksoc_max)+1
                     cellsoc_diff=peaksoc_max-peaksoc_min
-                    cellsoc_diff=format(cellsoc_diff,'.1f')
+                    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

+ 0 - 2
LIB/MIDDLE/CellStateEstimation/Uniform/main.py

@@ -11,8 +11,6 @@ from LIB.BACKEND import DBManager, Log
 from sqlalchemy import create_engine
 from sqlalchemy.orm import sessionmaker
 import time, datetime
-from LIB.MIDDLE.soh import NCMSoh_20210716 as NCMSoh
-from LIB.MIDDLE.soh import LFPSoh_20210711 as LFPSoh
 from urllib import parse
 
 dbManager = DBManager.DBManager()