Browse Source

更新SOH算法

qingfeng 3 years ago
parent
commit
39b969d3f3

+ 6 - 6
LIB/MIDDLE/CellStateEstimation/SOH/V1_0_0/BatParam.py

@@ -15,10 +15,10 @@ class BatParam:
             self.celltype=2 #4840三元电芯
         elif 'PK504' in sn:
             self.celltype=99    #60ah林磷酸铁锂电芯
-        elif 'MGMCLN750' in sn: 
-            self.celltype=3 #CATL 50ah三元电芯
         elif 'MGMLXN750' in sn:
-            self.celltype=4 #力信50ah三元电芯
+            self.celltype=3 #力信50ah三元电芯
+        elif 'MGMCLN750' in sn: 
+            self.celltype=4 #CATL 50ah三元电芯
         else:
             print('未找到对应电池编号!!!')
             sys.exit()
@@ -61,15 +61,15 @@ class BatParam:
             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 self.celltype==3:
-            self.Capacity = 50
+            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.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]
+            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('未找到对应电池编号!!!')

+ 58 - 69
LIB/MIDDLE/CellStateEstimation/SOH/V1_0_0/CBMSBatSoh.py

@@ -7,7 +7,7 @@ import BatParam
 import DBDownload
 
 class BatSoh:
-    def __init__(self,sn,df_bms,df_accum):  #参数初始化
+    def __init__(self,sn,df_bms,df_accum, host, port, db, user, password, tablename):  #参数初始化
 
         self.sn=sn
         self.param=BatParam.BatParam(sn)
@@ -22,6 +22,13 @@ class BatSoh:
         self.df_accum=df_accum
         self.accumtime=pd.to_datetime(df_accum['时间戳'], 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 batsoh(self):
         if self.param.celltype==1 or self.param.celltype==2:
             df_res=self._ncmsoh_twopoint()
@@ -32,22 +39,10 @@ class BatSoh:
             return df_res
 
     def getdata(self):  #获取已有soh结果
-        host='rm-bp10j10qy42bzy0q77o.mysql.rds.aliyuncs.com'
-        port=3306
-        db='qx_cas'
-        user='qx_read'
-        password='Qx@123456'
-
-        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=60)
-        end_time=str(now_time)
-        start_time=str(start_time)
-
-        DBManager=DBDownload.DBDownload(host, port, db, user, password)
+
+        DBManager=DBDownload.DBDownload(self.host, self.port, self.db, self.user, self.password)
         with DBManager as DBManager:
-            df_soh=DBManager.getdata('sn', 'time', 'bms_soh', 'soh', 'soh_err', tablename='soh_result_old',st=start_time,sp=end_time)
-            self.df_soh=df_soh[df_soh['sn']==self.sn]
+            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))
@@ -249,7 +244,7 @@ class BatSoh:
 
         if standingpoint_sp:
             self.getdata()  #获取已计算的soh
-            column_name=['time_st','time_sp','sn','method','soh','cellsoh1','cellsoh2','cellsoh3','cellsoh4','cellsoh5','cellsoh6','cellsoh7','cellsoh8','cellsoh9','cellsoh10','cellsoh11','cellsoh12','cellsoh13','cellsoh14','cellsoh15','cellsoh16','cellsoh17','cellsoh18','cellsoh19','cellsoh20']
+            column_name=['time_st','time_sp','sn','method','soh','cellsoh']
             df_res=pd.DataFrame(columns=column_name)
 
             for i in range(len(standingpoint_sp)):
@@ -313,39 +308,37 @@ class BatSoh:
                 else:
                     soh_weight1=soh_weight1
 
-                cellsoh=[timepoint_bms_st, timepoint_bms_sp, self.sn, 1]
-                for j in range(20):    #计算每个电芯的SOH值
-                    if j<self.param.CellVoltNums:
-                        ocv_soc1=np.interp(cellocv_st[j],self.param.LookTab_OCV,self.param.LookTab_SOC)
-                        ocv_soc2=np.interp(cellocv_sp[j],self.param.LookTab_OCV,self.param.LookTab_SOC)
-                        delt_ocv_soc=ocv_soc2-ocv_soc1
-                        delt_ocv_soc_weight=self._deltsoc_weight(abs(delt_ocv_soc))
-                        soh_weight=soh_weight1*tempweightlist[i]*delt_ocv_soc_weight
-                        cellsoh_init=ah_accum*100/((ocv_soc2-ocv_soc1)*0.01*self.param.Capacity)
-
-                        if cellsoh_init>55 and cellsoh_init<120:    #判断soh值的有效区间
-                            if len(df_res)<1:
-                                if not self.df_soh.empty and self.df_soh.shape[1]>10:
-                                    cellsoh_cal=cellsoh_init*soh_weight + list(self.df_soh['cellsoh'+str(j+1)])[-1]*(1-soh_weight)
-                                else:
-                                    cellsoh_cal=cellsoh_init
+                cellsoh=[]
+                for j in range(self.param.CellVoltNums):    #计算每个电芯的SOH值
+                    ocv_soc1=np.interp(cellocv_st[j],self.param.LookTab_OCV,self.param.LookTab_SOC)
+                    ocv_soc2=np.interp(cellocv_sp[j],self.param.LookTab_OCV,self.param.LookTab_SOC)
+                    delt_ocv_soc=ocv_soc2-ocv_soc1
+                    delt_ocv_soc_weight=self._deltsoc_weight(abs(delt_ocv_soc))
+                    soh_weight=soh_weight1*tempweightlist[i]*delt_ocv_soc_weight
+                    cellsoh_init=ah_accum*100/((ocv_soc2-ocv_soc1)*0.01*self.param.Capacity)
+
+                    if cellsoh_init>55 and cellsoh_init<120:    #判断soh值的有效区间
+                        if len(df_res)<1:
+                            if not self.df_soh.empty:
+                                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)
                             else:
