|
@@ -0,0 +1,991 @@
|
|
|
+import pandas as pd
|
|
|
+import numpy as np
|
|
|
+import bisect
|
|
|
+import datetime
|
|
|
+import BatParam
|
|
|
+
|
|
|
+class BatDiag:
|
|
|
+ def __init__(self, df_bms): #参数初始化
|
|
|
+
|
|
|
+ self.df_bms=df_bms
|
|
|
+ self.vin=df_bms['VIN']
|
|
|
+ self.model=df_bms['VehModel']
|
|
|
+ self.sn=df_bms['SN']
|
|
|
+
|
|
|
+ self.packcrnt=df_bms['PackCrnt']
|
|
|
+ self.packvolt=df_bms['PackVolt']
|
|
|
+ self.bmssoc=df_bms['PackSoc']
|
|
|
+ self.isor=df_bms['InsulationRss']
|
|
|
+ self.enmtemp=df_bms['EnmTemp']
|
|
|
+ self.bmsstate=df_bms['BMSSta'].fillna(0)
|
|
|
+ self.bmstime= pd.to_datetime(df_bms['Time'], format='%Y-%m-%d %H:%M:%S')
|
|
|
+ CellVoltNums=df_bms['CellVoltTotalCount']
|
|
|
+ CellTempNums=df_bms['CellMinTempNum']
|
|
|
+
|
|
|
+ self.cellvolt_name=['CellVolt'+str(x) for x in range(1,CellVoltNums+1)]
|
|
|
+ self.celltemp_name=['CellTemp'+str(x) for x in range(1,CellTempNums+1)]
|
|
|
+
|
|
|
+ #寻找当前行数据的所有温度值...................................................................................
|
|
|
+ def _celltemp_get(self,num):
|
|
|
+ celltemp = np.array(self.df_bms.loc[num,self.celltemp_name])
|
|
|
+ return celltemp
|
|
|
+
|
|
|
+ #获取当前行所有电压数据............................................................................................
|
|
|
+ def _cellvolt_get(self,num):
|
|
|
+ cellvolt = np.array(self.df_bms.loc[num,self.cellvolt_name]/1000)
|
|
|
+ return cellvolt
|
|
|
+
|
|
|
+ #..........................................................电池故障诊断功能..................................................................
|
|
|
+ def diag(self, df_diag_ram, df_soh, df_sor, df_adjust_param, df_pack_param, df_algo_param):
|
|
|
+
|
|
|
+ # df_res=pd.DataFrame(columns=['start_time', 'end_time', 'vin', 'sn', 'model', 'fault_code', 'fault_reason', 'fault_advice', 'fault_location'])
|
|
|
+ bmssoc_st=self.bmssoc[0]
|
|
|
+ celltemp_stnum=0
|
|
|
+ end_time='0000-00-00 00:00:00'
|
|
|
+ ah_accum=0 #SOC卡滞初始参数
|
|
|
+ cellvoltvalid=1
|
|
|
+ voltdsc_time=0
|
|
|
+ voltfail_time=0
|
|
|
+ voltloose_time=0
|
|
|
+ voltstray_time=0
|
|
|
+ tempstray_time=0
|
|
|
+ packvoltvalid_time=0
|
|
|
+ tempvalid_time=0
|
|
|
+ cov_time=0
|
|
|
+ cuv_time=0
|
|
|
+ cdv_time=0
|
|
|
+ pov_time=0
|
|
|
+ puv_time=0
|
|
|
+ ot_time=0
|
|
|
+ ut_time=0
|
|
|
+ dt_time=0
|
|
|
+ rt_time=0
|
|
|
+ disoc_time=0
|
|
|
+ chgoc_time=0
|
|
|
+ isor_time=0
|
|
|
+
|
|
|
+ sor=eval(df_sor.loc[0,'sor'])
|
|
|
+ sor_mean=np.mean(sor)
|
|
|
+
|
|
|
+ for i in range(1,len(self.df_volt)-1):
|
|
|
+ df_diag_now=df_diag_ram[df_diag_ram['end_time']=='0000-00-00 00:00:00']
|
|
|
+
|
|
|
+ #电压诊断功能.........................................................................................................................................
|
|
|
+ if i<=1:
|
|
|
+ time1=self.bmstime[i-1]
|
|
|
+ time2=self.bmstime[i]
|
|
|
+ cellvolt2=self._cellvolt_get(i)
|
|
|
+ cellvoltmin2=min(cellvolt2)
|
|
|
+ cellvoltmax2=max(cellvolt2)
|
|
|
+ cellvoltmin_index2=list(cellvolt2).index(cellvoltmin2)
|
|
|
+ cellvoltmax_index2=list(cellvolt2).index(cellvoltmax2)
|
|
|
+ cellvolt1=self._cellvolt_get(i-1)
|
|
|
+ cellvoltmin1=min(cellvolt1)
|
|
|
+ cellvoltmax1=max(cellvolt1)
|
|
|
+ cellvoltmin_index1=list(cellvolt1).index(cellvoltmin1)
|
|
|
+ cellvoltmax_index1=list(cellvolt1).index(cellvoltmax1)
|
|
|
+
|
|
|
+ cellvolt1_std=np.std(cellvolt1)
|
|
|
+ cellvolt1_mean=np.mean(cellvolt1)
|
|
|
+ cellvolt1_3sigma=(cellvolt1-cellvolt1_mean)/cellvolt1_std
|
|
|
+ cellvolt2_std=np.std(cellvolt2)
|
|
|
+ cellvolt2_mean=np.mean(cellvolt2)
|
|
|
+ cellvolt2_3sigma=(cellvolt2-cellvolt2_mean)/cellvolt2_std
|
|
|
+
|
|
|
+ celltemp1=self._celltemp_get(i-1)
|
|
|
+ celltemp2=self._celltemp_get(i)
|
|
|
+ celltempmin1=min(celltemp1)
|
|
|
+ celltempmin2=min(celltemp2)
|
|
|
+ celltempmax1=max(celltemp1)
|
|
|
+ celltempmax2=max(celltemp2)
|
|
|
+
|
|
|
+ celltemp1_std=np.std(celltemp1)
|
|
|
+ celltemp1_mean=np.mean(celltemp1)
|
|
|
+ celltemp1_3sigma=(np.array(celltemp1)-celltemp1_mean)/celltemp1_std
|
|
|
+ celltemp2_std=np.std(celltemp2)
|
|
|
+ celltemp2_mean=np.mean(celltemp2)
|
|
|
+ celltemp2_3sigma=(np.array(celltemp2)-celltemp2_mean)/celltemp2_std
|
|
|
+ else:
|
|
|
+ time1=self.bmstime[i-1]
|
|
|
+ time2=self.bmstime[i]
|
|
|
+ cellvolt1=cellvolt2
|
|
|
+ cellvoltmin1=cellvoltmin2
|
|
|
+ cellvoltmax1=cellvoltmax2
|
|
|
+ cellvoltmin_index1=cellvoltmin_index2
|
|
|
+ cellvoltmax_index1=cellvoltmax_index2
|
|
|
+ cellvolt2=self._cellvolt_get(i)
|
|
|
+ cellvoltmin2=min(cellvolt2)
|
|
|
+ cellvoltmax2=max(cellvolt2)
|
|
|
+ cellvoltmin_index2=list(cellvolt2).index(cellvoltmin2)
|
|
|
+ cellvoltmax_index2=list(cellvolt2).index(cellvoltmax2)
|
|
|
+
|
|
|
+ cellvolt1_std=cellvolt2_std
|
|
|
+ cellvolt1_mean=cellvolt2_mean
|
|
|
+ cellvolt1_3sigma=cellvolt2_3sigma
|
|
|
+ cellvolt2_std=np.std(cellvolt2)
|
|
|
+ cellvolt2_mean=np.mean(cellvolt2)
|
|
|
+ cellvolt2_3sigma=(cellvolt2-cellvolt2_mean)/cellvolt2_std
|
|
|
+
|
|
|
+ #电芯电压无效-1..........................................................................................................................................
|
|
|
+ if not 'C309' in list(df_diag_now['fault_code']): #当前故障中没有该故障,则判断是否发生该故障
|
|
|
+ #电芯电压断线
|
|
|
+ if (cellvoltmin2<2 and cellvoltmax2>4.5 and abs(cellvoltmax_index2-cellvoltmin_index2)==1) and (cellvoltmin1<2 and cellvoltmax1>4.5 and abs(cellvoltmax_index1-cellvoltmin_index1)==1): #电压断线故障进入
|
|
|
+ cellvoltvalid=0
|
|
|
+ voltdsc_time=voltdsc_time+(time2-time1).total_seconds()
|
|
|
+ if voltdsc_time>df_adjust_param.loc[1,'confirm_time']: #持续时间
|
|
|
+ fault_code='C309'
|
|
|
+ # faultlv=3
|
|
|
+ # faultinfo='电芯电压无效'
|
|
|
+ fault_reason='电芯电压采样线断线'
|
|
|
+ fault_location='电芯{}'.format([cellvoltmin_index2+1, cellvoltmax_index2+1])
|
|
|
+ fault_advice='召回电池包,进行检修'
|
|
|
+ # influence='失去对电芯电压监测'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ voltdsc_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ elif (cellvoltmin2<2 and cellvoltmax2>4.5 and abs(cellvoltmax_index2-cellvoltmin_index2)==1) and (cellvoltmin1>2.5 and cellvoltmax1<4.3): #连续跳变
|
|
|
+ cellvoltvalid=0
|
|
|
+ voltdsc_time=voltdsc_time+(time2-time1).total_seconds()
|
|
|
+ if voltdsc_time>df_adjust_param.loc[1,'confirm_time']:
|
|
|
+ fault_code='C309'
|
|
|
+ # faultlv=3
|
|
|
+ # faultinfo='电芯电压无效'
|
|
|
+ fault_reason='电芯电压采样线断线'
|
|
|
+ fault_location='电芯{}'.format([cellvoltmin_index2+1, cellvoltmax_index2+1])
|
|
|
+ fault_advice='召回电池包,进行检修'
|
|
|
+ # influence='失去对电芯电压监测'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ voltdsc_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ #电芯电压超限
|
|
|
+ elif ((cellvoltmin2<1 and cellvoltmin1<1) or (cellvoltmax2>5 and cellvoltmax1>5)):
|
|
|
+ cellvoltvalid=0
|
|
|
+ voltdsc_time=0
|
|
|
+ voltfail_time=voltfail_time+(time2-time1).total_seconds()
|
|
|
+ if voltfail_time>df_adjust_param.loc[1,'confirm_time']: #持续时间
|
|
|
+ fault_code='C309'
|
|
|
+ # faultlv=3
|
|
|
+ # faultinfo='电芯电压无效'
|
|
|
+ fault_reason='电芯电压采样电路异常'
|
|
|
+ fault_location='电芯{}'.format(list(np.argwhere(cellvolt2<1)+1)+list(np.argwhere(cellvolt2>5)+1))
|
|
|
+ fault_advice='召回电池包,进行检修'
|
|
|
+ # influence='失去对电芯电压监测'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ voltfail_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ elif (cellvoltmin2<1 and cellvoltmin1>2.5) or (cellvoltmax2>5 and cellvoltmax1<4.5): #连续跳变
|
|
|
+ cellvoltvalid=0
|
|
|
+ voltdsc_time=0
|
|
|
+ voltfail_count=voltfail_count+1
|
|
|
+ if voltfail_count>=3:
|
|
|
+ fault_code='C309'
|
|
|
+ # faultlv=3
|
|
|
+ # faultinfo='电芯电压无效'
|
|
|
+ fault_reason='数据通讯异常'
|
|
|
+ fault_location='电芯{}'.format(list(np.argwhere(cellvolt2<1)+1)+list(np.argwhere(cellvolt2>5)+1))
|
|
|
+ fault_advice='检修数据传输链路'
|
|
|
+ # influence='失去对电芯电压监测'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ voltfail_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ #电芯电压松动
|
|
|
+ elif cellvoltmin2>2 and cellvoltmax2<4.5 and cellvoltmin1>2 and cellvoltmax1<4.5:
|
|
|
+ voltdsc_time=0
|
|
|
+ voltfail_time=0
|
|
|
+ if (min(cellvolt1_3sigma)<-4 and max(cellvolt1_3sigma)>4) and (min(cellvolt2_3sigma)<-4 and max(cellvolt2_3sigma)>4) and (cellvoltmax2-cellvoltmin2)>0.15 and (cellvoltmax1-cellvoltmin1)>0.15: #连续发生
|
|
|
+ cellvoltvalid=0
|
|
|
+ voltloose_time=voltloose_time+(time2-time1).total_seconds()
|
|
|
+ if voltloose_time>df_adjust_param.loc[1,'confirm_time']:
|
|
|
+ fault_code='C309'
|
|
|
+ # faultlv=3
|
|
|
+ # faultinfo='电芯电压无效'
|
|
|
+ fault_reason='电芯电压采样线松动'
|
|
|
+ fault_location='电芯{}'.format([cellvoltmin_index2+1, cellvoltmax_index2+1])
|
|
|
+ fault_advice='召回电池包,进行检修'
|
|
|
+ # influence='失去对电芯电压监测'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ voltloose_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ voltloose_time=0
|
|
|
+ else:
|
|
|
+ voltdsc_time=0
|
|
|
+ voltfail_time=0
|
|
|
+ voltloose_time=0
|
|
|
+ else:
|
|
|
+ cellvoltvalid=0
|
|
|
+ if cellvoltmin2>2 and cellvoltmax2<4.5 and cellvoltmin1>2 and cellvoltmax1<4.5 and (min(cellvolt1_3sigma)>-4 and max(cellvolt1_3sigma)<4) and (min(cellvolt2_3sigma)>-4 and max(cellvolt2_3sigma)<4):
|
|
|
+ voltfail_time=voltfail_time+(time2-time1).total_seconds()
|
|
|
+ if voltfail_time>df_adjust_param.loc[1,'remove_time']:
|
|
|
+ cellvoltvalid=1
|
|
|
+ df_diag_ram.loc[df_diag_ram[df_diag_ram['fault_code']=='C309'].index[-1], 'end_time'] = time2
|
|
|
+ voltfail_time=0
|
|
|
+ else:
|
|
|
+ voltfail_time=0
|
|
|
+
|
|
|
+ #电芯电压诊断............................................................................................................................................
|
|
|
+ if cellvoltvalid==1:
|
|
|
+ #电芯过压-2.............................................................................................................................................
|
|
|
+ if not 'C401' in list(df_diag_now['fault_code']): #当前故障中没有该故障,则判断是否发生该故障
|
|
|
+ if cellvoltmax2>df_adjust_param.loc[2,'threshold'] and cellvoltmax1>df_adjust_param.loc[2,'threshold']: #二级过压进入
|
|
|
+ cov_time=cov_time+(time2-time1).total_seconds()
|
|
|
+ if cov_time>df_adjust_param.loc[2,'confirm_time']:
|
|
|
+ fault_code='C401'
|
|
|
+ # faultlv=4
|
|
|
+ # faultinfo='电芯过压'
|
|
|
+ fault_location='电芯{}'.format(list(np.argwhere(cellvolt2>df_adjust_param.loc[2,'threshold'])+1))
|
|
|
+ # influence='长时间过压会导致电池析锂,存在电池安全与寿命衰减过快风险'
|
|
|
+ cellocvmax=cellvoltmax2-self.packcrnt[i]*sor_mean*2 #内阻反推OCV
|
|
|
+ cellsocmax=np.interp(cellocvmax,df_pack_param.iloc[0]['charge_ocv_v'],df_pack_param.iloc[0]['charge_ocv_soc']) #ocv反查表得到SOC
|
|
|
+ if self.bmssoc[i]<90 and self.packcrnt[i]>-df_pack_param.iloc[0]['capacity']/10 and self.packcrnt[i-1]>-df_pack_param.iloc[0]['capacity']/10:
|
|
|
+ fault_reason='BMS计算SOC偏低'
|
|
|
+ fault_advice='优化SOC算法'
|
|
|
+ elif self.bmssoc[i]<cellsocmax-10:
|
|
|
+ fault_reason='BMS计算SOC偏低'
|
|
|
+ fault_advice='优化SOC算法'
|
|
|
+ elif self.packcrnt[i-1]<-df_pack_param.iloc[0]['capacity']/2 or self.packcrnt[i]<-df_pack_param.iloc[0]['capacity']/2:
|
|
|
+ fault_reason='充电电流过大'
|
|
|
+ fault_advice='优化充放电功率限值'
|
|
|
+ else:
|
|
|
+ fault_reason='1.BMS软件策略BUG,2.继电器粘连'
|
|
|
+ fault_advice='检修电池包'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ cov_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ cov_time=0
|
|
|
+ else: #ram当前故障中有该故障,则判断是否退出该故障
|
|
|
+ if cellvoltmax2<df_adjust_param.loc[2,'threshold']-0.05 and cellvoltmax1<df_adjust_param.loc[2,'threshold']-0.05: #二级过压故障恢复
|
|
|
+ cov_time=cov_time+(time2-time1).total_seconds()
|
|
|
+ if cov_time>df_adjust_param.loc[2,'confirm_time']:
|
|
|
+ df_diag_ram.loc[df_diag_ram[df_diag_ram['fault_code']=='C401'].index[-1], 'end_time'] = time2
|
|
|
+ cov_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ cov_time=0
|
|
|
+
|
|
|
+ #欠压诊断-3.................................................................................................................
|
|
|
+ if not 'C202' in list(df_diag_now['fault_code']): #当前故障中没有该故障,则判断是否发生该故障
|
|
|
+ if cellvoltmin2<df_adjust_param.loc[3,'threshold'] and cellvoltmin1<df_adjust_param.loc[3,'threshold']: #二级欠压
|
|
|
+ cuv_time=cuv_time+(time2-time1).total_seconds()
|
|
|
+ if cuv_time>df_adjust_param.loc[3,'confirm_time']:
|
|
|
+ fault_code='C202'
|
|
|
+ # faultlv=2
|
|
|
+ # faultinfo='电芯{}欠压'
|
|
|
+ fault_location='电芯{}'.format(list(np.argwhere(cellvolt2<df_adjust_param.loc[4,'threshold'])+1))
|
|
|
+ # influence='欠压可能导致电池过放,严重过放会导致负极集流体溶解,进而发生内短路风险'
|
|
|
+ cellocvmin=cellvoltmin2+-self.packcrnt[i]*sor_mean*2 #内阻反推OCV
|
|
|
+ cellsocmin=np.interp(cellocvmin,df_pack_param.iloc[0]['discharge_ocv_v'],df_pack_param.iloc[0]['discharge_ocv_soc']) #ocv反查表得到SOC
|
|
|
+ if self.bmssoc[i]>10 and self.packcrnt[i]<df_pack_param.iloc[0]['capacity']/10 and self.packcrnt[i-1]<df_pack_param.iloc[0]['capacity']/10:
|
|
|
+ fault_reason='BMS计算SOC偏高'
|
|
|
+ fault_advice='优化SOC算法'
|
|
|
+ elif self.bmssoc[i]>cellsocmin+10:
|
|
|
+ fault_reason='BMS计算SOC偏高'
|
|
|
+ fault_advice='优化SOC算法'
|
|
|
+ elif self.packcrnt[i-1]>df_pack_param.iloc[0]['capacity']/2 or self.packcrnt[i]>df_pack_param.iloc[0]['capacity']/2:
|
|
|
+ fault_reason='放电电流过大'
|
|
|
+ fault_advice='优化充放电功率限值'
|
|
|
+ else:
|
|
|
+ fault_reason='1.BMS软件策略BUG,2.继电器粘连'
|
|
|
+ fault_advice='检修电池包'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ cuv_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ cuv_time=0
|
|
|
+ else:
|
|
|
+ if cellvoltmin2>df_adjust_param.loc[3,'threshold']+0.1 and cellvoltmin1>df_adjust_param.loc[3,'threshold']+0.1:
|
|
|
+ cuv_time=cuv_time+(time2-time1).total_seconds()
|
|
|
+ if cuv_time>df_adjust_param.loc[3,'confirm_time']:
|
|
|
+ df_diag_ram.loc[df_diag_ram[df_diag_ram['fault_code']=='C202'].index[-1], 'end_time'] = time2
|
|
|
+ cuv_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ cuv_time=0
|
|
|
+
|
|
|
+ #电芯压差大-4.....................................................................................................................................................
|
|
|
+ if not 'C104' in list(df_diag_now['fault_code']): #当前故障中没有该故障,则判断是否发生该故障
|
|
|
+ if (cellvoltmax2-cellvoltmin2)>df_adjust_param.loc[4,'threshold'] and (cellvoltmax1-cellvoltmin1)>df_adjust_param.loc[4,'threshold']: #二级电芯压差
|
|
|
+ cdv_time=cdv_time+(time2-time1).total_seconds()
|
|
|
+ if cdv_time>df_adjust_param.loc[4,'confirm_time']:
|
|
|
+ fault_code='C104'
|
|
|
+ # faultlv=1
|
|
|
+ # faultinfo='电芯电压一致性差'
|
|
|
+ fault_location='电芯{}'.format([cellvoltmin_index2+1, cellvoltmax_index2+1])
|
|
|
+ fault_advice='更换模组'
|
|
|
+ # influence='容量/内阻/自放电不一致,影响电池充放电性能'
|
|
|
+ if (not df_soh.empty) and (df_soh.loc[0,'cellsohmax']-df_soh.loc[0,'cellsohmin'])>5:
|
|
|
+ fault_reason='电芯容量一致性差'
|
|
|
+ elif ('C316' in list(df_diag_now['fault_code'])) or ('C317' in list(df_diag_now['fault_code'])):
|
|
|
+ fault_reason='电芯内阻一致性差'
|
|
|
+ elif 'C490' in list(df_diag_now['fault_code']):
|
|
|
+ fault_reason='电芯自放电异常'
|
|
|
+ elif celltempmin1<-5 and celltempmin2<-5 and abs(self.packcrnt[i-1])>df_pack_param.iloc[0]['capacity']/10 and abs(self.packcrnt[i])>df_pack_param.iloc[0]['capacity']/10:
|
|
|
+ fault_reason='电芯低温性能差'
|
|
|
+ fault_advice='优化电芯低温性能'
|
|
|
+ elif self.bmssoc[i-1]<3 and self.self.bmssoc[i]<3:
|
|
|
+ fault_reason='SOC过低'
|
|
|
+ fault_advice='通知用户充电'
|
|
|
+ else:
|
|
|
+ fault_reason='BMS均衡逻辑异常'
|
|
|
+ fault_advice='优化均衡策略'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ cdv_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ cdv_time=0
|
|
|
+ else:
|
|
|
+ if (cellvoltmax2-cellvoltmin2)<df_adjust_param.loc[4,'threshold']-0.05 and (cellvoltmax1-cellvoltmin1)<df_adjust_param.loc[4,'threshold']-0.05:
|
|
|
+ cdv_time=cdv_time+(time2-time1).total_seconds()
|
|
|
+ if cdv_time>df_adjust_param.loc[4,'confirm_time']:
|
|
|
+ df_diag_ram.loc[df_diag_ram[df_diag_ram['fault_code']=='C104'].index[-1], 'end_time'] = time2
|
|
|
+ cdv_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ cdv_time=0
|
|
|
+
|
|
|
+ #电芯电压离群-5.......................................................................................................................................
|
|
|
+ if not 'C206' in list(df_diag_now['fault_code']):
|
|
|
+ if (min(cellvolt1_3sigma)<-4 and min(cellvolt2_3sigma)<-4 and cellvolt2_mean-cellvoltmin2>0.02) or (max(cellvolt1_3sigma)>4 and max(cellvolt2_3sigma)>4 and cellvoltmax2-cellvolt2_mean>0.02):
|
|
|
+ voltstray_time=voltstray_time+(time2-time1).total_seconds()
|
|
|
+ if voltstray_time>df_adjust_param.loc[5,'confirm_time']:
|
|
|
+ fault_code='C206'
|
|
|
+ # faultlv=2
|
|
|
+ # faultinfo='电芯电压离群'
|
|
|
+ fault_location='电芯{}'.format([cellvoltmin_index2+1, cellvoltmax_index2+1])
|
|
|
+ fault_advice='更换模组'
|
|
|
+ # influence='容量/内阻/自放电不一致,影响电池充放电性能'
|
|
|
+ if (not df_soh.empty) and (df_soh.loc[0,'cellsohmax']-df_soh.loc[0,'cellsohmin'])>5:
|
|
|
+ fault_reason='电芯容量一致性差'
|
|
|
+ elif ('C316' in list(df_diag_now['fault_code'])) or ('C317' in list(df_diag_now['fault_code'])):
|
|
|
+ fault_reason='电芯内阻一致性差'
|
|
|
+ elif 'C490' in list(df_diag_now['fault_code']):
|
|
|
+ fault_reason='电芯自放电异常'
|
|
|
+ elif celltempmin1<-5 and celltempmin2<-5 and abs(self.packcrnt[i-1])>df_pack_param.iloc[0]['capacity']/10 and abs(self.packcrnt[i])>df_pack_param.iloc[0]['capacity']/10:
|
|
|
+ fault_reason='电芯低温性能差'
|
|
|
+ fault_advice='优化电芯低温性能'
|
|
|
+ elif self.bmssoc[i-1]<3 and self.self.bmssoc[i]<3:
|
|
|
+ fault_reason='SOC过低'
|
|
|
+ fault_advice='通知用户充电'
|
|
|
+ else:
|
|
|
+ fault_reason='BMS均衡逻辑异常'
|
|
|
+ fault_advice='优化均衡策略'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ voltstray_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ voltstray_time=0
|
|
|
+ else:
|
|
|
+ if min(cellvolt1_3sigma)>-3 and min(cellvolt2_3sigma)>-3 and max(cellvolt1_3sigma)<3 and max(cellvolt2_3sigma)<3:
|
|
|
+ voltstray_time=voltstray_time+(time2-time1).total_seconds()
|
|
|
+ if voltstray_time>df_adjust_param.loc[4,'confirm_time']:
|
|
|
+ df_diag_ram.loc[df_diag_ram[df_diag_ram['fault_code']=='C206'].index[-1], 'end_time'] = time2
|
|
|
+ voltstray_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ voltstray_time=0
|
|
|
+
|
|
|
+ else:
|
|
|
+ cov_time=0
|
|
|
+ cuv_time=0
|
|
|
+ cdv_time=0
|
|
|
+ voltstray_time=0
|
|
|
+
|
|
|
+ #电池包诊断-6.....................................................................................................................................
|
|
|
+ packvolt1=self.packvolt[i-1]
|
|
|
+ packvolt2=self.packvolt[i]
|
|
|
+ if not 'C304' in list(df_diag_now['fault_code']):
|
|
|
+ if packvolt2<2*df_pack_param.iloc[0]['cellvoltnum'] or packvolt2>4.5*df_pack_param.iloc[0]['cellvoltnum'] or (cellvoltvalid==1 and abs(packvolt2-sum(cellvolt2))>10): #电池包电压有效性
|
|
|
+ packvoltvalid=0
|
|
|
+ packvoltvalid_time=packvoltvalid_time+(time2-time1).total_seconds()
|
|
|
+ if packvoltvalid_time>df_adjust_param.loc[6,'confirm_time']:
|
|
|
+ fault_code='304'
|
|
|
+ # faultlv=3
|
|
|
+ # faultinfo='电池包电压无效'
|
|
|
+ fault_reason='1.电池包电压采样电路异常,2.数据通讯异常'
|
|
|
+ fault_location='电池包电压'
|
|
|
+ fault_advice='召回电池包,进行检修'
|
|
|
+ # influence='失去对电池包电压监测'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ packvoltvalid_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ packvoltvalid=1
|
|
|
+ packvoltvalid_time=0
|
|
|
+ else:
|
|
|
+ packvoltvalid=0
|
|
|
+ if packvolt1>2.2*df_pack_param.iloc[0]['cellvoltnum'] and packvolt2<4.3*df_pack_param.iloc[0]['cellvoltnum']:
|
|
|
+ packvoltvalid_time=packvoltvalid_time+(time2-time1).total_seconds()
|
|
|
+ if packvoltvalid_time>df_adjust_param.loc[6,'confirm_time']:
|
|
|
+ packvoltvalid=1
|
|
|
+ df_diag_ram.loc[df_diag_ram[df_diag_ram['fault_code']=='C304'].index[-1], 'end_time'] = time2
|
|
|
+ packvoltvalid_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ packvoltvalid_time=0
|
|
|
+
|
|
|
+ if packvoltvalid==1:
|
|
|
+ #电池包过压-7...................................................................................................
|
|
|
+ if not 'C402' in list(df_diag_now['fault_code']): #当前故障中没有该故障,则判断是否发生该故障
|
|
|
+ if packvolt1>df_adjust_param.loc[7,'threshold'] and packvolt2>df_adjust_param.loc[7,'threshold']: #电池包过压二级进入
|
|
|
+ pov_time=pov_time+(time2-time1).total_seconds()
|
|
|
+ if pov_time>df_adjust_param.loc[7,'confirm_time']:
|
|
|
+ fault_code='C402'
|
|
|
+ # faultlv=4
|
|
|
+ # faultinfo='电池包过压'
|
|
|
+ fault_location='电池包电压'
|
|
|
+ # influence='长时间过压会导致电池析锂,存在电池安全与寿命衰减过快风险'
|
|
|
+ cellocvmax=cellvoltmax2-self.packcrnt[i]*sor_mean*2 #内阻反推OCV
|
|
|
+ cellsocmax=np.interp(cellocvmax,df_pack_param.iloc[0]['charge_ocv_v'],df_pack_param.iloc[0]['charge_ocv_soc']) #ocv反查表得到SOC
|
|
|
+ if self.bmssoc[i]<90 and self.packcrnt[i]>-df_pack_param.iloc[0]['capacity']/10 and self.packcrnt[i-1]>-df_pack_param.iloc[0]['capacity']/10:
|
|
|
+ fault_reason='BMS计算SOC偏低'
|
|
|
+ fault_advice='优化SOC算法'
|
|
|
+ elif self.bmssoc[i]<cellsocmax-10:
|
|
|
+ fault_reason='BMS计算SOC偏低'
|
|
|
+ fault_advice='优化SOC算法'
|
|
|
+ elif self.packcrnt[i-1]<-df_pack_param.iloc[0]['capacity']/2 or self.packcrnt[i]<-df_pack_param.iloc[0]['capacity']/2:
|
|
|
+ fault_reason='充电电流过大'
|
|
|
+ fault_advice='优化充放电功率限值'
|
|
|
+ else:
|
|
|
+ fault_reason='1.BMS软件策略BUG,2.继电器粘连'
|
|
|
+ fault_advice='检修电池包'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ pov_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ pov_time=0
|
|
|
+ else:
|
|
|
+ if packvolt1<df_adjust_param.loc[7,'threshold']-10 and packvolt2<df_adjust_param.loc[7,'threshold']-10: #电池包过压二级恢复
|
|
|
+ pov_time=pov_time+(time2-time1).total_seconds()
|
|
|
+ if pov_time>df_adjust_param.loc[7,'confirm_time']:
|
|
|
+ df_diag_ram.loc[df_diag_ram[df_diag_ram['fault_code']=='C402'].index[-1], 'end_time'] = time2
|
|
|
+ pov_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ pov_time=0
|
|
|
+ #电池包欠压-8.......................................................................................................................................
|
|
|
+ if not 'C203' in list(df_diag_now['fault_code']): #当前故障中没有该故障,则判断是否发生该故障
|
|
|
+ if packvolt1<df_adjust_param.loc[8,'threshold'] and packvolt2<df_adjust_param.loc[7,'threshold']: #电池包二级欠压进入
|
|
|
+ puv_time=puv_time+(time2-time1).total_seconds()
|
|
|
+ if puv_time>df_adjust_param.loc[8,'confirm_time']:
|
|
|
+ fault_code='C203'
|
|
|
+ # faultlv=2
|
|
|
+ # faultinfo='电池包欠压'
|
|
|
+ fault_location='电池包电压'
|
|
|
+ # influence='欠压可能导致电池过放,严重过放会导致负极集流体溶解,进而发生内短路风险'
|
|
|
+ cellocvmin=cellvoltmin2+-self.packcrnt[i]*sor_mean*2 #内阻反推OCV
|
|
|
+ cellsocmin=np.interp(cellocvmin,df_pack_param.iloc[0]['discharge_ocv_v'],df_pack_param.iloc[0]['discharge_ocv_soc']) #ocv反查表得到SOC
|
|
|
+ if self.bmssoc[i]>10 and self.packcrnt[i]<df_pack_param.iloc[0]['capacity']/10 and self.packcrnt[i-1]<df_pack_param.iloc[0]['capacity']/10:
|
|
|
+ fault_reason='BMS计算SOC偏高'
|
|
|
+ fault_advice='优化SOC算法'
|
|
|
+ elif self.bmssoc[i]>cellsocmin+10:
|
|
|
+ fault_reason='BMS计算SOC偏高'
|
|
|
+ fault_advice='优化SOC算法'
|
|
|
+ elif self.packcrnt[i-1]>df_pack_param.iloc[0]['capacity']/2 or self.packcrnt[i]>df_pack_param.iloc[0]['capacity']/2:
|
|
|
+ fault_reason='放电电流过大'
|
|
|
+ fault_advice='优化充放电功率限值'
|
|
|
+ else:
|
|
|
+ fault_reason='1.BMS软件策略BUG,2.继电器粘连'
|
|
|
+ fault_advice='检修电池包'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ puv_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ puv_time=0
|
|
|
+ else:
|
|
|
+ if packvolt1>df_adjust_param.loc[8,'threshold']+10 and packvolt2>df_adjust_param.loc[8,'threshold']+10:
|
|
|
+ puv_time=puv_time+(time2-time1).total_seconds()
|
|
|
+ if puv_time>df_adjust_param.loc[8,'remove_time']:
|
|
|
+ df_diag_ram.loc[df_diag_ram[df_diag_ram['fault_code']=='C203'].index[-1], 'end_time'] = time2
|
|
|
+ puv_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ puv_time=0
|
|
|
+ else:
|
|
|
+ pov_time=0
|
|
|
+ puv_time=0
|
|
|
+ packvoltvalid_time=0
|
|
|
+
|
|
|
+ #温度有效性判断-9................................................................................................................................................
|
|
|
+ if not 'C301' in list(df_diag_now['fault_code']):
|
|
|
+ if celltempmax2>int(eval(df_algo_param.loc[9,'global_param'])['tempuplmt']) or celltempmin2<int(eval(df_algo_param.loc[9,'global_param'])['templwlmt']):
|
|
|
+ celltempvalid=0
|
|
|
+ tempvalid_time=tempvalid_time+(time2-time1).total_seconds()
|
|
|
+ if tempvalid_time>df_adjust_param.loc[9,'confirm_time']:
|
|
|
+ fault_code='301'
|
|
|
+ # faultlv=3
|
|
|
+ # faultinfo='电芯温度无效'
|
|
|
+ fault_reason='1.温度采样电路异常,2.数据通讯异常'
|
|
|
+ fault_location='温度探针{}'.format(list(np.argwhere(np.array(celltemp2)<int(eval(df_algo_param.loc[9,'global_param'])['templwlmt']))+1)+list(np.argwhere(np.array(celltemp2)>int(eval(df_algo_param.loc[9,'global_param'])['tempuplmt']))+1))
|
|
|
+ fault_advice='召回电池包,进行检修'
|
|
|
+ # influence='失去对电池温度监测'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ tempvalid_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ celltempvalid=1
|
|
|
+ tempvalid_time=0
|
|
|
+ else:
|
|
|
+ celltempvalid=0
|
|
|
+ if -25<celltempmax1<60 and -25<celltempmax2<60:
|
|
|
+ tempvalid_time=tempvalid_time+(time2-time1).total_seconds()
|
|
|
+ if tempvalid_time>df_adjust_param.loc[9,'remove_time']:
|
|
|
+ df_diag_ram.loc[df_diag_ram[df_diag_ram['fault_code']=='C304'].index[-1], 'end_time'] = time2
|
|
|
+ tempvalid_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ tempvalid_time=0
|
|
|
+
|
|
|
+ if celltempvalid==1:
|
|
|
+ #过温判断-10.............................................................................................................
|
|
|
+ if not 'C302' in list(df_diag_now['fault_code']): #当前故障中没有该故障,则判断是否发生该故障
|
|
|
+ if celltempmax1>df_adjust_param.loc[10,'threshold'] and celltempmax2>df_adjust_param.loc[10,'threshold']: #二级高温进入
|
|
|
+ ot_time=ot_time+(time2-time1).total_seconds()
|
|
|
+ if ot_time>df_adjust_param.loc[10,'confirm_time']:
|
|
|
+ fault_code='C302'
|
|
|
+ # faultlv=3
|
|
|
+ # faultinfo='电芯温度过高'
|
|
|
+ fault_location='温度探针{}'.format(list(np.argwhere(np.array(celltemp2)>df_adjust_param.loc[10,'threshold'])+1))
|
|
|
+ fault_advice='禁止充放电,并开启电池冷却功能'
|
|
|
+ # influence='高温下充放电,SEI膜增长加速,导致容量衰减过快,温度过高则存在热失控风险'
|
|
|
+ if max(celltemp1_3sigma)>3 and max(celltemp2_3sigma)>3:
|
|
|
+ fault_reason='Busbar连接异常'
|
|
|
+ fault_advice='检修电池包'
|
|
|
+ elif sum(self.packcrnt[:i]*self.packvolt[:i])/(1000*(i+1))>50:
|
|
|
+ fault_reason='电池持续输出大功率'
|
|
|
+ fault_advice='优化电池充放电功率限值'
|
|
|
+ else:
|
|
|
+ fault_reason='1.冷却液温度过高,2.冷却水泵异常,3.Busbar连接异常'
|
|
|
+ fault_advice='检修电池包'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ ot_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ ot_time=0
|
|
|
+ else: #ram当前故障中有该故障,则判断是否退出该故障
|
|
|
+ if celltempmax1<df_adjust_param.loc[10,'threshold']-5 and celltempmax2<df_adjust_param.loc[10,'threshold']-5:
|
|
|
+ ot_time=ot_time+(time2-time1).total_seconds()
|
|
|
+ if ot_time>df_adjust_param.loc[10,'remove_time']:
|
|
|
+ df_diag_ram.loc[df_diag_ram[df_diag_ram['fault_code']=='C302'].index[-1], 'end_time'] = time2
|
|
|
+ ot_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ ot_time=0
|
|
|
+
|
|
|
+ #欠温判断-11.................................................................................................................
|
|
|
+ if not 'C102' in list(df_diag_now['fault_code']): #当前故障中没有该故障,则判断是否发生该故障
|
|
|
+ if celltempmin1<df_adjust_param.loc[11,'threshold'] and celltempmin2<df_adjust_param.loc[11,'threshold']: #二级低温进入
|
|
|
+ ut_time=ut_time+(time2-time1).total_seconds()
|
|
|
+ if ut_time>df_adjust_param.loc[11,'confirm_time']:
|
|
|
+ fault_code='C102'
|
|
|
+ # faultlv=1
|
|
|
+ # faultinfo='电芯温度过低'
|
|
|
+ fault_location='温度探针{}'.format(list(np.argwhere(np.array(celltemp2)<df_adjust_param.loc[11,'threshold'])+1))
|
|
|
+ # influence='低温下充电,会导致析锂,存在电池安全与寿命衰减过快风险'
|
|
|
+ if self.enmtemp[i-1]-celltempmin1>10 and self.enmtemp[i]-celltempmin2>10:
|
|
|
+ fault_reason='温度检测系统异常'
|
|
|
+ fault_advice='检修电池包'
|
|
|
+ elif self.bmssoc[i-1]<5 and self.bmssoc[i]<5:
|
|
|
+ fault_reason='电池包SOC过低'
|
|
|
+ fault_advice='通知用户进行充电'
|
|
|
+ else:
|
|
|
+ fault_reason='PTC加热系统异常'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ ut_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ ut_time=0
|
|
|
+ else: #ram当前故障中有该故障,则判断是否退出该故障
|
|
|
+ if celltempmax1>df_adjust_param.loc[11,'threshold']+2 and celltempmax2>df_adjust_param.loc[11,'threshold']+2: #二级高温恢复
|
|
|
+ ut_time=ut_time+(time2-time1).total_seconds()
|
|
|
+ if ut_time>df_adjust_param.loc[11,'remove_time']:
|
|
|
+ df_diag_ram.loc[df_diag_ram[df_diag_ram['fault_code']=='C102'].index[-1], 'end_time'] = time2
|
|
|
+ ut_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ ut_time=0
|
|
|
+
|
|
|
+ #温差判断-12.............................................................................................................................
|
|
|
+ if not 'C103' in list(df_diag_now['fault_code']): #当前故障中没有该故障,则判断是否发生该故障
|
|
|
+ if (celltempmax1-celltempmin1)>df_adjust_param.loc[12,'threshold'] and (celltempmax2-celltempmin2)>df_adjust_param.loc[12,'threshold']: #二级温差进入
|
|
|
+ dt_time=dt_time+(time2-time1).total_seconds()
|
|
|
+ if dt_time>df_adjust_param.loc[12,'confirm_time']:
|
|
|
+ fault_code='C103'
|
|
|
+ # faultlv=1
|
|
|
+ # faultinfo='电芯温差过大'
|
|
|
+ fault_location='温度探针{}'.format([list(celltemp2).index(celltempmin2)+1,list(celltemp2).index(celltempmax2)+1])
|
|
|
+ # influence='存在电芯的老化速率不一致的风险'
|
|
|
+ if self.enmtemp[i-1]>0 and self.enmtemp>0 and (('C316' in list(df_diag_now['fault_code'])) or ('C317' in list(df_diag_now['fault_code']))):
|
|
|
+ fault_reason='电芯内阻不一致'
|
|
|
+ fault_advice='更换模组'
|
|
|
+ elif self.enmtemp[i-1]>10 and self.enmtemp>10:
|
|
|
+ fault_reason='Busbar连接异常'
|
|
|
+ fault_advice='检修电池包'
|
|
|
+ elif self.enmtemp[i-1]<-10 and self.enmtemp<-10:
|
|
|
+ fault_reason='环境温度过低'
|
|
|
+ fault_advice='合理优化低温充放电功率限值,并开启水泵'
|
|
|
+ else:
|
|
|
+ fault_reason='电池包冷却/加热系统设计不合理'
|
|
|
+ fault_advice='合理优化电池包冷却/加热系统'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ dt_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ dt_time=0
|
|
|
+ else: #ram当前故障中有该故障,则判断是否退出该故障
|
|
|
+ if (celltempmax1-celltempmin1)<df_adjust_param.loc[12,'threshold']-5 and (celltempmax2-celltempmin2)>df_adjust_param.loc[12,'threshold']-5: #二级温差恢复
|
|
|
+ dt_time=dt_time+(time2-time1).total_seconds()
|
|
|
+ if dt_time>df_adjust_param.loc[12,'remove_time']:
|
|
|
+ df_diag_ram.loc[df_diag_ram[df_diag_ram['fault_code']=='C103'].index[-1], 'end_time'] = time2
|
|
|
+ dt_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ dt_time=0
|
|
|
+
|
|
|
+ #温度离群判断-13.............................................................................................................................
|
|
|
+ if not 'C105' in list(df_diag_now['fault_code']): #当前故障中没有该故障,则判断是否发生该故障
|
|
|
+ if (max(celltemp1_3sigma)>3 and max(celltemp2_3sigma)>3) or (min(celltemp1_3sigma)<-3 and min(celltemp2_3sigma)<-3):
|
|
|
+ tempstray_time=tempstray_time+(time2-time1).total_seconds()
|
|
|
+ if tempstray_time>df_adjust_param.loc[13,'confirm_time']:
|
|
|
+ fault_code='C105'
|
|
|
+ # faultlv=1
|
|
|
+ # faultinfo='电芯温度离群'
|
|
|
+ fault_location='温度探针{}'.format([list(celltemp2).index(celltempmax2)+1,list(celltemp2).index(celltempmin2)+1])
|
|
|
+ # influence='存在电芯的老化速率不一致的风险'
|
|
|
+ if self.enmtemp[i-1]>0 and self.enmtemp>0 and (('C316' in list(df_diag_now['fault_code'])) or ('C317' in list(df_diag_now['fault_code']))):
|
|
|
+ fault_reason='电芯内阻不一致'
|
|
|
+ fault_advice='更换模组'
|
|
|
+ elif self.enmtemp[i-1]>10 and self.enmtemp>10:
|
|
|
+ fault_reason='Busbar连接异常'
|
|
|
+ fault_advice='检修电池包'
|
|
|
+ elif self.enmtemp[i-1]<-10 and self.enmtemp<-10:
|
|
|
+ fault_reason='环境温度过低'
|
|
|
+ fault_advice='合理优化低温充放电功率限值,并开启水泵'
|
|
|
+ else:
|
|
|
+ fault_reason='电池包冷却/加热系统设计不合理'
|
|
|
+ fault_advice='合理优化电池包冷却/加热系统'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ tempstray_time=0
|
|
|
+ else:
|
|
|
+ tempstray_time=0
|
|
|
+ else: #ram当前故障中有该故障,则判断是否退出该故障
|
|
|
+ if (max(celltemp1_3sigma)<3 and max(celltemp2_3sigma)<3) or (min(celltemp1_3sigma)>-3 and min(celltemp2_3sigma)>-3):
|
|
|
+ tempstray_time=tempstray_time+(time2-time1).total_seconds()
|
|
|
+ if tempstray_time>df_adjust_param.loc[13,'remove_time']:
|
|
|
+ df_diag_ram.loc[df_diag_ram[df_diag_ram['fault_code']=='C105'].index[-1], 'end_time'] = time2
|
|
|
+ tempstray_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ tempstray_time=0
|
|
|
+
|
|
|
+ #温升速率-14...............................................................................................................................
|
|
|
+ rtac_time=(time2-self.bmstime[celltemp_stnum]).total_seconds()
|
|
|
+ if rtac_time>60:
|
|
|
+ celltemp_st=np.array(self._celltemp_get(celltemp_stnum))
|
|
|
+ celltemprate=(np.array(celltemp2)-celltemp_st)/(rtac_time*60)
|
|
|
+ celltemp_stnum=celltemp_stnum+1
|
|
|
+ if not 'C303' in list(df_diag_now['fault_code']): #当前故障中没有该故障,则判断是否发生该故障
|
|
|
+ if max(celltemprate)>df_adjust_param.loc[14,'threshold']:
|
|
|
+ rt_time=rt_time+(time2-time1).total_seconds()
|
|
|
+ if rt_time>df_adjust_param.loc[14,'confirm_time']:
|
|
|
+ fault_code='C303'
|
|
|
+ # faultlv=3
|
|
|
+ # faultinfo='电芯温升过快'
|
|
|
+ fault_location='温度探针{}'.format((np.argwhere(celltemp_st>df_adjust_param.loc[14,'threshold'])+1).tolist())
|
|
|
+ # influence='温升速率过快,存在热失控风险'
|
|
|
+ if max(celltemp1_3sigma)>3 and max(celltemp2_3sigma)>3:
|
|
|
+ fault_reason='Busbar连接异常'
|
|
|
+ fault_advice='检修电池包'
|
|
|
+ elif sum(self.packcrnt[:i]*self.packvolt[:i])/(1000*(i+1))>50:
|
|
|
+ fault_reason='电池持续输出大功率'
|
|
|
+ fault_advice='优化电池充放电功率限值'
|
|
|
+ else:
|
|
|
+ fault_reason='1.冷却液温度过高,2.冷却水泵异常,3.Busbar连接异常'
|
|
|
+ fault_advice='检修电池包'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ rt_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ rt_time=0
|
|
|
+ else: #ram当前故障中有该故障,则判断是否退出该故障
|
|
|
+ if max(celltemprate)<2:
|
|
|
+ rt_time=rt_time+(time2-time1).total_seconds()
|
|
|
+ if rt_time<df_adjust_param.loc[14,'remove_time']:
|
|
|
+ df_diag_ram.loc[df_diag_ram[df_diag_ram['fault_code']=='303'].index[-1], 'end_time'] = time2
|
|
|
+ rt_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ rt_time=0
|
|
|
+
|
|
|
+ else:
|
|
|
+ ot_time=0
|
|
|
+ ut_time=0
|
|
|
+ dt_time=0
|
|
|
+ rt_time=0
|
|
|
+ tempstray_time=0
|
|
|
+
|
|
|
+ #放电过流诊断-16.......................................................................................................................
|
|
|
+ if not 'C306' in list(df_diag_now['fault_code']): #当前故障中没有该故障,则判断是否发生该故障
|
|
|
+ if self.packcrnt[i]>df_adjust_param.loc[16,'threshold'] and self.packcrnt[i-1]>df_adjust_param.loc[16,'threshold']:
|
|
|
+ disoc_time=disoc_time+(time2-time1).total_seconds()
|
|
|
+ if disoc_time>df_adjust_param.loc[16,'confirm_time']:
|
|
|
+ fault_code='C306'
|
|
|
+ # faultlv=3
|
|
|
+ # faultinfo='电池放电过流'
|
|
|
+ fault_location='电池包'
|
|
|
+ # influence='长时间过流会导致电池欠压及温升过快'
|
|
|
+ if cellvoltmin1<df_adjust_param.loc[3,'threshold']+0.5 and cellvoltmin2<df_adjust_param.loc[3,'threshold']+0.5:
|
|
|
+ fault_reason='BMS控制策略异常'
|
|
|
+ fault_advice='优化BMS控制策略'
|
|
|
+ else:
|
|
|
+ fault_reason='1.充电器异常,2.继电器粘连'
|
|
|
+ fault_advice='停止放电'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ disoc_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ disoc_time=0
|
|
|
+ else:
|
|
|
+ if self.packcrnt[i]<df_adjust_param.loc[16,'threshold']-10 and self.packcrnt[i-1]<df_adjust_param.loc[16,'threshold']-10:
|
|
|
+ disoc_time=disoc_time+(time2-time1).total_seconds()
|
|
|
+ if disoc_time>df_adjust_param.loc[16,'remove_time']:
|
|
|
+ df_diag_ram.loc[df_diag_ram[df_diag_ram['fault_code']=='C306'].index[-1], 'end_time'] = time2
|
|
|
+ disoc_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ disoc_time=0
|
|
|
+ #充电过流-15.................................................................................
|
|
|
+ if not 'C305' in list(df_diag_now['fault_code']): #当前故障中没有该故障,则判断是否发生该故障
|
|
|
+ if self.packcrnt[i]<df_adjust_param.loc[15,'threshold'] and self.packcrnt[i-1]<df_adjust_param.loc[15,'threshold']:
|
|
|
+ chgoc_time=chgoc_time+(time2-time1).total_seconds()
|
|
|
+ if chgoc_time>df_adjust_param.loc[15,'confirm_time']:
|
|
|
+ fault_code='C305'
|
|
|
+ # faultlv=3
|
|
|
+ # faultinfo='电池充电过流'
|
|
|
+ fault_location='电池包'
|
|
|
+ # influence='过流会导致电池析锂,存在电池安全与寿命衰减过快风险'
|
|
|
+ if cellvoltmax1>df_adjust_param.loc[2,'threshold']-0.1 and cellvoltmax2>df_adjust_param.loc[2,'threshold']-0.1:
|
|
|
+ fault_reason='BMS控制策略异常'
|
|
|
+ fault_advice='优化BMS控制策略'
|
|
|
+ else:
|
|
|
+ fault_reason='1.充电器异常,2.继电器粘连'
|
|
|
+ fault_advice='停止放电'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ chgoc_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ if self.packcrnt[i]>df_adjust_param.loc[15,'threshold']+10 and self.packcrnt[i-1]>df_adjust_param.loc[15,'threshold']+10:
|
|
|
+ chgoc_time=chgoc_time+(time2-time1).total_seconds()
|
|
|
+ if chgoc_time>df_adjust_param.loc[15,'remove_time']:
|
|
|
+ df_diag_ram.loc[df_diag_ram[df_diag_ram['fault_code']=='C305'].index[-1], 'end_time'] = time2
|
|
|
+ chgoc_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ chgoc_time=0
|
|
|
+
|
|
|
+ #SOC故障诊断........................................................................................................................
|
|
|
+ #SOC卡滞-18
|
|
|
+ if not 'C106' in list(df_diag_now['fault_code']): #当前故障中没有该故障,则判断是否发生该故障
|
|
|
+ step=(time2-time1).total_seconds()
|
|
|
+ if step<120:
|
|
|
+ ah_accum=ah_accum-self.packcrnt[i]*step/3600 #ah累计
|
|
|
+ if abs(ah_accum)>df_pack_param.iloc[0]['capacity']*0.1:
|
|
|
+ bmssoc_now=self.bmssoc[i]
|
|
|
+ if abs(bmssoc_now-bmssoc_st)<df_adjust_param.loc[18,'threshold']: #SOC卡滞故障进入
|
|
|
+ fault_code='C106'
|
|
|
+ # faultlv=1
|
|
|
+ # faultinfo='电池SOC卡滞'
|
|
|
+ fault_location='电池包SOC'
|
|
|
+ if cellvoltvalid==0:
|
|
|
+ fault_reason='电压采样异常'
|
|
|
+ fault_advice='检查电芯电压采样系统'
|
|
|
+ else:
|
|
|
+ fault_reason='BMS软件SOC估算异常'
|
|
|
+ fault_advice='检修BMS软件'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ bmssoc_st=bmssoc_now
|
|
|
+ ah_accum=0
|
|
|
+ else:
|
|
|
+ if abs(bmssoc_now-bmssoc_st)>df_adjust_param.loc[18,'threshold']: #SOC卡滞故障退出
|
|
|
+ df_diag_ram.loc[df_diag_ram[df_diag_ram['fault_code']=='C106'].index[-1], 'end_time'] = time2
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+
|
|
|
+ #SOC跳变-17....................................................................................................................
|
|
|
+ bmssoc_last=self.bmssoc[i-1]
|
|
|
+ bmssoc_now=self.bmssoc[i]
|
|
|
+ if not 'C107' in list(df_diag_now['fault_code']): #当前故障中没有该故障,则判断是否发生该故障
|
|
|
+ if step<70 and abs(bmssoc_now-bmssoc_last)>df_adjust_param.loc[17,'threshold']: #SOC跳变进入
|
|
|
+ fault_code='C107'
|
|
|
+ # faultlv=1
|
|
|
+ # faultinfo='电池SOC跳变'
|
|
|
+ fault_location='电池包SOC'
|
|
|
+ if cellvoltvalid==0:
|
|
|
+ fault_reason='电压采样异常'
|
|
|
+ fault_advice='检查电芯电压采样系统'
|
|
|
+ else:
|
|
|
+ fault_reason='BMS软件SOC估算异常'
|
|
|
+ fault_advice='检修BMS软件'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ if abs(bmssoc_now-bmssoc_last)<df_adjust_param.loc[17,'threshold']: #SOC跳变故障退出
|
|
|
+ df_diag_ram.loc[df_diag_ram[df_diag_ram['fault_code']=='C107'].index[-1], 'end_time'] = time2
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+
|
|
|
+ #绝缘故障检测
|
|
|
+ if not 'C315' in list(df_diag_now['fault_code']): #当前故障中没有该故障,则判断是否发生该故障
|
|
|
+ if self.isor[i-1]<df_adjust_param.loc[19,'threshold'] and self.isor[i]<df_adjust_param.loc[19,'threshold']:
|
|
|
+ isor_time=isor_time+(time2-time1).total_seconds()
|
|
|
+ if isor_time>df_adjust_param.loc[19,'confirm_time']:
|
|
|
+ fault_code='C315'
|
|
|
+ # faultlv=3
|
|
|
+ # faultinfo='绝缘异常'
|
|
|
+ fault_advice='召回车辆,检修高压线路/接插件'
|
|
|
+ if self.isor[i-1]<5 and self.isor[i]<5:
|
|
|
+ fault_reason='绝缘检测系统异常'
|
|
|
+ fault_location='绝缘检测系统'
|
|
|
+ elif self.bmsstate[i-1]==2 or self.bmsstate[i-1]==3:
|
|
|
+ fault_reason='充电桩绝缘异常'
|
|
|
+ fault_location='充电桩'
|
|
|
+ fault_advice='通知用户使用其他充电桩进行充电'
|
|
|
+ elif self.vehstate[i-1]!=2 and self.vehstate[i]!=2:
|
|
|
+ fault_reason='电池包内高压线路/接插件异常'
|
|
|
+ fault_location='电池包内高压线路/接插件'
|
|
|
+ else:
|
|
|
+ fault_reason='电池包外高压线路/接插件异常'
|
|
|
+ fault_location='电池包外高压线路/接插件'
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ isor_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ isor_time=0
|
|
|
+ else:
|
|
|
+ if self.isor[i-1]>df_adjust_param.loc[19,'threshold']+100 and self.isor[i]>df_adjust_param.loc[19,'threshold']+100:
|
|
|
+ isor_time=isor_time+(time2-time1).total_seconds()
|
|
|
+ if isor_time>df_adjust_param.loc[19,'remove_time']:
|
|
|
+ df_diag_ram.loc[df_diag_ram[df_diag_ram['fault_code']=='C315'].index[-1], 'end_time'] = time2
|
|
|
+ isor_time=0
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ isor_time=0
|
|
|
+
|
|
|
+ # #SOC一致性故障报警..........................................................................................................
|
|
|
+ # if not self.df_uniform.empty:
|
|
|
+ # cellsoc_diff=self.df_uniform.loc[0,'cellsoc_diff']
|
|
|
+ # if not 'C201' in list(df_diag_now['fault_code']): #当前故障中没有该故障,则判断是否发生该故障
|
|
|
+ # if cellsoc_diff>self.param.SocDiff: #SOC一致性差故障进入
|
|
|
+ # time=self.bmstime[0]
|
|
|
+ # fault_code='C201'
|
|
|
+ # faultlv=0
|
|
|
+ # faultinfo='电芯{}和{}SOC差过大:{}'.format(int(self.df_uniform.loc[0,'cellmin_num']),int(self.df_uniform.loc[0,'cellmax_num']),cellsoc_diff)
|
|
|
+ # fault_advice='技术介入诊断'
|
|
|
+ # df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.sn, fault_code, faultlv, faultinfo, fault_advice]
|
|
|
+ # else:
|
|
|
+ # pass
|
|
|
+ # else:
|
|
|
+ # if cellsoc_diff<self.param.SocDiff: #SOC一致性差故障恢复
|
|
|
+ # time=self.bmstime[0]
|
|
|
+ # df_diag_ram.loc[df_diag_ram[df_diag_ram['fault_code']=='C201'].index[-1], 'end_time'] = time2
|
|
|
+ # else:
|
|
|
+ # cellsoc_diff=3
|
|
|
+
|
|
|
+ #容量过低和一致性故障报警-20-21................................................................................................
|
|
|
+ if not df_soh.empty:
|
|
|
+ soh=df_soh.loc[0,'soh']
|
|
|
+ cellsoh=eval(df_soh.loc[0,'cellsoh'])
|
|
|
+ cellsoh=np.array(cellsoh)
|
|
|
+ cellsoh_lowindex=np.argwhere(cellsoh<df_adjust_param.loc[20,'threshold']).tolist()
|
|
|
+ cellsoh_lowindex=cellsoh_lowindex+1
|
|
|
+ if self.celltype==1 or self.celltype==2 or self.celltype==3 or self.celltype==4:
|
|
|
+ cellsoh_diff=np.max(cellsoh)-np.min(cellsoh)
|
|
|
+ if not 'C204' in list(df_diag_now['fault_code']): #当前故障中没有该故障,则判断是否发生该故障
|
|
|
+ if soh<df_adjust_param.loc[20,'threshold']: #soh过低故障进入
|
|
|
+ fault_code='C204'
|
|
|
+ # faultlv=2
|
|
|
+ # faultinfo='电池包容量过低'
|
|
|
+ fault_location='电芯{}'.format(cellsoh_lowindex)
|
|
|
+ fault_advice='更换容量过低的模组/电池包'
|
|
|
+ fault_reason=''
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ if soh>df_adjust_param.loc[20,'threshold']+2: #soh过低故障恢复
|
|
|
+ df_diag_ram.loc[df_diag_ram[df_diag_ram['fault_code']=='C204'].index[-1], 'end_time'] = time2
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+
|
|
|
+ if not 'C205' in list(df_diag_now['fault_code']): #当前故障中没有该故障,则判断是否发生该故障
|
|
|
+ if cellsoh_diff>df_adjust_param.loc[21,'threshold']:
|
|
|
+ fault_code='C205'
|
|
|
+ # faultlv=2
|
|
|
+ # faultinfo='电池包容量一致性差'
|
|
|
+ fault_advice='检修电池,更换容量过低的电芯或模组'
|
|
|
+ fault_location='电芯{}'.format(cellsoh_lowindex)
|
|
|
+ fault_advice='更换容量过低的模组/电池包'
|
|
|
+ fault_reason=''
|
|
|
+ df_diag_ram.loc[len(df_diag_ram)]=[time2, end_time, self.vin, self.sn, self.model, fault_code, fault_reason, fault_advice, fault_location]
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ if cellsoh_diff<df_adjust_param.loc[21,'threshold']-2:
|
|
|
+ df_diag_ram.loc[df_diag_ram[df_diag_ram['fault_code']=='C205'].index[-1], 'end_time'] = time2
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+ else:
|
|
|
+ cellsoh_diff=5
|
|
|
+
|
|
|
+ return df_diag_ram
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|