CBMSSafetyAlarm.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. import pandas as pd
  2. import numpy as np
  3. import datetime
  4. import BatParam
  5. class SafetyAlarm:
  6. def __init__(self,sn,celltype,df_bms,df_diag_ram_sn, df_bms_ram_sn, df_alarm_ram_sn): #参数初始化
  7. self.sn=sn
  8. self.celltype=celltype
  9. self.param=BatParam.BatParam(celltype)
  10. self.df_bms=df_bms
  11. self.df_ram_alarm=df_alarm_ram_sn.copy()
  12. self.df_ram_bms=df_bms_ram_sn.copy()
  13. self.df_diag_ram=df_diag_ram_sn.copy()
  14. df_bms['time']=pd.to_datetime(df_bms['time'], format='%Y-%m-%d %H:%M:%S')
  15. if (not df_bms_ram_sn.empty) and (not self.df_bms.empty):
  16. self.df_bms=self.df_bms[self.df_bms['time'] > df_bms_ram_sn.iloc[-1]['time']] #滤除原始数据中的重复数据
  17. self.df_bms.reset_index(inplace=True,drop=True) #重置索引
  18. self.packcrnt=df_bms['PackCrnt']*self.param.PackCrntDec
  19. self.packvolt=df_bms['PackCrnt']
  20. self.bmstime= df_bms['time']
  21. self.cellvolt_name=['CellVolt'+str(x) for x in range(1,self.param.CellVoltNums+1)]
  22. # othertemp=['其他温度'+str(x) for x in range(1,self.param.OtherTempNums+1)]
  23. self.celltemp_name=['CellTemp'+str(x) for x in range(1,self.param.CellTempNums+1)]
  24. # self.celltemp_name=celltemp+othertemp
  25. def safety_alarm_diag(self):
  26. time_now=datetime.datetime.now()
  27. if not self.df_diag_ram.empty:
  28. fault_time=self.df_diag_ram.iloc[-1]['start_time']
  29. if (time_now-fault_time).total_seconds()>24*3600:
  30. self.df_diag_ram['end_time']=time_now
  31. return self.df_diag_ram, self.df_ram_bms, self.df_ram_alarm
  32. else:
  33. return self.df_diag_ram, self.df_ram_bms, self.df_ram_alarm
  34. else:
  35. df_res=self._alarm_diag()
  36. return df_res
  37. #定义滑动滤波函数.............................................................................................
  38. def _np_move_avg(self,a, n, mode="same"):
  39. return (np.convolve(a, np.ones((n,)) / n, mode=mode))
  40. #寻找当前行数据的所有温度值...................................................................................
  41. def _celltemp_get(self,num):
  42. celltemp = np.array(self.df_bms.loc[num,self.celltemp_name])
  43. return celltemp
  44. #获取当前行所有电压数据............................................................................................
  45. def _cellvolt_get(self,num):
  46. cellvolt = np.array(self.df_bms.loc[num,self.cellvolt_name])
  47. return cellvolt
  48. #..........................................三元电池诊断功能..................................................................
  49. def _alarm_diag(self):
  50. # column_name=['time_st','time_sp','sn','faultcode','faultlv','faultinfo','faultadvice']
  51. # df_res=pd.DataFrame(columns=column_name)
  52. end_time='0000-00-00 00:00:00'
  53. time_now=datetime.datetime.now()
  54. celltemprise=0
  55. celltemphigh=0
  56. cellvoltfall=0
  57. cellvoltdsc=0
  58. packvoltfall=0
  59. cellvolttime=0
  60. if not self.df_ram_alarm.empty:
  61. safetywarning1=self.df_ram_alarm.iloc[-1]['safetywarning1']
  62. safetywarning2=self.df_ram_alarm.iloc[-1]['safetywarning2']
  63. time_last=self.df_ram_alarm.iloc[-1]['time']
  64. else:
  65. safetywarning1=0
  66. safetywarning2=0
  67. if not self.df_bms.empty:
  68. for i in range(len(self.df_bms)):
  69. if i<1:
  70. if not self.df_ram_bms.empty:
  71. temp1=np.array(self.df_ram_bms.iloc[-1]['celltemp'])
  72. temp2=self._celltemp_get(i)
  73. time1=self.df_ram_bms.iloc[-1]['time']
  74. time2=self.bmstime[i]
  75. temp_st=temp1
  76. time_st=time1
  77. cellvolt1=np.array(self.df_ram_bms.iloc[-1]['cellvolt'])
  78. cellvolt2=self._cellvolt_get(i)
  79. packvolt1=self.df_ram_bms.iloc[-1]['packvolt']
  80. packvolt2=self.packvolt[i]
  81. delta_soc=abs(self.df_ram_bms.iloc[-1]['packsoc']-self.packsoc[i])
  82. packcrnt1=self.df_ram_bms.iloc[-1]['packcrnt']
  83. packcrnt2=self.packcrnt[i]
  84. if len(temp1)==len(temp2):
  85. pass
  86. else:
  87. temp1=temp2
  88. temp_st=temp2
  89. if len(cellvolt1)==len(cellvolt2):
  90. pass
  91. else:
  92. cellvolt1=cellvolt2
  93. else:
  94. temp1=self._celltemp_get(i)
  95. temp2=temp1
  96. time1=self.bmstime[i]-datetime.timedelta(seconds=1)
  97. time2=self.bmstime[i]
  98. temp_st=temp1
  99. time_st=time1
  100. cellvolt1=self._cellvolt_get(i)
  101. cellvolt2=cellvolt1
  102. packvolt1=self.packvolt[i]
  103. packvolt2=packvolt1
  104. delta_soc=0
  105. packcrnt1=self.packcrnt[i]
  106. packcrnt2=packcrnt1
  107. else:
  108. temp1=self._celltemp_get(i-1)
  109. temp2=self._celltemp_get(i)
  110. time1=self.bmstime[i-1]
  111. time2=self.bmstime[i]
  112. cellvolt1=self._cellvolt_get(i-1)
  113. cellvolt2=self._cellvolt_get(i)
  114. packvolt1=packvolt2
  115. packvolt2=self.packvolt[i]
  116. packcrnt1=self.packcrnt[i-1]
  117. packcrnt2=self.packcrnt[i]
  118. delta_soc=abs(self.packsoc[i-1]-self.packsoc[i])
  119. #温度有效性判断...........................................................................
  120. if max(temp2)>self.param.CellTempUpLmt or min(temp2)<self.param.CellTempLwLmt:
  121. celltempvalid=0
  122. else:
  123. celltempvalid=1
  124. temp1_valid=np.where((temp1<self.param.CellTempUpLmt) & (temp1>self.param.CellTempLwLmt),True,False)
  125. temp2_valid=np.where((temp2<self.param.CellTempUpLmt) & (temp2>self.param.CellTempLwLmt),True,False)
  126. temp1=temp1[temp1_valid & temp2_valid]
  127. temp2=temp2[temp1_valid & temp2_valid]
  128. if len(temp1)>0.5 and len(temp2)>0.5:
  129. celltempmax=max(temp2)
  130. #过温判断............................................................................................................................
  131. if celltempmax>self.param.TrwTempHigh and np.sum(temp2>self.param.TrwTempHigh)<=self.CellTempNums/2:
  132. celltemphigh=1
  133. else:
  134. pass
  135. #温升判断.............................................................................................................................
  136. delttime=(time2-time_st).total_seconds()
  137. if delttime>5:
  138. temp_st=temp_st[temp1_valid & temp2_valid]
  139. celltemp_rate=((temp2-temp_st)*60)/delttime #计算最大温升速率
  140. time_st=time2
  141. temp_st=self._celltemp_get(i)
  142. else:
  143. celltemp_rate=np.array([0,0])
  144. if delta_soc<5 and max(celltemp_rate)>self.param.TrwTempRate and np.sum(celltemp_rate>self.param.TrwTempRate)<=self.CellTempNums/2:
  145. celltemprise=celltemprise+1
  146. else:
  147. pass
  148. else:
  149. pass
  150. #电压有效性..........................................................................................................................................
  151. cellvolt1_valid=np.where((cellvolt1>0.1) & (cellvolt1<5),True,False)
  152. cellvolt2_valid=np.where((cellvolt2>0.1) & (cellvolt2<5),True,False)
  153. cellvoltfall1=cellvolt1[cellvolt1_valid & cellvolt2_valid]
  154. cellvoltfall2=cellvolt2[cellvolt1_valid & cellvolt2_valid]
  155. if len(cellvoltfall1)<self.CellVoltNums-5 and len(cellvoltfall2)<self.CellVoltNums-5:
  156. cellvolttime=cellvolttime+(time2-time1).total_seconds()
  157. if cellvolttime>2:
  158. cellvoltvalid=0
  159. else:
  160. cellvoltvalid=1
  161. else:
  162. cellvolttime=0
  163. cellvoltvalid=1
  164. delttime=(time2-time1).total_seconds()
  165. if delttime<60:
  166. #单体电压跌落...........................................................................................................................
  167. if len(cellvoltfall1)>1 and len(cellvoltfall2)>1:
  168. if delta_soc<5 and abs(packcrnt1)<=1 and abs(packcrnt2)<=1 and max(cellvoltfall1-cellvoltfall2)>self.param.TrwCellVoltFall and np.sum(cellvoltfall1-cellvoltfall2>self.param.TrwCellVoltFall)<=self.CellVoltNums/2:
  169. cellvoltfall=cellvoltfall+1
  170. else:
  171. pass
  172. #单体电压断线..............................................................................................................................
  173. if 0<min(cellvolt2)<2 and 5<max(cellvolt2)<10:
  174. cellvoltdsc=1
  175. else:
  176. pass
  177. else:
  178. pass
  179. #电池包诊断.....................................................................................................................................
  180. packvolt2=self.packvolt[i]
  181. #电池包电压有效性............................................................................................................................
  182. if self.CellVoltNums<packvolt2<self.CellVoltNums*4.5:
  183. packvoltvalid=1
  184. else:
  185. packvoltvalid=0
  186. if packvoltvalid==1:
  187. delttime=(time2-time1).total_seconds()
  188. if delttime<360:
  189. if delta_soc<5 and abs(packcrnt1)<5 and abs(packcrnt2)<5 and (packvolt1-packvolt2)>self.param.TrwPackVoltFall and self.CellVoltNums<packvolt1<self.CellVoltNums*4.5:
  190. packvoltfall=packvoltfall+1
  191. else:
  192. pass
  193. else:
  194. pass
  195. else:
  196. pass
  197. #热失控故障判断........................................................................................................................
  198. self.df_ram_bms.loc[0]=[time2, self.sn, packvolt2, list(self._cellvolt_get(i)), list(self._celltemp_get(i)), self.packsoc[i],packcrnt2]
  199. self.df_ram_alarm=pd.DataFrame(columns=['sn','time','safetywarning1','safetywarning2'])
  200. trwtemp=max(celltemprise,celltemphigh)
  201. trwcellvolt=cellvoltfall
  202. trwpackvolt=packvoltfall
  203. trw_array=np.array([trwtemp, trwcellvolt, trwpackvolt])
  204. if trwcellvolt>0.5 and np.sum(trw_array)>3.5 and np.sum(trw_array>0.5)>1.5:
  205. fltcode=119
  206. self.df_diag_ram.loc[0]=[self.bmstime[len(self.bmstime)-1], end_time, self.sn, fltcode, 5, '电池发生热失控', '断开继电器,远离电池,立刻消防处理,并通知技术人员介入']
  207. elif safetywarning1>2.5 and np.sum(trw_array)>1.5 and np.sum(trw_array>0.5)>1.5:
  208. fltcode=119
  209. self.df_diag_ram.loc[0]=[self.bmstime[len(self.bmstime)-1], end_time, self.sn, fltcode, 5, '电池发生热失控', '断开继电器,远离电池,立刻消防处理,并通知技术人员介入']
  210. elif safetywarning1>2.5 and cellvoltvalid==0:
  211. fltcode=119
  212. self.df_diag_ram.loc[0]=[self.bmstime[len(self.bmstime)-1], end_time, self.sn, fltcode, 5, '电池发生热失控', '断开继电器,远离电池,立刻消防处理,并通知技术人员介入']
  213. else:
  214. #更新df_ram_alarm信息
  215. if trwcellvolt>0.5 and np.sum(trw_array)>1.5 and np.sum(trw_array>0.5)>1.5:
  216. safetywarning1=3
  217. self.df_ram_alarm.loc[0]=[self.sn,time2,safetywarning1,safetywarning2]
  218. elif (trwcellvolt<0.5 or np.sum(trw_array>0.5)<1.5) and celltempvalid==1 and cellvoltvalid==1:
  219. safetywarning1=0
  220. self.df_ram_alarm.loc[0]=[self.sn,time2,safetywarning1,safetywarning2]
  221. else:
  222. pass
  223. return self.df_diag_ram, self.df_ram_bms, self.df_ram_alarm
  224. else:
  225. if (safetywarning1>2.5 or safetywarning2>2.5) and (time_now-time_last).total_seconds()>360:
  226. fltcode=119
  227. time_now=time_now.strftime('%Y-%m-%d %H:%M:%S')
  228. time_now=datetime.datetime.strptime(time_now,'%Y-%m-%d %H:%M:%S')
  229. self.df_diag_ram.loc[0]=[time_now, end_time, self.sn, fltcode, 5, '电池发生热失控', '断开继电器,远离电池,立刻消防处理,并通知技术人员介入']
  230. self.df_ram_alarm=pd.DataFrame(columns=['sn','time','safetywarning1','safetywarning2'])
  231. else:
  232. pass
  233. return self.df_diag_ram, self.df_ram_bms, self.df_ram_alarm