CBMSBatDiag.py 63 KB

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