-                                if abs(cellsoh_init-df_res.iloc[-1]['cellsoh'+str(j+1)])<15:
-                                    cellsoh_cal=cellsoh_init*soh_weight*0.5 + df_res.iloc[-1]['cellsoh'+str(j+1)]*(1-soh_weight*0.5)
-                                else:
-                                    soh_weight=soh_weight*0.2
-                                    cellsoh_cal=cellsoh_init*soh_weight*0.5 + df_res.iloc[-1]['cellsoh'+str(j+1)]*(1-soh_weight*0.5)
-                            cellsoh.append(cellsoh_cal)
+                                cellsoh_cal=cellsoh_init*soh_weight+100*(1-soh_weight)
                         else:
-                            cellsoh=[]
-                            break
+                            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)
+                            else:
+                                soh_weight=soh_weight*0.2
+                                cellsoh_cal=cellsoh_init*soh_weight*0.5 + cellsoh_last[j]*(1-soh_weight*0.5)
+                        cellsoh.append(cellsoh_cal)
                     else:
-                        cellsoh.append(0)
-                if len(cellsoh)>4:
-                    soh_value=cellsoh[4:4+self.param.CellVoltNums]
-                    soh=min(soh_value)
-                    cellsoh.insert(4,soh)
-                    df_res.loc[len(df_res)]=cellsoh
+                        cellsoh=[]
+                        break
+                if cellsoh:
+                    soh=min(cellsoh)
+                    soh_list=[timepoint_bms_st, timepoint_bms_sp, self.sn, 1, soh, str(cellsoh)]
+                    df_res.loc[len(df_res)]=soh_list
                 else:
                     continue
             if df_res.empty:
@@ -429,7 +422,9 @@ class BatSoh:
 
             #获取DVDQ算法所需数据——开始
             if i==3 and self.packcrnt[1]<=-1 and self.packcrnt[2]<=-1 and self.packcrnt[3]<=-1:
+                self._celltemp_weight(i)
                 chrg_start.append(i)
+                tempweightlist2.append(self.tempweight)
                 charging=1
             elif self.packcrnt[i-1]>-1 and self.packcrnt[i]<=-1 and self.packcrnt[i+1]<=-1 and self.packcrnt[i+2]<=-1:     #判断充电开始
                 if self.bms_soc[i]<45:
@@ -489,7 +484,7 @@ class BatSoh:
         
         if standingpoint_sp or chrg_end:       #开始计算SOH
             self.getdata()  #获取已计算的soh
-            column_name=['time_st','time_sp','sn','method','soh','cellsoh1','cellsoh2','cellsoh3','cellsoh4','cellsoh5','cellsoh6','cellsoh7','cellsoh8','cellsoh9','cellsoh10','cellsoh11','cellsoh12','cellsoh13','cellsoh14','cellsoh15','cellsoh16','cellsoh17','cellsoh18','cellsoh19','cellsoh20']
+            column_name=['time_st','time_sp','sn','method','soh','cellsoh']
             df_res=pd.DataFrame(columns=column_name)
         
             if standingpoint_sp:    #两点法计算SOH
@@ -556,7 +551,6 @@ class BatSoh:
                     else:
                         soh_weight=soh_weight
 
-                    cellsoh=[timepoint_bms_st, timepoint_bms_sp, self.sn]
                     delt_ocv_soc=ocv_soc2-ocv_soc1
                     delt_ocv_soc_weight=self._deltsoc_weight(abs(delt_ocv_soc))
                     soh_weight=soh_weight*tempweightlist1[i]*delt_ocv_soc_weight*0.5
@@ -564,22 +558,20 @@ class BatSoh:
 
                     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:
+                            if not self.df_soh.empty:
                                 cellsoh_cal=cellsoh_init*soh_weight + list(self.df_soh['soh'])[-1]*(1-soh_weight)
                             else:
-                                cellsoh_cal=cellsoh_init
+                                cellsoh_cal=cellsoh_init*soh_weight+100*(1-soh_weight)
                         else:
