CBMSBatDiag.py 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. import pandas as pd
  2. import numpy as np
  3. import datetime
  4. from LIB.MIDDLE.CellStateEstimation.Common.V1_0_1 import BatParam
  5. class BatDiag:
  6. def __init__(self,sn,celltype,df_bms,df_diag_ram_sn,df_bms_ram_sn,df_soh,df_uniform): #参数初始化
  7. self.sn=sn
  8. self.celltype=celltype
  9. self.param=BatParam.BatParam(celltype)
  10. self.df_bms=df_bms
  11. self.df_uniform=df_uniform
  12. self.df_soh=df_soh
  13. self.df_bms_ram=df_bms_ram_sn.copy()
  14. self.df_diag_ram=df_diag_ram_sn.copy()
  15. df_bms['时间戳']=pd.to_datetime(df_bms['时间戳'], format='%Y-%m-%d %H:%M:%S')
  16. if not df_bms_ram_sn.empty:
  17. self.df_bms=self.df_bms[self.df_bms['时间戳'] > df_bms_ram_sn.iloc[-1]['time']] #滤除原始数据中的重复数据
  18. self.df_bms.reset_index(inplace=True,drop=True) #重置索引
  19. self.packcrnt=df_bms['总电流[A]']*self.param.PackCrntDec
  20. self.packvolt=df_bms['总电压[V]']
  21. self.bmstime= df_bms['时间戳']
  22. self.bms_soc=df_bms['SOC[%]']
  23. self.cellvolt_name=['单体电压'+str(x) for x in range(1,self.param.CellVoltNums+1)]
  24. # othertemp=['其他温度'+str(x) for x in range(1,self.param.OtherTempNums+1)]
  25. self.celltemp_name=['单体温度'+str(x) for x in range(1,self.param.CellTempNums+1)]
  26. # self.celltemp_name=celltemp+othertemp
  27. def diag(self):
  28. if self.celltype<=50:
  29. df_res1,df_res2=self._bat_diag()
  30. return df_res1,df_res2
  31. else:
  32. df_res1,df_res2=self._bat_diag()
  33. return df_res1,df_res2
  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 _bat_diag(self):
  44. column_name=['start_time', 'end_time', 'product_id', 'code', 'level', 'info','advice']
  45. df_res=pd.DataFrame(columns=column_name)
  46. end_time='0000-00-00 00:00:00'
  47. ah_accum=0 #SOC卡滞初始参数
  48. as_chg=0 #过流诊断初始参数
  49. as_dis=0 #过流诊断初始参数
  50. cellvoltvalid=1
  51. voltdsc_time=0
  52. voltdsc_count=0
  53. voltfail_time=0
  54. voltfail_count=0
  55. voltloose_time=0
  56. voltloose_count=0
  57. voltover_time=0
  58. voltunder_time=0
  59. cov_time=0
  60. cuv_time=0
  61. cdv_time=0
  62. pov_time=0
  63. puv_time=0
  64. ot_time=0
  65. ut_time=0
  66. dt_time=0
  67. for i in range(len(self.df_bms)):
  68. #电压诊断功能.........................................................................................................................................
  69. if i<1:
  70. cellvolt2=self._cellvolt_get(i)
  71. cellvoltmin2=min(cellvolt2)
  72. cellvoltmax2=max(cellvolt2)
  73. cellvoltmin_index2=cellvolt2.index(cellvoltmin2)
  74. cellvoltmax_index2=cellvolt2.index(cellvoltmax2)
  75. if not self.df_bms_ram.empty:
  76. time1=self.df_bms_ram.iloc[-1]['time']
  77. time2=self.bmstime[i]
  78. cellvolt1=self.df_bms_ram.iloc[-1]['cellvolt']
  79. cellvoltmin1=min(cellvolt1)
  80. cellvoltmax1=max(cellvolt1)
  81. cellvoltmin_index1=cellvolt1.index(cellvoltmin1)
  82. cellvoltmax_index1=cellvolt1.index(cellvoltmax1)
  83. else:
  84. cellvolt1=cellvolt2
  85. time1=self.bmstime[i]
  86. time2=self.bmstime[i]
  87. cellvoltmin1=cellvoltmin2
  88. cellvoltmax1=cellvoltmax2
  89. cellvoltmin_index1=cellvoltmin_index2
  90. cellvoltmax_index1=cellvoltmax_index2
  91. else:
  92. time1=self.bmstime[i-1]
  93. time2=self.bmstime[i]
  94. cellvolt2=self._cellvolt_get(i)
  95. cellvoltmin2=min(cellvolt2)
  96. cellvoltmax2=max(cellvolt2)
  97. cellvoltmin_index2=cellvolt2.index(cellvoltmin2)
  98. cellvoltmax_index2=cellvolt2.index(cellvoltmax2)
  99. cellvolt1=self._cellvolt_get(i-1)
  100. cellvoltmin1=min(cellvolt1)
  101. cellvoltmax1=max(cellvolt1)
  102. cellvoltmin_index1=cellvolt1.index(cellvoltmin1)
  103. cellvoltmax_index1=cellvolt1.index(cellvoltmax1)
  104. #电压采样断线..........................................................................................................................................
  105. if not 'C308' in list(self.df_diag_ram['code']): #当前故障中没有该故障,则判断是否发生该故障
  106. 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): #电压断线故障进入
  107. cellvoltvalid=0
  108. voltdsc_time=voltdsc_time+(time2-time1).total_seconds()
  109. if voltdsc_time>self.param.volt_time: #持续时间
  110. time=self.bmstime[i]
  111. code='C308'
  112. faultlv=3
  113. faultinfo='电芯{}和{}电压采样断线'.format(cellvoltmin_index2+1, cellvoltmax_index2+1)
  114. faultadvice='通知用户更换电池,电池返厂维修'
  115. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  116. else:
  117. pass
  118. elif (cellvoltmin2<2 and cellvoltmax2>4.5 and abs(cellvoltmax_index2-cellvoltmin_index2)==1) and (cellvoltmin1>2.5 and cellvoltmax1<4.3): #连续跳变
  119. cellvoltvalid=0
  120. voltdsc_count=voltdsc_count+1
  121. if voltdsc_count>=3:
  122. time=self.bmstime[i]
  123. code='C308'
  124. faultlv=3
  125. faultinfo='电芯{}和{}电压采样断线'.format(cellvoltmin_index2+1, cellvoltmax_index2+1)
  126. faultadvice='通知用户更换电池,电池返厂维修'
  127. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  128. else:
  129. pass
  130. else:
  131. voltdsc_time=0
  132. else:
  133. cellvoltvalid=0
  134. if cellvoltmin2>2 and cellvoltmax2<4.5 and cellvoltmin1>2 and cellvoltmax1<4.5:
  135. cellvoltvalid=1
  136. time=self.bmstime[i]
  137. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C308'].index, 'end_time'] = time
  138. else:
  139. pass
  140. #电压采样系统失效.............................................................................................................
  141. if not 'C309' in list(self.df_diag_ram['code']): #当前故障中没有该故障,则判断是否发生该故障
  142. if (cellvoltmin2<1 and cellvoltmin1<1) or (cellvoltmax2>5 and cellvoltmax1>5):
  143. cellvoltvalid=0
  144. voltfail_time=voltfail_time+(time2-time1).total_seconds()
  145. if voltfail_time>self.param.volt_time: #持续时间
  146. time=self.bmstime[i]
  147. code='C309'
  148. faultlv=3
  149. faultinfo='电芯电压采样系统失效'
  150. faultadvice='通知用户更换电池,电池返厂维修'
  151. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  152. else:
  153. pass
  154. elif (cellvoltmin2<1 and cellvoltmin1>2.5) or (cellvoltmax2>5 and cellvoltmax1<4.5): #连续跳变
  155. cellvoltvalid=0
  156. voltfail_count=voltfail_count+1
  157. if voltfail_count>=3:
  158. time=self.bmstime[i]
  159. code='C309'
  160. faultlv=3
  161. faultinfo='电芯电压采样系统失效'
  162. faultadvice='通知用户更换电池,电池返厂维修'
  163. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  164. else:
  165. pass
  166. else:
  167. voltfail_time=0
  168. else:
  169. cellvoltvalid=0
  170. if cellvoltmin2>2.5 and cellvoltmax2<4.5 and cellvoltmin1>2.5 and cellvoltmax1<4.5:
  171. cellvoltvalid=1
  172. time=self.bmstime[i]
  173. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C309'].index, 'end_time'] = time
  174. else:
  175. pass
  176. #电压采样线松动.................................................................................................................
  177. if not 'C208' in list(self.df_diag_ram['code']): #当前故障中没有该故障,则判断是否发生该故障
  178. if cellvoltmin2>2 and cellvoltmax2<4.5 and cellvoltmin1>2 and cellvoltmax1<4.5:
  179. cellvolt1_std=np.std(cellvolt1)
  180. cellvolt1_mean=np.mean(cellvolt1)
  181. cellvolt1_3sigma=(np.array(cellvolt1)-cellvolt1_mean)/cellvolt1_std
  182. cellvolt2_std=np.std(cellvolt2)
  183. cellvolt2_mean=np.mean(cellvolt2)
  184. cellvolt2_3sigma=(np.array(cellvolt2)-cellvolt2_mean)/cellvolt2_std
  185. if (min(cellvolt1_3sigma)<-3 and max(cellvolt1_3sigma)>3) and (min(cellvolt2_3sigma)<-3 and max(cellvolt2_3sigma)>3): #连续发生
  186. cellvoltvalid=0
  187. voltloose_time=voltloose_time+(time2-time1).total_seconds()
  188. if voltloose_time>self.param.volt_time:
  189. time=self.bmstime[i]
  190. code='C208'
  191. faultlv=3
  192. faultinfo='电芯电压{}和{}采样松动'.format(cellvoltmin_index2+1, cellvoltmax_index2+1)
  193. faultadvice='通知技术人员介入诊断'
  194. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  195. else:
  196. pass
  197. elif (min(cellvolt1_3sigma)>-3 and max(cellvolt1_3sigma)<3) and (min(cellvolt2_3sigma)<-3 and max(cellvolt2_3sigma)>3): #连续跳变
  198. cellvoltvalid=0
  199. voltloose_count=voltloose_count+1
  200. if voltloose_count>=3:
  201. time=self.bmstime[i]
  202. code='C208'
  203. faultlv=3
  204. faultinfo='电芯电压{}和{}采样松动'.format(cellvoltmin_index2+1, cellvoltmax_index2+1)
  205. faultadvice='通知技术人员介入诊断'
  206. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  207. else:
  208. pass
  209. else:
  210. voltloose_time=0
  211. else:
  212. voltloose_time=0
  213. else:
  214. cellvoltvalid=0
  215. cellvolt1_std=np.std(cellvolt1)
  216. cellvolt1_mean=np.mean(cellvolt1)
  217. cellvolt1_3sigma=(np.array(cellvolt1)-cellvolt1_mean)/cellvolt1_std
  218. cellvolt2_std=np.std(cellvolt2)
  219. cellvolt2_mean=np.mean(cellvolt2)
  220. cellvolt2_3sigma=(np.array(cellvolt2)-cellvolt2_mean)/cellvolt2_std
  221. if(min(cellvolt1_3sigma)>-3 or max(cellvolt1_3sigma)<3) and (min(cellvolt2_3sigma)>-3 or max(cellvolt2_3sigma)<3):
  222. cellvoltvalid=1
  223. time=self.bmstime[i]
  224. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C208'].index, 'end_time'] = time
  225. else:
  226. pass
  227. if cellvoltvalid==1:
  228. #继电器粘连.............................................................................................................................................
  229. if not 'C310' in list(self.df_diag_ram['code']): #当前故障中没有该故障,则判断是否发生该故障
  230. if cellvoltmax2>self.param.CellOvLv2 and cellvoltmax1>self.param.CellOvLv2 and self.packcrnt[i]<0:
  231. voltover_time=voltover_time+(time2-time1).total_seconds()
  232. if voltover_time>self.param.volt_time:
  233. time=self.bmstime[i]
  234. code='C310'
  235. faultlv=3
  236. faultinfo='充电继电器粘连'
  237. faultadvice='通知技术人员介入诊断'
  238. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  239. else:
  240. pass
  241. else:
  242. voltover_time=0
  243. else:
  244. if cellvoltmax2<self.param.CellOvLv2-0.05 and cellvoltmax1<self.param.CellOvLv2-0.05:
  245. time=self.bmstime[i]
  246. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C310'].index, 'end_time'] = time
  247. else:
  248. pass
  249. if not 'C311' in list(self.df_diag_ram['code']): #当前故障中没有该故障,则判断是否发生该故障
  250. if cellvoltmin2<self.param.CellUvLv2 and cellvoltmin1<self.param.CellUvLv2 and self.packcrnt[i]>0:
  251. voltunder_time=voltunder_time+(time2-time1).total_seconds()
  252. if voltunder_time>self.param.volt_time:
  253. time=self.bmstime[i]
  254. code='C311'
  255. faultlv=3
  256. faultinfo='放电继电器粘连'
  257. faultadvice='通知技术人员介入诊断'
  258. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  259. else:
  260. pass
  261. else:
  262. voltunder_time=0
  263. else:
  264. if cellvoltmin2>self.param.CellUvLv2+0.05 and cellvoltmin1>self.param.CellOvLv2+0.05:
  265. time=self.bmstime[i]
  266. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C311'].index, 'end_time'] = time
  267. else:
  268. pass
  269. #电芯过压.............................................................................................................................................
  270. if not 'C501' in list(self.df_diag_ram['code']): #当前故障中没有该故障,则判断是否发生该故障
  271. if cellvoltmax2>self.param.CellOvLv2 and cellvoltmax1>self.param.CellOvLv2 and self.packcrnt[i]<0: #二级过压进入
  272. cov_time=cov_time+(time2-time1).total_seconds()
  273. if cov_time>self.param.volt_time:
  274. time=self.bmstime[i]
  275. code='C501'
  276. faultlv=5
  277. faultinfo='电芯{}过压'.format(cellvolt1.index(cellvoltmax1)+1)
  278. faultadvice='联系用户立即停止充电,并通知技术运维人员'
  279. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  280. else:
  281. pass
  282. else:
  283. cov_time=0
  284. else: #ram当前故障中有该故障,则判断是否退出该故障
  285. if cellvoltmax2<self.param.CellOvLv1-0.05 and cellvoltmax1<self.param.CellOvLv1-0.05: #二级过压故障恢复
  286. time=self.bmstime[i]
  287. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C501'].index, 'end_time'] = time
  288. else:
  289. pass
  290. #欠压诊断.................................................................................................................
  291. if not 'C202' in list(self.df_diag_ram['code']): #当前故障中没有该故障,则判断是否发生该故障
  292. if cellvoltmin2<self.param.CellUvLv2 and cellvoltmin1<self.param.CellUvLv2: #二级欠压
  293. cuv_time=cuv_time+(time2-time1).total_seconds()
  294. if cuv_time>self.param.volt_time:
  295. time=self.bmstime[i]
  296. code='C202'
  297. faultlv=2
  298. faultinfo='电芯{}欠压'.format(cellvolt1.index(cellvoltmin1)+1)
  299. faultadvice='联系用户询问用车场景,技术介入诊断'
  300. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  301. else:
  302. pass
  303. else:
  304. cuv_time=0
  305. else:
  306. if cellvoltmin2>self.param.CellUvLv1+0.1 and cellvoltmin1>self.param.CellUvLv1+0.1:
  307. time=self.bmstime[i]
  308. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C202'].index, 'end_time'] = time
  309. else:
  310. pass
  311. #电芯压差大.....................................................................................................................................................
  312. if not 'C104' in list(self.df_diag_ram['code']): #当前故障中没有该故障,则判断是否发生该故障
  313. if (cellvoltmax2-cellvoltmin2)>self.param.CellVoltDiffLv2 and (cellvoltmax1-cellvoltmin1)>self.param.CellVoltDiffLv2: #二级电芯压差
  314. cdv_time=cdv_time+(time2-time1).total_seconds()
  315. if cdv_time>self.param.volt_time:
  316. time=self.bmstime[i]
  317. code='C104'
  318. faultlv=0
  319. faultinfo='电芯{}和{}压差大'.format(cellvolt1.index(cellvoltmax1)+1,cellvolt1.index(cellvoltmin1)+1)
  320. faultadvice='技术介入诊断'
  321. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  322. else:
  323. pass
  324. else:
  325. cdv_time=0
  326. else:
  327. if (cellvoltmax2-cellvoltmin2)<self.param.CellVoltDiffLv1-0.05 and (cellvoltmax1-cellvoltmin1)<self.param.CellVoltDiffLv1-0.05: #二级欠压恢复
  328. time=self.bmstime[i]
  329. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C104'].index, 'end_time'] = time
  330. else:
  331. pass
  332. else:
  333. cov_time=0
  334. cuv_time=0
  335. cdv_time=0
  336. #电池包诊断.....................................................................................................................................
  337. if i<1:
  338. if not self.df_bms_ram.empty:
  339. packvolt1=self.df_bms_ram.iloc[-1]['packvolt']
  340. packvolt2=self.packvolt[i]
  341. time1=self.df_bms_ram.iloc[-1]['time']
  342. time2=self.bmstime[i]
  343. else:
  344. packvolt1=self.packvolt[i]
  345. packvolt2=self.packvolt[i]
  346. time1=self.bmstime[i]
  347. time2=self.bmstime[i]
  348. else:
  349. packvolt1=self.packvolt[i-1]
  350. packvolt2=self.packvolt[i]
  351. time1=self.bmstime[i-1]
  352. time2=self.bmstime[i]
  353. if packvolt1<2*self.param.CellVoltNums or packvolt2>4.5*self.param.CellVoltNums: #电池包电压有效性
  354. packvoltvalid=0
  355. else:
  356. packvoltvalid=1
  357. if packvoltvalid==1:
  358. if not 'C502' in list(self.df_diag_ram['code']): #当前故障中没有该故障,则判断是否发生该故障
  359. if packvolt1>self.param.PackVoltOvLv2 and packvolt2>self.param.PackVoltOvLv2 and self.packcrnt[i]<0: #电池包过压二级进入
  360. pov_time=pov_time+(time2-time1).total_seconds()
  361. if pov_time>self.param.volt_time:
  362. time=self.bmstime[i]
  363. code='C502'
  364. faultlv=5
  365. faultinfo='电池包过压'
  366. faultadvice='联系用户立即停止充电,并通知技术运维人员'
  367. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  368. else:
  369. pass
  370. else:
  371. pov_time=0
  372. else:
  373. if packvolt1<self.param.PackVoltOvLv1-0.05*self.param.CellVoltNums and packvolt2<self.param.PackVoltOvLv1-0.05*self.param.CellVoltNums: #电池包过压二级恢复
  374. time=self.bmstime[i]
  375. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C502'].index, 'end_time'] = time
  376. else:
  377. pass
  378. if not 'C203' in list(self.df_diag_ram['code']): #当前故障中没有该故障,则判断是否发生该故障
  379. if packvolt1<self.param.PackVoltUvLv2 and packvolt2<self.param.PackVoltUvLv2: #电池包二级欠压进入
  380. puv_time=puv_time+(time2-time1).total_seconds()
  381. if puv_time>self.param.volt_time:
  382. time=self.bmstime[i]
  383. code='C203'
  384. faultlv=2
  385. faultinfo='电池包欠压'
  386. faultadvice='联系用户询问用车场景,技术介入诊断'
  387. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  388. else:
  389. pass
  390. else:
  391. puv_time=0
  392. else:
  393. if packvolt1>self.param.PackVoltUvLv1+0.1*self.param.CellVoltNums and packvolt2>self.param.PackVoltUvLv1+0.1*self.param.CellVoltNums: #电池包二级欠压恢复
  394. time=self.bmstime[i]
  395. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C203'].index, 'end_time'] = time
  396. else:
  397. pass
  398. else:
  399. pov_time=0
  400. puv_time=0
  401. #温度诊断功能.............................................................................................................
  402. if i<1:
  403. if not self.df_bms_ram.empty:
  404. celltemp1=self.df_bms_ram.iloc[-1]['celltemp']
  405. celltemp2=self._celltemp_get(i)
  406. time1=self.df_bms_ram.iloc[-1]['time']
  407. time2=self.bmstime[i]
  408. else:
  409. celltemp1=self._celltemp_get(i)
  410. celltemp2=self._celltemp_get(i)
  411. time1=self.bmstime[i]
  412. time2=self.bmstime[i]
  413. else:
  414. celltemp1=self._celltemp_get(i-1)
  415. celltemp2=self._celltemp_get(i)
  416. time1=self.bmstime[i-1]
  417. time2=self.bmstime[i]
  418. celltempmin1=min(celltemp1)
  419. celltempmin2=min(celltemp2)
  420. celltempmax1=max(celltemp1)
  421. celltempmax2=max(celltemp2)
  422. #温度有效性判断..........................................................................
  423. if celltempmax1>self.param.CellTempUpLmt or celltempmin1<self.param.CellTempLwLmt:
  424. celltempvalid=0
  425. else:
  426. celltempvalid=1
  427. if celltempvalid==1:
  428. #过温判断.............................................................................................................
  429. if not 'C302' in list(self.df_diag_ram['code']): #当前故障中没有该故障,则判断是否发生该故障
  430. if celltempmax1>self.param.CellTempHighLv2 and celltempmax2>self.param.CellTempHighLv2: #二级高温进入
  431. ot_time=ot_time+(time2-time1).total_seconds()
  432. if ot_time>self.param.temp_time:
  433. time=self.bmstime[i]
  434. code='C302'
  435. faultlv=3
  436. faultinfo='温度{}高温'.format(celltemp1.index(celltempmax1)+1)
  437. faultadvice='技术介入诊断'
  438. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  439. else:
  440. pass
  441. else:
  442. ot_time=0
  443. else: #ram当前故障中有该故障,则判断是否退出该故障
  444. if celltempmax1<self.param.CellTempHighLv1-5 and celltempmax2<self.param.CellTempHighLv1-5: #二级高温恢复
  445. time=self.bmstime[i]
  446. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C302'].index, 'end_time'] = time
  447. else:
  448. pass
  449. #欠温判断.................................................................................................................
  450. if not 'C102' in list(self.df_diag_ram['code']): #当前故障中没有该故障,则判断是否发生该故障
  451. if celltempmin1<self.param.CellTempLowLv2 and celltempmin2<self.param.CellTempLowLv2: #二级低温进入
  452. ut_time=ut_time+(time2-time1).total_seconds()
  453. if ut_time>self.param.temp_time:
  454. time=self.bmstime[i]
  455. code='C102'
  456. faultlv=1
  457. faultinfo='温度{}低温'.format(celltemp1.index(celltempmin1)+1)
  458. faultadvice='技术介入诊断'
  459. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  460. else:
  461. pass
  462. else:
  463. ut_time=0
  464. else: #ram当前故障中有该故障,则判断是否退出该故障
  465. if celltempmax1>self.param.CellTempLowLv1+2 and celltempmax2>self.param.CellTempLowLv1+2: #二级高温恢复
  466. time=self.bmstime[i]
  467. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C102'].index, 'end_time'] = time
  468. else:
  469. pass
  470. #温差判断.............................................................................................................................
  471. if not 'C103' in list(self.df_diag_ram['code']): #当前故障中没有该故障,则判断是否发生该故障
  472. if (celltempmax1-celltempmin1)>self.param.CellTempDiffLv2 and (celltempmax2-celltempmin2)>self.param.CellTempDiffLv2: #二级温差进入
  473. dt_time=dt_time+(time2-time1).total_seconds()
  474. if dt_time>self.param.temp_time:
  475. time=self.bmstime[i]
  476. code='C103'
  477. faultlv=1
  478. faultinfo='温度{}和{}温差大'.format(celltemp1.index(celltempmax1)+1,celltemp1.index(celltempmin1)+1)
  479. faultadvice='技术介入诊断'
  480. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  481. else:
  482. pass
  483. else:
  484. dt_time=0
  485. else: #ram当前故障中有该故障,则判断是否退出该故障
  486. if (celltempmax1-celltempmin1)<self.param.CellTempDiffLv1-2 and (celltempmax2-celltempmin2)>self.param.CellTempDiffLv1-2: #二级温差恢复
  487. time=self.bmstime[i]
  488. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C103'].index, 'end_time'] = time
  489. else:
  490. pass
  491. else:
  492. ot_time=0
  493. ut_time=0
  494. dt_time=0
  495. #电流过流诊断.......................................................................................................................
  496. if i>0.5:
  497. step=(self.bmstime[i]-self.bmstime[i-1]).total_seconds()
  498. if step<120 and self.packcrnt[i]>self.param.PackDisOc and self.packcrnt[i-1]>self.param.PackDisOc:
  499. as_dis=as_dis+(self.packcrnt[i]-self.param.PackDisOc)*step #ah累计
  500. elif step<120 and self.packcrnt[i]<self.param.PackChgOc and self.packcrnt[i-1]<self.param.PackChgOc:
  501. as_chg=as_chg+(self.param.PackDisOc-self.packcrnt[i])*step #ah累计
  502. else:
  503. as_dis=0
  504. as_chg=0
  505. if not 'C306' in list(self.df_diag_ram['code']): #当前故障中没有该故障,则判断是否发生该故障
  506. if as_dis>100:
  507. time=self.bmstime[i]
  508. code='C306'
  509. faultlv=3
  510. faultinfo='电池包放电过流'
  511. faultadvice='联系用户询问用车场景,技术介入诊断'
  512. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  513. else:
  514. pass
  515. else:
  516. if self.packcrnt[i]<self.param.PackDisOc-10:
  517. time=self.bmstime[i]
  518. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C306'].index, 'end_time'] = time
  519. else:
  520. pass
  521. if not 'C305' in list(self.df_diag_ram['code']): #当前故障中没有该故障,则判断是否发生该故障
  522. if as_chg>100:
  523. time=self.bmstime[i]
  524. code='C305'
  525. faultlv=3
  526. faultinfo='电池包充电过流'
  527. faultadvice='联系用户询问用车场景,技术介入诊断'
  528. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  529. else:
  530. pass
  531. else:
  532. if self.packcrnt[i]>self.param.PackChgOc+10:
  533. time=self.bmstime[i]
  534. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C305'].index, 'end_time'] = time
  535. else:
  536. pass
  537. #SOC卡滞、跳变诊断................................................................................................
  538. if i<1:
  539. bmssoc_st=float(self.bms_soc[i])
  540. bmssoc_last=float(self.bms_soc[i])
  541. bmssoc_now=float(self.bms_soc[i])
  542. else:
  543. step=(self.bmstime[i]-self.bmstime[i-1]).total_seconds()
  544. if step<120:
  545. ah_accum=ah_accum-self.packcrnt[i]*step/3600 #ah累计
  546. else:
  547. pass
  548. #SOC卡滞............................................................................................................
  549. if abs(ah_accum)>self.param.Capacity*0.1:
  550. bmssoc_now=float(self.bms_soc[i])
  551. if not 'C106' in list(self.df_diag_ram['code']): #当前故障中没有该故障,则判断是否发生该故障
  552. if abs(bmssoc_now-bmssoc_st)<self.param.SocClamp: #SOC卡滞故障进入
  553. time=self.bmstime[i]
  554. code='C106'
  555. faultlv=0
  556. faultinfo='电池SOC卡滞'
  557. faultadvice='技术介入诊断,检修电池BMS软件'
  558. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  559. else:
  560. pass
  561. else:
  562. if abs(bmssoc_now-bmssoc_st)>self.param.SocClamp: #SOC卡滞故障退出
  563. time=self.bmstime[i]
  564. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C106'].index, 'end_time'] = time
  565. else:
  566. pass
  567. bmssoc_st=bmssoc_now
  568. ah_accum=0
  569. else:
  570. pass
  571. #SOC跳变....................................................................................................................
  572. bmssoc_last=float(self.bms_soc[i-1])
  573. bmssoc_now=float(self.bms_soc[i])
  574. if not 'C107' in list(self.df_diag_ram['code']): #当前故障中没有该故障,则判断是否发生该故障
  575. if step<70 and abs(bmssoc_now-bmssoc_last)>self.param.SocJump: #SOC跳变进入
  576. time=self.bmstime[i]
  577. code='C107'
  578. faultlv=0
  579. faultinfo='电池SOC跳变{}%'.format(bmssoc_now-bmssoc_last)
  580. faultadvice='技术介入诊断,检修电池BMS软件'
  581. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  582. else:
  583. pass
  584. else:
  585. if abs(bmssoc_now-bmssoc_st)<self.param.SocJump: #SOC跳变故障退出
  586. time=self.bmstime[i]
  587. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C107'].index, 'end_time'] = time
  588. else:
  589. pass
  590. #SOC一致性故障报警..........................................................................................................
  591. if not self.df_uniform.empty:
  592. cellsoc_diff=self.df_uniform.loc[0,'cellsoc_diff']
  593. if not 'C201' in list(self.df_diag_ram['code']): #当前故障中没有该故障,则判断是否发生该故障
  594. if cellsoc_diff>self.param.SocDiff: #SOC一致性差故障进入
  595. time=self.bmstime[0]
  596. code='C201'
  597. faultlv=0
  598. faultinfo='电芯{}和{}SOC差过大:{}'.format(int(self.df_uniform.loc[0,'cellmin_num']),int(self.df_uniform.loc[0,'cellmax_num']),cellsoc_diff)
  599. faultadvice='技术介入诊断'
  600. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  601. else:
  602. pass
  603. else:
  604. if cellsoc_diff<self.param.SocDiff: #SOC一致性差故障恢复
  605. time=self.bmstime[0]
  606. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C201'].index, 'end_time'] = time
  607. else:
  608. cellsoc_diff=3
  609. #容量过低和一致性故障报警................................................................................................
  610. if not self.df_soh.empty:
  611. soh=self.df_soh.loc[0,'soh']
  612. cellsoh=eval(self.df_soh.loc[0,'cellsoh'])
  613. cellsoh=np.array(cellsoh)
  614. cellsoh_lowindex=np.argwhere(cellsoh<self.param.SohLow)
  615. cellsoh_lowindex=cellsoh_lowindex+1
  616. if self.celltype==1 or self.celltype==2 or self.celltype==3 or self.celltype==4:
  617. cellsoh_diff=np.max(cellsoh)-np.min(cellsoh)
  618. if not 'C204' in list(self.df_diag_ram['code']): #当前故障中没有该故障,则判断是否发生该故障
  619. if soh<self.param.SohLow: #soh过低故障进入
  620. time=self.bmstime[0]
  621. code='C204'
  622. faultlv=2
  623. faultinfo='电池包容量过低:电芯{}'.format(cellsoh_lowindex)
  624. faultadvice='检修电池,更换容量过低的电芯或模组'
  625. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  626. else:
  627. pass
  628. else:
  629. if soh>self.param.SohLow+2: #soh过低故障恢复
  630. time=self.bmstime[0]
  631. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C204'].index, 'end_time'] = time
  632. else:
  633. pass
  634. if not 'C205' in list(self.df_diag_ram['code']): #当前故障中没有该故障,则判断是否发生该故障
  635. if cellsoh_diff>self.param.SohDiff:
  636. time=self.bmstime[0]
  637. code='C205'
  638. faultlv=2
  639. faultinfo='电池包容量一致性差:电芯{}'.format(cellsoh_lowindex)
  640. faultadvice='检修电池,更换容量过低的电芯或模组'
  641. self.df_diag_ram.loc[len(self.df_diag_ram)]=[time, end_time, self.sn, code, faultlv, faultinfo, faultadvice]
  642. else:
  643. pass
  644. else:
  645. if cellsoh_diff<self.param.SohDiff-2:
  646. time=self.bmstime[0]
  647. self.df_diag_ram.loc[self.df_diag_ram[self.df_diag_ram['code']=='C205'].index, 'end_time'] = time
  648. else:
  649. pass
  650. else:
  651. pass
  652. else:
  653. cellsoh_diff=5
  654. #ram更新.......................................................................
  655. df_bms_ram=pd.DataFrame(columns=['time', 'sn', 'packvolt', 'cellvolt', 'celltemp'])
  656. df_bms_ram.loc[0]=[self.bmstime[0], self.sn, packvolt2, cellvolt2, celltemp2]
  657. return self.df_diag_ram, df_bms_ram