CBMSBatDiag copy 2.py 61 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  1. import pandas as pd
  2. import numpy as np
  3. import bisect
  4. import datetime
  5. import BatParam
  6. class BatDiag:
  7. def __init__(self,sn,celltype,df_bms,df_volt,df_temp,df_diag,df_diag_ram, df_soh, df_sor): #参数初始化
  8. self.sn=sn
  9. self.celltype=celltype
  10. self.param=BatParam.BatParam(self.celltype)
  11. self.df_volt=df_volt
  12. self.df_temp=df_temp
  13. self.df_soh=df_soh
  14. self.df_sor=df_sor
  15. self.packcrnt=(df_volt['可充电储能装置电流(A)'].astype('float'))*self.param.PackCrntDec
  16. self.packvolt=df_volt['可充电储能装置电压(V)'].astype('float')
  17. self.bmssoc=df_bms['SOC'].map(lambda x:x.strip('%'))
  18. self.HIVLLk=df_diag['高压互锁状态']
  19. self.ISO=df_diag['绝缘']
  20. self.enmtemp=df_bms['EnmTemp']
  21. # self.bms_soh=df_volt['SOH[%]']
  22. self.bmstime= pd.to_datetime(df_volt['上报时间'], format='%Y-%m-%d %H:%M:%S')
  23. self.param.CellTempNums=int(df_temp.loc[5,'可充电储能温度探针个数'])
  24. self.df_diag_ram=df_diag_ram
  25. self.cellvolt_name=[str(x)+'.0' for x in range(1,self.param.CellVoltNums+1)]
  26. self.celltemp_name=[str(x)+'.0' for x in range(1,self.param.CellTempNums+1)]
  27. def diag(self):
  28. if self.celltype<=50:
  29. df_res=self._ncm_diag()
  30. return df_res
  31. else:
  32. df_res=self._ncm_diag()
  33. return df_res
  34. #寻找当前行数据的所有温度值...................................................................................
  35. def _celltemp_get(self,num):
  36. celltemp = list(self.df_bms.loc[num,self.celltemp_name])
  37. return celltemp
  38. #获取当前行所有电压数据............................................................................................
  39. def _cellvolt_get(self,num):
  40. cellvolt = list(self.df_bms.loc[num,self.cellvolt_name]/1000)
  41. return cellvolt
  42. #电芯温升.....................................................................................................
  43. def _celltemp_rate(self,num):
  44. celltemp_rate={}
  45. if num>0:
  46. for j in range(1, self.param.CellTempNums+1):
  47. time_now=self.bmstime[num]
  48. for k in range(1,num):
  49. if (time_now-self.bmstime[num-k]).total_seconds()>60:
  50. num_last=num-k
  51. celltemp_now=self.df_temp.loc[num,str(j)+'.0']
  52. celltemp_last=self.df_temp.loc[num_last,str(j)+'.0']
  53. time_last=self.bmstime[num_last]
  54. temp_rate=(celltemp_now-celltemp_last)*60/(time_now-time_last).total_seconds()
  55. if temp_rate>self.param.CellTempRate:
  56. celltemp_rate[j]=temp_rate
  57. break
  58. else:
  59. pass
  60. else:
  61. pass
  62. return celltemp_rate
  63. #..........................................三元电池诊断功能..................................................................
  64. def _ncm_diag(self):
  65. column_name=['start_time', 'end_time', 'product_id', 'code', 'level', 'info','advice']
  66. df_res=pd.DataFrame(columns=column_name)
  67. end_time='0000-00-00 00:00:00'
  68. ah_accum=0 #SOC卡滞初始参数
  69. as_chg=0 #过流诊断初始参数
  70. as_dis=0 #过流诊断初始参数
  71. cellvoltvalid=1
  72. voltdsc_time=0
  73. voltdsc_count=0
  74. voltfail_time=0
  75. voltfail_count=0
  76. voltloose_time=0
  77. voltloose_count=0
  78. voltstray_time=0
  79. tempstray_time=0
  80. packvoltvalid_time=0
  81. tempvalid_time=0
  82. cov_time=0
  83. cuv_time=0
  84. cdv_time=0
  85. pov_time=0
  86. puv_time=0
  87. ot_time=0
  88. ut_time=0
  89. dt_time=0
  90. sor=eval(self.df_sor.loc[0,'sor'])
  91. sor_mean=np.mean(sor)
  92. for i in range(1,len(self.df_volt)-1):
  93. df_diag_now=self.df_diag_ram[self.df_diag_ram['end_time']=='0000-00-00 00:00:00']
  94. #电压诊断功能.........................................................................................................................................
  95. if i<=1:
  96. time1=self.bmstime[i-1]
  97. time2=self.bmstime[i]
  98. cellvolt2=self._cellvolt_get(i)
  99. cellvoltmin2=min(cellvolt2)
  100. cellvoltmax2=max(cellvolt2)
  101. cellvoltmin_index2=cellvolt2.index(cellvoltmin2)
  102. cellvoltmax_index2=cellvolt2.index(cellvoltmax2)
  103. cellvolt1=self._cellvolt_get(i-1)
  104. cellvoltmin1=min(cellvolt1)
  105. cellvoltmax1=max(cellvolt1)
  106. cellvoltmin_index1=cellvolt1.index(cellvoltmin1)
  107. cellvoltmax_index1=cellvolt1.index(cellvoltmax1)
  108. cellvolt1_std=np.std(cellvolt1)
  109. cellvolt1_mean=np.mean(cellvolt1)
  110. cellvolt1_3sigma=(np.array(cellvolt1)-cellvolt1_mean)/cellvolt1_std
  111. cellvolt2_std=np.std(cellvolt2)
  112. cellvolt2_mean=np.mean(cellvolt2)
  113. cellvolt2_3sigma=(np.array(cellvolt2)-cellvolt2_mean)/cellvolt2_std
  114. celltemp1=self._celltemp_get(i-1)
  115. celltemp2=self._celltemp_get(i)
  116. celltempmin1=min(celltemp1)
  117. celltempmin2=min(celltemp2)
  118. celltempmax1=max(celltemp1)
  119. celltempmax2=max(celltemp2)
  120. celltemp1_std=np.std(celltemp1)
  121. celltemp1_mean=np.mean(celltemp1)
  122. celltemp1_3sigma=(np.array(celltemp1)-celltemp1_mean)/celltemp1_std
  123. celltemp2_std=np.std(celltemp2)
  124. celltemp2_mean=np.mean(celltemp2)
  125. celltemp2_3sigma=(np.array(celltemp2)-celltemp2_mean)/celltemp2_std
  126. else:
  127. time1=self.bmstime[i-1]
  128. time2=self.bmstime[i]
  129. cellvolt1=cellvolt2
  130. cellvoltmin1=cellvoltmin2
  131. cellvoltmax1=cellvoltmax2
  132. cellvoltmin_index1=cellvoltmin_index2
  133. cellvoltmax_index1=cellvoltmax_index2
  134. cellvolt2=self._cellvolt_get(i)
  135. cellvoltmin2=min(cellvolt2)
  136. cellvoltmax2=max(cellvolt2)
  137. cellvoltmin_index2=cellvolt2.index(cellvoltmin2)
  138. cellvoltmax_index2=cellvolt2.index(cellvoltmax2)
  139. cellvolt1_std=cellvolt2_std
  140. cellvolt1_mean=cellvolt2_mean
  141. cellvolt1_3sigma=cellvolt2_3sigma
  142. cellvolt2_std=np.std(cellvolt2)
  143. cellvolt2_mean=np.mean(cellvolt2)
  144. cellvolt2_3sigma=(np.array(cellvolt2)-cellvolt2_mean)/cellvolt2_std
  145. #电压采样断线..........................................................................................................................................
  146. if not 'C308' in list(df_diag_now['code']): #当前故障中没有该故障,则判断是否发生该故障
  147. 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): #电压断线故障进入
  148. cellvoltvalid=0
  149. voltdsc_time=voltdsc_time+(time2-time1).total_seconds()
  150. if voltdsc_time>self.param.volt_time: #持续时间
  151. time=self.bmstime[i]
  152. code='C308'
  153. faultlv=3
  154. faultinfo='电芯电压无效'
  155. reason='电芯电压采样线断线'
  156. faultlocation='电芯{}'.format([cellvoltmin_index2+1, cellvoltmax_index2+1])
  157. faultadvice='召回电池包,进行检修'
  158. influence='失去对电芯电压监测'
  159. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, reason, faultlocation, faultadvice, influence]
  160. else:
  161. pass
  162. elif (cellvoltmin2<2 and cellvoltmax2>4.5 and abs(cellvoltmax_index2-cellvoltmin_index2)==1) and (cellvoltmin1>2.5 and cellvoltmax1<4.3): #连续跳变
  163. cellvoltvalid=0
  164. voltdsc_count=voltdsc_count+1
  165. if voltdsc_count>=3:
  166. time=self.bmstime[i]
  167. code='C308'
  168. faultlv=3
  169. faultinfo='电芯电压无效'
  170. reason='电芯电压采样线断线'
  171. faultlocation='电芯{}'.format([cellvoltmin_index2+1, cellvoltmax_index2+1])
  172. faultadvice='召回电池包,进行检修'
  173. influence='失去对电芯电压监测'
  174. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, reason, faultlocation, faultadvice, influence]
  175. else:
  176. pass
  177. else:
  178. voltdsc_time=0
  179. else:
  180. cellvoltvalid=0
  181. if cellvoltmin2>2 and cellvoltmax2<4.5 and cellvoltmin1>2 and cellvoltmax1<4.5:
  182. cellvoltvalid=1
  183. time=self.bmstime[i]
  184. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C309'].index[-1], 'end_time'] = time
  185. else:
  186. pass
  187. #电压采样系统失效.............................................................................................................
  188. if not 'C309' in list(df_diag_now['code']): #当前故障中没有该故障,则判断是否发生该故障
  189. if ((cellvoltmin2<1 and cellvoltmin1<1) or (cellvoltmax2>5 and cellvoltmax1>5)):
  190. cellvoltvalid=0
  191. voltfail_time=voltfail_time+(time2-time1).total_seconds()
  192. if voltfail_time>self.param.volt_time and (not 'C308' in list(df_diag_now['code'])): #持续时间
  193. time=self.bmstime[i]
  194. code='C309'
  195. faultlv=3
  196. faultinfo='电芯电压无效'
  197. reason='电芯电压采样电路异常'
  198. faultlocation='电芯{}'.format(list(np.argwhere(np.array(cellvolt2)<1)+1)+list(np.argwhere(np.array(cellvolt2)>5)+1))
  199. faultadvice='召回电池包,进行检修'
  200. influence='失去对电芯电压监测'
  201. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, reason, faultlocation, faultadvice, influence]
  202. else:
  203. pass
  204. elif (cellvoltmin2<1 and cellvoltmin1>2.5) or (cellvoltmax2>5 and cellvoltmax1<4.5): #连续跳变
  205. cellvoltvalid=0
  206. voltfail_count=voltfail_count+1
  207. if voltfail_count>=3 and (not 'C308' in list(df_diag_now['code'])):
  208. time=self.bmstime[i]
  209. code='C309'
  210. faultlv=3
  211. faultinfo='电芯电压无效'
  212. reason='数据通讯异常'
  213. faultlocation='电芯{}'.format(list(np.argwhere(np.array(cellvolt2)<1)+1)+list(np.argwhere(np.array(cellvolt2)>5)+1))
  214. faultadvice='检修数据传输链路'
  215. influence='失去对电芯电压监测'
  216. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, reason, faultlocation, faultadvice, influence]
  217. else:
  218. pass
  219. else:
  220. voltfail_time=0
  221. else:
  222. cellvoltvalid=0
  223. if cellvoltmin2>2.5 and cellvoltmax2<4.5 and cellvoltmin1>2.5 and cellvoltmax1<4.5:
  224. cellvoltvalid=1
  225. time=self.bmstime[i]
  226. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C309'].index[-1], 'end_time'] = time
  227. else:
  228. pass
  229. #电压采样线松动.................................................................................................................
  230. if not 'C208' in list(df_diag_now['code']): #当前故障中没有该故障,则判断是否发生该故障
  231. if cellvoltmin2>2 and cellvoltmax2<4.5 and cellvoltmin1>2 and cellvoltmax1<4.5:
  232. if (min(cellvolt1_3sigma)<-3 and max(cellvolt1_3sigma)>3) and (min(cellvolt2_3sigma)<-3 and max(cellvolt2_3sigma)>3) and (cellvoltmax2-cellvoltmin2)>0.2 and (cellvoltmax1-cellvoltmin1)>0.2: #连续发生
  233. cellvoltvalid=0
  234. voltloose_time=voltloose_time+(time2-time1).total_seconds()
  235. if voltloose_time>self.param.volt_time:
  236. time=self.bmstime[i]
  237. code='C208'
  238. faultinfo='电芯电压无效'
  239. reason='电芯电压采样线松动'
  240. faultlocation='电芯{}'.format([cellvoltmin_index2+1, cellvoltmax_index2+1])
  241. faultadvice='召回电池包,进行检修'
  242. influence='失去对电芯电压监测'
  243. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, reason, faultlocation, faultadvice, influence]
  244. else:
  245. pass
  246. elif (min(cellvolt1_3sigma)>-3 and max(cellvolt1_3sigma)<3) and (min(cellvolt2_3sigma)<-3 and max(cellvolt2_3sigma)>3) and (cellvoltmax2-cellvoltmin2)>0.2 and (cellvoltmax1-cellvoltmin1)>0.2: #连续跳变
  247. cellvoltvalid=0
  248. voltloose_count=voltloose_count+1
  249. if voltloose_count>=3:
  250. time=self.bmstime[i]
  251. code='C208'
  252. faultlv=3
  253. faultinfo='电压电压无效'
  254. reason='电芯电压采样线松动'
  255. faultlocation='电芯{}'.format([cellvoltmin_index2+1, cellvoltmax_index2+1])
  256. faultadvice='召回电池包,进行检修'
  257. influence='失去对电芯电压监测'
  258. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, reason, faultlocation, faultadvice, influence]
  259. else:
  260. pass
  261. else:
  262. voltloose_time=0
  263. else:
  264. voltloose_time=0
  265. else:
  266. if(cellvoltmax2-cellvoltmin2)<0.1 and (cellvoltmax1-cellvoltmin1)<0.1:
  267. cellvoltvalid=1
  268. time=self.bmstime[i]
  269. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C208'].index[-1], 'end_time'] = time
  270. else:
  271. pass
  272. #电芯电压诊断............................................................................................................................................
  273. if cellvoltvalid==1:
  274. #电芯过压.............................................................................................................................................
  275. if not 'C401' in list(df_diag_now['code']): #当前故障中没有该故障,则判断是否发生该故障
  276. if cellvoltmax2>self.param.CellOvLv2 and cellvoltmax1>self.param.CellOvLv2: #二级过压进入
  277. cov_time=cov_time+(time2-time1).total_seconds()
  278. if cov_time>self.param.volt_time:
  279. time=self.bmstime[i]
  280. code='C401'
  281. faultlv=4
  282. faultinfo='电芯过压'
  283. faultlocation='电芯{}'.format(list(np.argwhere(np.array(cellvolt2)>self.param.CellOvLv2)+1))
  284. influence='长时间过压会导致电池析锂,存在电池安全与寿命衰减过快风险'
  285. cellocvmax=cellvoltmax2-self.packcrnt[i]*sor_mean*2 #内阻反推OCV
  286. cellsocmax=np.interp(cellocvmax,self.param.LookTab_OCV,self.param.LookTab_SOC) #ocv反查表得到SOC
  287. if self.bmssoc[i]<90 and self.packcrnt[i]>-self.param.Capacity/10 and self.packcrnt[i-1]>-self.param.Capacity/10:
  288. reason='BMS计算SOC偏低'
  289. faultadvice='优化SOC算法'
  290. elif self.bmssoc[i]<cellsocmax-10:
  291. reason='BMS计算SOC偏低'
  292. faultadvice='优化SOC算法'
  293. elif self.packcrnt[i-1]<-self.param.Capacity/2 or self.packcrnt[i]<-self.param.Capacity/2:
  294. reason='充电电流过大'
  295. faultadvice='优化充放电功率限值'
  296. else:
  297. reason='1.BMS软件策略BUG,2.继电器粘连'
  298. faultadvice='检修电池包'
  299. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, reason, faultlocation, faultadvice, influence]
  300. else:
  301. pass
  302. else:
  303. cov_time=0
  304. else: #ram当前故障中有该故障,则判断是否退出该故障
  305. if cellvoltmax2<self.param.CellOvLv1-0.05 and cellvoltmax1<self.param.CellOvLv1-0.05: #二级过压故障恢复
  306. time=self.bmstime[i]
  307. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C401'].index[-1], 'end_time'] = time
  308. else:
  309. pass
  310. #欠压诊断.................................................................................................................
  311. if not 'C202' in list(df_diag_now['code']): #当前故障中没有该故障,则判断是否发生该故障
  312. if cellvoltmin2<self.param.CellUvLv2 and cellvoltmin1<self.param.CellUvLv2: #二级欠压
  313. cuv_time=cuv_time+(time2-time1).total_seconds()
  314. if cuv_time>self.param.volt_time:
  315. time=self.bmstime[i]
  316. code='C202'
  317. faultlv=2
  318. faultinfo='电芯{}欠压'
  319. faultlocation='电芯{}'.format([cellvoltmin_index2+1, cellvoltmax_index2+1])
  320. influence='欠压可能导致电池过放,严重过放会导致负极集流体溶解,进而发生内短路风险'
  321. cellocvmin=cellvoltmin2+-self.packcrnt[i]*sor_mean*2 #内阻反推OCV
  322. cellsocmin=np.interp(cellocvmin,self.param.LookTab_OCV,self.param.LookTab_SOC) #ocv反查表得到SOC
  323. if self.bmssoc[i]>10 and self.packcrnt[i]<self.param.Capacity/10 and self.packcrnt[i-1]<self.param.Capacity/10:
  324. reason='BMS计算SOC偏高'
  325. faultadvice='优化SOC算法'
  326. elif self.bmssoc[i]>cellsocmin+10:
  327. reason='BMS计算SOC偏高'
  328. faultadvice='优化SOC算法'
  329. elif self.packcrnt[i-1]>self.param.Capacity/2 or self.packcrnt[i]>self.param.Capacity/2:
  330. reason='放电电流过大'
  331. faultadvice='优化充放电功率限值'
  332. else:
  333. reason='1.BMS软件策略BUG,2.继电器粘连'
  334. faultadvice='检修电池包'
  335. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, reason, faultlocation, faultadvice, influence]
  336. else:
  337. pass
  338. else:
  339. cuv_time=0
  340. else:
  341. if cellvoltmin2>self.param.CellUvLv1+0.1 and cellvoltmin1>self.param.CellUvLv1+0.1:
  342. time=self.bmstime[i]
  343. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C202'].index[-1], 'end_time'] = time
  344. else:
  345. pass
  346. #电芯压差大.....................................................................................................................................................
  347. if not 'C104' in list(df_diag_now['code']): #当前故障中没有该故障,则判断是否发生该故障
  348. if (cellvoltmax2-cellvoltmin2)>self.param.CellVoltDiffLv2 and (cellvoltmax1-cellvoltmin1)>self.param.CellVoltDiffLv2: #二级电芯压差
  349. cdv_time=cdv_time+(time2-time1).total_seconds()
  350. if cdv_time>self.param.volt_time:
  351. time=self.bmstime[i]
  352. code='C104'
  353. faultlv=0
  354. faultinfo='电芯电压一致性差'
  355. faultlocation='电芯{}'.format(list(np.argwhere(np.array(cellvolt2)<self.param.CellUvLv2)+1))
  356. faultadvice='更换模组'
  357. influence='容量/内阻/自放电不一致,影响电池充放电性能'
  358. if (not self.df_soh.empty) and (self.df_soh.loc[0,'cellsohmax']-self.df_soh.loc[0,'cellsohmin'])>5:
  359. reason='电芯容量一致性差'
  360. elif ('C316' in list(df_diag_now['code'])) or ('C317' in list(df_diag_now['code'])):
  361. reason='电芯内阻一致性差'
  362. elif 'C490' in list(df_diag_now['code']):
  363. reason='电芯自放电异常'
  364. elif celltempmin1<-5 and celltempmin2<-5 and abs(self.packcrnt[i-1])>self.param.Capacity/10 and abs(self.packcrnt[i])>self.param.Capacity/10:
  365. reason='电芯低温性能差'
  366. faultadvice='优化电芯低温性能'
  367. elif self.bmssoc[i-1]<3 and self.self.bmssoc[i]<3:
  368. reason='SOC过低'
  369. faultadvice='通知用户充电'
  370. else:
  371. reason='BMS均衡逻辑异常'
  372. faultadvice='优化均衡策略'
  373. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, reason, faultlocation, faultadvice, influence]
  374. else:
  375. pass
  376. else:
  377. cdv_time=0
  378. else:
  379. if (cellvoltmax2-cellvoltmin2)<self.param.CellVoltDiffLv1-0.05 and (cellvoltmax1-cellvoltmin1)<self.param.CellVoltDiffLv1-0.05: #二级欠压恢复
  380. time=self.bmstime[i]
  381. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C104'].index[-1], 'end_time'] = time
  382. else:
  383. pass
  384. #电芯电压离群.......................................................................................................................................
  385. if not 'C206' in list(df_diag_now['code']):
  386. if min(cellvolt1_3sigma)<-4 and min(cellvolt2_3sigma)<-4 and cellvolt2_mean-cellvoltmin2>0.05:
  387. cellvoltvalid=0
  388. voltstray_time=voltstray_time+(time2-time1).total_seconds()
  389. if voltstray_time>self.param.volt_time:
  390. time=self.bmstime[i]
  391. code='C206'
  392. faultlv=2
  393. faultinfo='电芯电压离群'
  394. faultlocation='电芯{}'.format([cellvoltmin_index2+1])
  395. faultadvice='更换模组'
  396. influence='容量/内阻/自放电不一致,影响电池充放电性能'
  397. if (not self.df_soh.empty) and (self.df_soh.loc[0,'cellsohmax']-self.df_soh.loc[0,'cellsohmin'])>5:
  398. reason='电芯容量一致性差'
  399. elif ('C316' in list(df_diag_now['code'])) or ('C317' in list(df_diag_now['code'])):
  400. reason='电芯内阻一致性差'
  401. elif 'C490' in list(df_diag_now['code']):
  402. reason='电芯自放电异常'
  403. elif celltempmin1<-5 and celltempmin2<-5 and abs(self.packcrnt[i-1])>self.param.Capacity/10 and abs(self.packcrnt[i])>self.param.Capacity/10:
  404. reason='电芯低温性能差'
  405. faultadvice='优化电芯低温性能'
  406. elif self.bmssoc[i-1]<3 and self.self.bmssoc[i]<3:
  407. reason='SOC过低'
  408. faultadvice='通知用户充电'
  409. else:
  410. reason='BMS均衡逻辑异常'
  411. faultadvice='优化均衡策略'
  412. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, reason, faultlocation, faultadvice, influence]
  413. else:
  414. pass
  415. elif max(cellvolt1_3sigma)>4 and max(cellvolt2_3sigma)>4 and cellvoltmax2-cellvolt2_mean>0.05: #连续发生
  416. cellvoltvalid=0
  417. voltstray_time=voltstray_time+(time2-time1).total_seconds()
  418. if voltstray_time>self.param.volt_time:
  419. time=self.bmstime[i]
  420. code='C206'
  421. faultlv=2
  422. faultinfo='电芯电压离群'
  423. faultlocation='电芯{}'.format([cellvoltmax_index2+1])
  424. faultadvice='更换模组'
  425. influence='容量/内阻/自放电不一致,影响电池充放电性能'
  426. if (not self.df_soh.empty) and (self.df_soh.loc[0,'cellsohmax']-self.df_soh.loc[0,'cellsohmin'])>5:
  427. reason='电芯容量一致性差'
  428. elif ('C316' in list(df_diag_now['code'])) or ('C317' in list(df_diag_now['code'])):
  429. reason='电芯内阻一致性差'
  430. elif 'C490' in list(df_diag_now['code']):
  431. reason='电芯自放电异常'
  432. else:
  433. reason='BMS均衡逻辑异常'
  434. faultadvice='优化均衡策略'
  435. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, reason, faultlocation, faultadvice, influence]
  436. else:
  437. pass
  438. else:
  439. voltstray_time=0
  440. else:
  441. if min(cellvolt1_3sigma)>-3 and min(cellvolt2_3sigma)>-3 and max(cellvolt1_3sigma)<3 and max(cellvolt2_3sigma)<3:
  442. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C206'].index[-1], 'end_time'] = self.bmstime[i]
  443. else:
  444. pass
  445. else:
  446. cov_time=0
  447. cuv_time=0
  448. cdv_time=0
  449. voltstray_time=0
  450. #电池包诊断.....................................................................................................................................
  451. packvolt1=self.packvolt[i-1]
  452. packvolt2=self.packvolt[i]
  453. time1=self.bmstime[i-1]
  454. time2=self.bmstime[i]
  455. if not 'C304' in list(df_diag_now['code']):
  456. if packvolt2<2*self.param.CellVoltNums or packvolt2>4.5*self.param.CellVoltNums or (cellvoltvalid==1 and abs(packvolt2-sum(cellvolt2))>10): #电池包电压有效性
  457. packvoltvalid=0
  458. packvoltvalid_time=packvoltvalid_time+(time2-time1).total_seconds()
  459. if packvoltvalid_time>self.param.volt_time:
  460. time=self.bmstime[i]
  461. code='304'
  462. faultlv=3
  463. faultinfo='电池包电压无效'
  464. reason='1.电池包电压采样电路异常,2.数据通讯异常'
  465. faultlocation='电池包电压'
  466. faultadvice='召回电池包,进行检修'
  467. influence='失去对电池包电压监测'
  468. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, reason, faultlocation, faultadvice, influence]
  469. else:
  470. pass
  471. else:
  472. packvoltvalid=1
  473. packvoltvalid_time=0
  474. else:
  475. packvoltvalid=1
  476. packvoltvalid_time=0
  477. if packvolt1>2.2*self.param.CellVoltNums or packvolt2<4.3*self.param.CellVoltNums:
  478. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C304'].index[-1], 'end_time'] = self.bmstime[i]
  479. else:
  480. pass
  481. if packvoltvalid==1:
  482. if not 'C402' in list(df_diag_now['code']): #当前故障中没有该故障,则判断是否发生该故障
  483. if packvolt1>self.param.PackVoltOvLv2 and packvolt2>self.param.PackVoltOvLv2 and self.packcrnt[i]<0: #电池包过压二级进入
  484. pov_time=pov_time+(time2-time1).total_seconds()
  485. if pov_time>self.param.volt_time:
  486. time=self.bmstime[i]
  487. code='C402'
  488. faultlv=4
  489. faultinfo='电池包过压'
  490. faultlocation='电池包电压'
  491. influence='长时间过压会导致电池析锂,存在电池安全与寿命衰减过快风险'
  492. cellocvmax=cellvoltmax2-self.packcrnt[i]*sor_mean*2 #内阻反推OCV
  493. cellsocmax=np.interp(cellocvmax,self.param.LookTab_OCV,self.param.LookTab_SOC) #ocv反查表得到SOC
  494. if self.bmssoc[i]<90 and self.packcrnt[i]>-self.param.Capacity/10 and self.packcrnt[i-1]>-self.param.Capacity/10:
  495. reason='BMS计算SOC偏低'
  496. faultadvice='优化SOC算法'
  497. elif self.bmssoc[i]<cellsocmax-10:
  498. reason='BMS计算SOC偏低'
  499. faultadvice='优化SOC算法'
  500. elif self.packcrnt[i-1]<-self.param.Capacity/2 or self.packcrnt[i]<-self.param.Capacity/2:
  501. reason='充电电流过大'
  502. faultadvice='优化充放电功率限值'
  503. else:
  504. reason='1.BMS软件策略BUG,2.继电器粘连'
  505. faultadvice='检修电池包'
  506. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, reason, faultlocation, faultadvice, influence]
  507. else:
  508. pass
  509. else:
  510. pov_time=0
  511. else:
  512. if packvolt1<self.param.PackVoltOvLv1-0.05*self.param.CellVoltNums and packvolt2<self.param.PackVoltOvLv1-0.05*self.param.CellVoltNums: #电池包过压二级恢复
  513. time=self.bmstime[i]
  514. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C402'].index[-1], 'end_time'] = time
  515. else:
  516. pass
  517. if not 'C203' in list(df_diag_now['code']): #当前故障中没有该故障,则判断是否发生该故障
  518. if packvolt1<self.param.PackVoltUvLv2 and packvolt2<self.param.PackVoltUvLv2: #电池包二级欠压进入
  519. puv_time=puv_time+(time2-time1).total_seconds()
  520. if puv_time>self.param.volt_time:
  521. time=self.bmstime[i]
  522. code='C203'
  523. faultlv=2
  524. faultinfo='电池包欠压'
  525. faultlocation='电池包电压'
  526. faultadvice='禁止放电'
  527. influence='欠压可能导致电池过放,严重过放会导致负极集流体溶解,进而发生内短路风险'
  528. cellocvmin=cellvoltmin2+-self.packcrnt[i]*sor_mean*2 #内阻反推OCV
  529. cellsocmin=np.interp(cellocvmin,self.param.LookTab_OCV,self.param.LookTab_SOC) #ocv反查表得到SOC
  530. if self.bmssoc[i]>10 and self.packcrnt[i]<self.param.Capacity/10 and self.packcrnt[i-1]<self.param.Capacity/10:
  531. reason='BMS计算SOC偏高'
  532. faultadvice='优化SOC算法'
  533. elif self.bmssoc[i]>cellsocmin+10:
  534. reason='BMS计算SOC偏高'
  535. faultadvice='优化SOC算法'
  536. elif self.packcrnt[i-1]>self.param.Capacity/2 or self.packcrnt[i]>self.param.Capacity/2:
  537. reason='放电电流过大'
  538. faultadvice='优化充放电功率限值'
  539. else:
  540. reason='1.BMS软件策略BUG,2.继电器粘连'
  541. faultadvice='检修电池包'
  542. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, reason, faultlocation, faultadvice, influence]
  543. else:
  544. pass
  545. else:
  546. puv_time=0
  547. else:
  548. if packvolt1>self.param.PackVoltUvLv1+0.1*self.param.CellVoltNums and packvolt2>self.param.PackVoltUvLv1+0.1*self.param.CellVoltNums: #电池包二级欠压恢复
  549. time=self.bmstime[i]
  550. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C203'].index[-1], 'end_time'] = time
  551. else:
  552. pass
  553. else:
  554. pov_time=0
  555. puv_time=0
  556. packvoltvalid_time=0
  557. #温度有效性判断................................................................................................................................................
  558. if not 'C301' in list(df_diag_now['code']):
  559. if celltempmax2>self.param.CellTempUpLmt or celltempmin2<self.param.CellTempLwLmt or max(np.array(celltemp2)-np.array(celltemp1))>10 or min(np.array(celltemp2)-np.array(celltemp1))<-10:
  560. celltempvalid=0
  561. tempvalid_time=tempvalid_time+(time2-time1).total_seconds()
  562. if tempvalid_time>self.param.temp_time:
  563. time=self.bmstime[i]
  564. code='301'
  565. faultlv=3
  566. faultinfo='电芯温度无效'
  567. reason='1.温度采样电路异常,2.数据通讯异常'
  568. faultlocation='温度探针{}'.format(list(np.argwhere(np.array(celltemp2)<self.param.CellTempLwLmt)+1)+list(np.argwhere(np.array(celltemp2)>self.param.CellTempUpLmt)+1))
  569. faultadvice='召回电池包,进行检修'
  570. influence='失去对电池温度监测'
  571. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, reason, faultlocation, faultadvice, influence]
  572. else:
  573. pass
  574. else:
  575. celltempvalid=1
  576. tempvalid_time=0
  577. else:
  578. celltempvalid=1
  579. tempvalid_time=0
  580. if celltempmax1<self.param.CellTempUpLmt or packvolt2<4.3*self.param.CellVoltNums:
  581. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C304'].index[-1], 'end_time'] = self.bmstime[i]
  582. else:
  583. pass
  584. if celltempvalid==1:
  585. #过温判断.............................................................................................................
  586. if not 'C302' in list(df_diag_now['code']): #当前故障中没有该故障,则判断是否发生该故障
  587. if celltempmax1>self.param.CellTempHighLv2 and celltempmax2>self.param.CellTempHighLv2: #二级高温进入
  588. ot_time=ot_time+(time2-time1).total_seconds()
  589. if ot_time>self.param.temp_time:
  590. time=self.bmstime[i]
  591. code='C302'
  592. faultlv=3
  593. faultinfo='电芯温度过高'
  594. faultlocation='温度探针{}'.format(list(np.argwhere(np.array(celltemp2)>self.param.CellTempHighLv2)+1))
  595. faultadvice='禁止充放电,并开启电池冷却功能'
  596. influence='高温下充放电,SEI膜增长加速,导致容量衰减过快,温度过高则存在热失控风险'
  597. if max(celltemp1_3sigma)>3 and max(celltemp2_3sigma)>3:
  598. reason='Busbar连接异常'
  599. faultadvice='检修电池包'
  600. elif sum(self.packcrnt[:i]*self.packvolt[:i])/(1000*(i+1))>50:
  601. reason='电池输出功率过大'
  602. faultadvice='优化电池充放电功率限值'
  603. else:
  604. reason='1.冷却液温度过高,2.冷却水泵异常,3.Busbar连接异常'
  605. faultadvice='检修电池包'
  606. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, reason, faultlocation, faultadvice, influence]
  607. else:
  608. pass
  609. else:
  610. ot_time=0
  611. else: #ram当前故障中有该故障,则判断是否退出该故障
  612. if celltempmax1<self.param.CellTempHighLv1-5 and celltempmax2<self.param.CellTempHighLv1-5: #二级高温恢复
  613. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C302'].index[-1], 'end_time'] = self.bmstime[i]
  614. else:
  615. pass
  616. #欠温判断.................................................................................................................
  617. if not 'C102' in list(df_diag_now['code']): #当前故障中没有该故障,则判断是否发生该故障
  618. if celltempmin1<self.param.CellTempLowLv2 and celltempmin2<self.param.CellTempLowLv2: #二级低温进入
  619. ut_time=ut_time+(time2-time1).total_seconds()
  620. if ut_time>self.param.temp_time:
  621. time=self.bmstime[i]
  622. code='C102'
  623. faultlv=1
  624. faultinfo='电芯温度过低'
  625. faultlocation='温度探针{}'.format(list(np.argwhere(np.array(celltemp2)<self.param.CellTempLowLv2)+1))
  626. influence='低温下充电,会导致析锂,存在电池安全与寿命衰减过快风险'
  627. if self.enmtemp[i-1]-celltempmin1>10 and self.enmtemp[i]-celltempmin2>10:
  628. reason='温度检测系统异常'
  629. faultadvice='检修电池包'
  630. elif self.bmssoc[i-1]<5 and self.bmssoc[i]<5:
  631. reason='电池包SOC过低'
  632. faultadvice='通知用户进行充电'
  633. else:
  634. reason='PTC加热系统异常'
  635. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, reason, faultlocation, faultadvice, influence]
  636. else:
  637. pass
  638. else:
  639. ut_time=0
  640. else: #ram当前故障中有该故障,则判断是否退出该故障
  641. if celltempmax1>self.param.CellTempLowLv1+2 and celltempmax2>self.param.CellTempLowLv1+2: #二级高温恢复
  642. time=self.bmstime[i]
  643. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C102'].index[-1], 'end_time'] = time
  644. else:
  645. pass
  646. #温差判断.............................................................................................................................
  647. if not 'C103' in list(df_diag_now['code']): #当前故障中没有该故障,则判断是否发生该故障
  648. if (celltempmax1-celltempmin1)>self.param.CellTempDiffLv2 and (celltempmax2-celltempmin2)>self.param.CellTempDiffLv2: #二级温差进入
  649. dt_time=dt_time+(time2-time1).total_seconds()
  650. if dt_time>self.param.temp_time:
  651. time=self.bmstime[i]
  652. code='C103'
  653. faultlv=1
  654. faultinfo='电芯温差过大'
  655. faultlocation='温度探针{}'.format([celltemp2.index(celltempmin2)+1,celltemp2.index(celltempmax2)+1])
  656. influence='存在电芯的老化速率不一致的风险'
  657. if self.enmtemp[i-1]>0 and self.enmtemp>0 and (('C316' in list(df_diag_now['code'])) or ('C317' in list(df_diag_now['code']))):
  658. reason='电芯内阻不一致'
  659. faultadvice='更换模组'
  660. elif self.enmtemp[i-1]>10 and self.enmtemp>10:
  661. reason='Busbar连接异常'
  662. faultadvice='检修电池包'
  663. elif self.enmtemp[i-1]<-10 and self.enmtemp<-10:
  664. reason='环境温度过低'
  665. faultadvice='合理优化低温充放电功率限值,并开启水泵'
  666. else:
  667. reason='电池包冷却/加热系统设计不合理'
  668. faultadvice='合理优化电池包冷却/加热系统'
  669. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, reason, faultlocation, faultadvice, influence]
  670. else:
  671. pass
  672. else:
  673. dt_time=0
  674. else: #ram当前故障中有该故障,则判断是否退出该故障
  675. if (celltempmax1-celltempmin1)<self.param.CellTempDiffLv1-2 and (celltempmax2-celltempmin2)>self.param.CellTempDiffLv1-2: #二级温差恢复
  676. time=self.bmstime[i]
  677. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C103'].index[-1], 'end_time'] = time
  678. else:
  679. pass
  680. #温度离群判断.............................................................................................................................
  681. if not 'C105' in list(df_diag_now['code']): #当前故障中没有该故障,则判断是否发生该故障
  682. if max(celltemp1_3sigma)>3 and max(celltemp2_3sigma)>3:
  683. tempstray_time=tempstray_time+(time2-time1).total_seconds()
  684. if tempstray_time>self.param.temp_time:
  685. time=self.bmstime[i]
  686. code='C105'
  687. faultlv=1
  688. faultinfo='电芯温度离群'
  689. faultlocation='温度探针{}'.format([celltemp2.index(celltempmax2)+1])
  690. influence='存在电芯的老化速率不一致的风险'
  691. if self.enmtemp[i-1]>0 and self.enmtemp>0 and (('C316' in list(df_diag_now['code'])) or ('C317' in list(df_diag_now['code']))):
  692. reason='电芯内阻不一致'
  693. faultadvice='更换模组'
  694. elif self.enmtemp[i-1]>10 and self.enmtemp>10:
  695. reason='Busbar连接异常'
  696. faultadvice='检修电池包'
  697. elif self.enmtemp[i-1]<-10 and self.enmtemp<-10:
  698. reason='环境温度过低'
  699. faultadvice='合理优化低温充放电功率限值,并开启水泵'
  700. else:
  701. reason='电池包冷却/加热系统设计不合理'
  702. faultadvice='合理优化电池包冷却/加热系统'
  703. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, reason, faultlocation, faultadvice, influence]
  704. elif min(celltemp1_3sigma)<-3 and min(celltemp2_3sigma)<-3:
  705. tempstray_time=tempstray_time+(time2-time1).total_seconds()
  706. if tempstray_time>self.param.temp_time:
  707. time=self.bmstime[i]
  708. code='C105'
  709. faultlv=1
  710. faultinfo='电芯温度离群'
  711. faultlocation='温度探针{}'.format([celltemp2.index(celltempmin2)+1])
  712. influence='存在电芯的老化速率不一致的风险'
  713. if self.enmtemp[i-1]>0 and self.enmtemp>0 and (('C316' in list(df_diag_now['code'])) or ('C317' in list(df_diag_now['code']))):
  714. reason='电芯内阻不一致'
  715. faultadvice='更换模组'
  716. elif self.enmtemp[i-1]>10 and self.enmtemp>10:
  717. reason='Busbar连接异常'
  718. faultadvice='检修电池包'
  719. elif self.enmtemp[i-1]<-10 and self.enmtemp<-10:
  720. reason='环境温度过低'
  721. faultadvice='合理优化低温充放电功率限值,并开启水泵'
  722. else:
  723. reason='电池包冷却/加热系统设计不合理'
  724. faultadvice='合理优化电池包冷却/加热系统'
  725. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, reason, faultlocation, faultadvice, influence]
  726. else:
  727. pass
  728. else:
  729. tempstray_time=0
  730. else: #ram当前故障中有该故障,则判断是否退出该故障
  731. if (celltempmax1-celltempmin1)<self.param.CellTempDiffLv1-2 and (celltempmax2-celltempmin2)>self.param.CellTempDiffLv1-2: #二级温差恢复
  732. time=self.bmstime[i]
  733. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C105'].index[-1], 'end_time'] = time
  734. else:
  735. pass
  736. else:
  737. ot_time=0
  738. ut_time=0
  739. dt_time=0
  740. tempstray_time=0
  741. #电流过流诊断.......................................................................................................................
  742. if i>0.5:
  743. step=(self.bmstime[i]-self.bmstime[i-1]).total_seconds()
  744. if step<120 and self.packcrnt[i]>self.param.PackDisOc and self.packcrnt[i-1]>self.param.PackDisOc:
  745. as_dis=as_dis+(self.packcrnt[i]-self.param.PackDisOc)*step #ah累计
  746. elif step<120 and self.packcrnt[i]<self.param.PackChgOc and self.packcrnt[i-1]<self.param.PackChgOc:
  747. as_chg=as_chg+(self.param.PackDisOc-self.packcrnt[i])*step #ah累计
  748. else:
  749. as_dis=0
  750. as_chg=0
  751. if not 'C306' in list(df_diag_now['code']): #当前故障中没有该故障,则判断是否发生该故障
  752. if as_dis>100:
  753. time=self.bmstime[i]
  754. code='C306'
  755. faultlv=3
  756. faultinfo='电池放电过流'
  757. faultlocation='电池包'
  758. influence='长时间过流会导致电池欠压及温升过快'
  759. if cellvoltmin1<self.param.CellUvLv2 and cellvoltmin2<self.param.CellUvLv2:
  760. reason='BMS控制策略异常'
  761. faultadvice='优化BMS控制策略'
  762. else:
  763. reason='1.充电器异常,2.继电器粘连'
  764. faultadvice='停止放电'
  765. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, reason, faultlocation, faultadvice, influence]
  766. else:
  767. pass
  768. else:
  769. if self.packcrnt[i]<self.param.PackDisOc-10:
  770. time=self.bmstime[i]
  771. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C306'].index[-1], 'end_time'] = time
  772. else:
  773. pass
  774. if not 'C305' in list(df_diag_now['code']): #当前故障中没有该故障,则判断是否发生该故障
  775. if as_chg>100:
  776. time=self.bmstime[i]
  777. code='C305'
  778. faultlv=3
  779. faultinfo='电池充电过流'
  780. faultlocation='电池包'
  781. influence='过流会导致电池析锂,存在电池安全与寿命衰减过快风险'
  782. if cellvoltmax1>self.param.CellOvLv2 and cellvoltmax2>self.param.CellOvLv2:
  783. reason='BMS控制策略异常'
  784. faultadvice='优化BMS控制策略'
  785. else:
  786. reason='1.充电器异常,2.继电器粘连'
  787. faultadvice='停止放电'
  788. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, reason, faultlocation, faultadvice, influence]
  789. else:
  790. pass
  791. else:
  792. if self.packcrnt[i]>self.param.PackChgOc+10:
  793. time=self.bmstime[i]
  794. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C305'].index[-1], 'end_time'] = time
  795. else:
  796. pass
  797. #SOC卡滞、跳变诊断................................................................................................
  798. if i<2:
  799. bmssoc_st=float(self.bms_soc[i])
  800. bmssoc_last=float(self.bms_soc[i])
  801. bmssoc_now=float(self.bms_soc[i])
  802. else:
  803. step=(self.bmstime[i]-self.bmstime[i-1]).total_seconds()
  804. if step<120:
  805. ah_accum=ah_accum-self.packcrnt[i]*step/3600 #ah累计
  806. else:
  807. pass
  808. #SOC卡滞............................................................................................................
  809. if abs(ah_accum)>self.param.Capacity*0.1:
  810. bmssoc_now=float(self.bms_soc[i])
  811. if not 'C106' in list(df_diag_now['code']): #当前故障中没有该故障,则判断是否发生该故障
  812. if abs(bmssoc_now-bmssoc_st)<self.param.SocClamp: #SOC卡滞故障进入
  813. time=self.bmstime[i]
  814. code='C106'
  815. faultlv=0
  816. faultinfo='电池SOC卡滞'
  817. faultadvice='技术介入诊断,检修电池BMS软件'
  818. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  819. else:
  820. pass
  821. else:
  822. if abs(bmssoc_now-bmssoc_st)>self.param.SocClamp: #SOC卡滞故障退出
  823. time=self.bmstime[i]
  824. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C106'].index[-1], 'end_time'] = time
  825. else:
  826. pass
  827. bmssoc_st=bmssoc_now
  828. ah_accum=0
  829. else:
  830. pass
  831. #SOC跳变....................................................................................................................
  832. bmssoc_last=float(self.bms_soc[i-1])
  833. bmssoc_now=float(self.bms_soc[i])
  834. if not 'C107' in list(df_diag_now['code']): #当前故障中没有该故障,则判断是否发生该故障
  835. if step<70 and abs(bmssoc_now-bmssoc_last)>self.param.SocJump: #SOC跳变进入
  836. time=self.bmstime[i]
  837. code='C107'
  838. faultlv=0
  839. faultinfo='电池SOC跳变{}%'.format(bmssoc_now-bmssoc_last)
  840. faultadvice='技术介入诊断,检修电池BMS软件'
  841. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  842. else:
  843. pass
  844. else:
  845. if abs(bmssoc_now-bmssoc_st)<self.param.SocJump: #SOC跳变故障退出
  846. time=self.bmstime[i]
  847. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C107'].index[-1], 'end_time'] = time
  848. else:
  849. pass
  850. #绝缘故障检测
  851. if not 'C315' in list(df_diag_now['code']): #当前故障中没有该故障,则判断是否发生该故障
  852. if self.ISO[i]=='异常' and self.ISO[i-1]=='异常':
  853. time=self.bmstime[i]
  854. code='C315'
  855. faultlv=3
  856. faultinfo='绝缘异常'
  857. faultadvice='通知技术人员介入诊断'
  858. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  859. else:
  860. pass
  861. else:
  862. if self.ISO[i]=='正常' and self.ISO[i-1]=='正常':
  863. time=self.bmstime[i]
  864. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C315'].index[-1], 'end_time'] = time
  865. else:
  866. pass
  867. #高压互锁检测
  868. if not 'C209' in list(df_diag_now['code']): #当前故障中没有该故障,则判断是否发生该故障
  869. if self.HIVLLk[i]=='异常' and self.HIVLLk[i-1]=='异常':
  870. time=self.bmstime[i]
  871. code='C209'
  872. faultlv=2
  873. faultinfo='高压互锁异常'
  874. faultadvice='通知技术人员介入诊断'
  875. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  876. else:
  877. pass
  878. else:
  879. if self.HIVLLk[i]=='正常' and self.HIVLLk[i-1]=='正常':
  880. time=self.bmstime[i]
  881. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C209'].index[-1], 'end_time'] = time
  882. else:
  883. pass
  884. # #SOC一致性故障报警..........................................................................................................
  885. # if not self.df_uniform.empty:
  886. # cellsoc_diff=self.df_uniform.loc[0,'cellsoc_diff']
  887. # if not 'C201' in list(df_diag_now['code']): #当前故障中没有该故障,则判断是否发生该故障
  888. # if cellsoc_diff>self.param.SocDiff: #SOC一致性差故障进入
  889. # time=self.bmstime[0]
  890. # code='C201'
  891. # faultlv=0
  892. # faultinfo='电芯{}和{}SOC差过大:{}'.format(int(self.df_uniform.loc[0,'cellmin_num']),int(self.df_uniform.loc[0,'cellmax_num']),cellsoc_diff)
  893. # faultadvice='技术介入诊断'
  894. # self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  895. # else:
  896. # pass
  897. # else:
  898. # if cellsoc_diff<self.param.SocDiff: #SOC一致性差故障恢复
  899. # time=self.bmstime[0]
  900. # self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C201'].index[-1], 'end_time'] = time
  901. # else:
  902. # cellsoc_diff=3
  903. # #容量过低和一致性故障报警................................................................................................
  904. # if not self.df_soh.empty:
  905. # soh=self.df_soh.loc[0,'soh']
  906. # cellsoh=eval(self.df_soh.loc[0,'cellsoh'])
  907. # cellsoh=np.array(cellsoh)
  908. # cellsoh_lowindex=np.argwhere(cellsoh<self.param.SohLow)
  909. # cellsoh_lowindex=cellsoh_lowindex+1
  910. # if self.celltype==1 or self.celltype==2 or self.celltype==3 or self.celltype==4:
  911. # cellsoh_diff=np.max(cellsoh)-np.min(cellsoh)
  912. # if not 'C204' in list(df_diag_now['code']): #当前故障中没有该故障,则判断是否发生该故障
  913. # if soh<self.param.SohLow: #soh过低故障进入
  914. # time=self.bmstime[0]
  915. # code='C204'
  916. # faultlv=2
  917. # faultinfo='电池包容量过低:电芯{}'.format(cellsoh_lowindex)
  918. # faultadvice='检修电池,更换容量过低的电芯或模组'
  919. # self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  920. # else:
  921. # pass
  922. # else:
  923. # if soh>self.param.SohLow+2: #soh过低故障恢复
  924. # time=self.bmstime[0]
  925. # self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C204'].index[-1], 'end_time'] = time
  926. # else:
  927. # pass
  928. # if not 'C205' in list(df_diag_now['code']): #当前故障中没有该故障,则判断是否发生该故障
  929. # if cellsoh_diff>self.param.SohDiff:
  930. # time=self.bmstime[0]
  931. # code='C205'
  932. # faultlv=2
  933. # faultinfo='电池包容量一致性差:电芯{}'.format(cellsoh_lowindex)
  934. # faultadvice='检修电池,更换容量过低的电芯或模组'
  935. # self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  936. # else:
  937. # pass
  938. # else:
  939. # if cellsoh_diff<self.param.SohDiff-2:
  940. # time=self.bmstime[0]
  941. # self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C205'].index[-1], 'end_time'] = time
  942. # else:
  943. # pass
  944. # else:
  945. # pass
  946. # else:
  947. # cellsoh_diff=5
  948. return self.df_diag_ram