-                            if abs(cellsoh_init-df_res.iloc[-1]['soh'])<10:
-                                cellsoh_cal=cellsoh_init*soh_weight + df_res.iloc[-1]['soh']*(1-soh_weight)
+                            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.1
-                                cellsoh_cal=cellsoh_init*soh_weight + df_res.iloc[-1]['soh']*(1-soh_weight)
+                                cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last*(1-soh_weight)
 
-                        cellsoh.append(1)
-                        cellsoh.append(cellsoh_cal)
-                        for j in range(20):    #计算每个电芯的SOH值
-                            cellsoh.append(cellsoh_cal)
-                        df_res.loc[len(df_res)]=cellsoh
+                        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:
                         continue
             else:
@@ -677,26 +669,23 @@ class BatSoh:
                             else:
                                 continue
                         
-                        cellsoh=[self.bmstime[chrg_start[i]], self.bmstime[chrg_end[i]], self.sn]
                         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
+                                    cellsoh_cal=cellsoh_init*soh_weight+100*(1-soh_weight)
                             else:
-                                if abs(cellsoh_init-df_res.iloc[-1]['soh'])<10:
-                                    cellsoh_cal=cellsoh_init*soh_weight + df_res.iloc[-1]['soh']*(1-soh_weight)
+                                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 + df_res.iloc[-1]['soh']*(1-soh_weight)
+                                    cellsoh_cal=cellsoh_init*soh_weight + cellsoh_last*(1-soh_weight)
                             
-                            cellsoh.append(2)
-                            cellsoh.append(cellsoh_cal)
-                            for j in range(20):    #计算每个电芯的SOH值
-                                cellsoh.append(cellsoh_cal)
-                            df_res.loc[len(df_res)]=cellsoh
+                            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:

+ 3 - 2
LIB/MIDDLE/CellStateEstimation/SOH/V1_0_0/DBDownload.py

@@ -33,7 +33,7 @@ class DBDownload:
                 print('数据库连接成功!')
                 self.cursor = self.conn.cursor()
 
-    def getdata(self,*param,tablename,st,sp):
+    def getdata(self,*param,tablename,sn):
         print('数据获取中......')
         param=list(param)
         str=''
@@ -42,7 +42,8 @@ class DBDownload:
                 str=str+param[i]
             else:
                 str=str+','+param[i]
-        self.cursor.execute("select %s from %s where time between '%s' and '%s'" %(str,tablename,st,sp))
+        # self.cursor.execute("select %s from %s where time between '%s' and '%s'" %(str,tablename,st,sp))
+        self.cursor.execute("select %s from %s where sn='%s' order by add_time desc limit 1" %(str,tablename,sn))
         res = self.cursor.fetchall()
         df_res = pd.DataFrame(res, columns=param)
         df_res = df_res.reset_index(drop=True)

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


+ 11 - 7
LIB/MIDDLE/CellStateEstimation/SOH/main.py

@@ -1,6 +1,5 @@
 import CBMSBatSoh
 import log
-
 #coding=utf-8
 import os
 import datetime
@@ -12,9 +11,15 @@ 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'
+port=3306
+db='qx_cas'
+user='qx_read'
+password='Qx@123456'
+tablename='soh_result'
+
 dbManager = DBManager.DBManager()
 if __name__ == "__main__":
     SNdata_6040 = pd.read_excel('骑享资产梳理-20210621.xlsx', sheet_name='6040骑享')
@@ -26,7 +31,7 @@ if __name__ == "__main__":
     SNnums_4840=SNdata_4840['SN号']
     SNnums_7250=SNdata_7250['SN号']
 
-    SNnums=SNnums_6060.tolist()+SNnums_6040.tolist()+SNnums_4840.tolist()
+    SNnums=SNnums_6040.tolist()+SNnums_6060.tolist()+SNnums_4840.tolist()
     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)
@@ -40,17 +45,16 @@ if __name__ == "__main__":
     for sn in SNnums:
         try:
             dbManager = DBManager.DBManager()
-            df_data = dbManager.get_data(sn=sn, start_time=start_time, end_time=end_time, data_groups=['bms','accum'])
+            df_data = dbManager.get_data(sn='PK50001A100000022', start_time=start_time, end_time=end_time, data_groups=['bms','accum'])
             df_bms = df_data['bms']
             df_accum=df_data['accum']
             # df_bms.to_csv('BMS_'+sn+'.csv')
             # df_accum.to_csv('BMS_accum_'+sn+'.csv')
 
-            BatSoh=CBMSBatSoh.BatSoh(sn,df_bms,df_accum)
+            BatSoh=CBMSBatSoh.BatSoh(sn,df_bms,df_accum,host, port, db, user, password, tablename)
             df_res=BatSoh.batsoh()
             df_res.to_csv('BMS_SOH_'+sn+'.csv',encoding='GB18030')
-        
-        
+             
         except IndexError as e:
             print(repr(e))
             mylog.logopt(sn,e)