CBMSBatInterShort.py 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826
  1. import pandas as pd
  2. import numpy as np
  3. import datetime
  4. import BatParam
  5. class BatInterShort():
  6. def __init__(self,sn,celltype,df_bms,df_soh,df_last,df_last1,df_last2,df_last3,df_lfp): #参数初始化
  7. if (not df_lfp.empty) and celltype>50:
  8. df_bms=pd.concat([df_lfp, df_bms], ignore_index=True)
  9. df_bms.reset_index(inplace=True,drop=True)
  10. else:
  11. pass
  12. self.sn=sn
  13. self.celltype=celltype
  14. self.param=BatParam.BatParam(celltype)
  15. self.packcrnt=df_bms['PackCrnt']*self.param.PackCrntDec
  16. self.packvolt=df_bms['PackVolt']
  17. self.bms_soc=df_bms['PackSOC']
  18. df_bms['time']=pd.to_datetime(df_bms['time'], format='%Y-%m-%d %H:%M:%S')
  19. self.bmstime= df_bms['time']
  20. self.df_bms=df_bms
  21. self.df_soh=df_soh
  22. self.df_last=df_last
  23. self.df_last1=df_last1
  24. self.df_last2=df_last2
  25. self.df_last3=df_last3
  26. self.df_lfp=df_lfp
  27. self.cellvolt_name=['CellVolt'+str(x) for x in range(1,self.param.CellVoltNums+1)]
  28. self.celltemp_name=['CellTemp'+str(x) for x in range(1,self.param.CellTempNums+1)]
  29. def intershort(self):
  30. if self.celltype<=50:
  31. df_res, df_ram_last, df_ram_last1, df_ram_last3=self._ncm_intershort()
  32. return df_res, df_ram_last, df_ram_last1,self.df_last2, df_ram_last3,self.df_lfp
  33. else:
  34. df_res, df_ram_last, df_ram_last1, df_ram_last2, df_ram_last3, df_ram_lfp=self._lfp_intershort()
  35. return df_res, df_ram_last, df_ram_last1, df_ram_last2, df_ram_last3, df_ram_lfp
  36. #定义滑动滤波函数....................................................................................
  37. def _np_move_avg(self,a, n, mode="same"):
  38. return (np.convolve(a, np.ones((n,)) / n, mode=mode))
  39. #寻找当前行数据的最小温度值.............................................................................
  40. def _celltemp_weight(self,num):
  41. celltemp = list(self.df_bms.loc[num,self.celltemp_name])
  42. celltemp=min(celltemp)
  43. self.celltemp=celltemp
  44. if self.celltype>50:
  45. if celltemp>=25:
  46. self.tempweight=1
  47. self.StandardStandingTime=4500
  48. elif celltemp>=15:
  49. self.tempweight=0.6
  50. self.StandardStandingTime=7200
  51. elif celltemp>=5:
  52. self.tempweight=0.2
  53. self.StandardStandingTime=10800
  54. else:
  55. self.tempweight=0.1
  56. self.StandardStandingTime=10800
  57. else:
  58. if celltemp>=25:
  59. self.tempweight=1
  60. self.StandardStandingTime=3600
  61. elif celltemp>=15:
  62. self.tempweight=0.8
  63. self.StandardStandingTime=5400
  64. elif celltemp>=5:
  65. self.tempweight=0.6
  66. self.StandardStandingTime=7200
  67. else:
  68. self.tempweight=0.2
  69. self.StandardStandingTime=10800
  70. #获取前5min每个电压的平均值........................................................................................
  71. def _avgvolt_get(self,num):
  72. time_now=self.df_bms.loc[num, 'time']
  73. time_last=time_now-datetime.timedelta(seconds=300)
  74. df_volt=self.df_bms[(self.df_bms['time']>=time_last) & (self.df_bms['time']<=time_now)]
  75. df_volt=df_volt[self.cellvolt_name]
  76. df_volt=df_volt[(df_volt>2) & (df_volt<4.5)]
  77. df_volt=df_volt.dropna()
  78. cellvolt_std=df_volt.std(axis=0)
  79. if len(df_volt)>2 and max(cellvolt_std)<0.005:
  80. cellvolt_sum=df_volt.sum(0)-df_volt.max(0)-df_volt.min(0)
  81. cellvolt_mean=cellvolt_sum/(len(df_volt)-2)
  82. cellvolt=cellvolt_mean
  83. elif len(df_volt)==2:
  84. # df_volt=pd.DataFrame(df_volt,dtype=np.float)
  85. if max(abs(df_volt.iloc[1]-df_volt.iloc[0]))<0.003:
  86. cellvolt=df_volt.mean(0)
  87. else:
  88. cellvolt=pd.DataFrame()
  89. elif len(df_volt)==1:
  90. cellvolt=df_volt.iloc[0]
  91. else:
  92. cellvolt=pd.DataFrame()
  93. return cellvolt
  94. #获取当前行所有电压数据........................................................................................
  95. def _cellvolt_get(self,num):
  96. cellvolt = np.array(self.df_bms.loc[num,self.cellvolt_name])
  97. return cellvolt
  98. #获取单个电压值.................................................................................................
  99. def _singlevolt_get(self,num,series,mode): #mode==1取当前行单体电压值,mode==2取某个单体所有电压值
  100. s=str(series)
  101. if mode==1:
  102. singlevolt=self.df_bms.loc[num,'CellVolt' + s]
  103. return singlevolt
  104. else:
  105. singlevolt=self.df_bms['CellVolt' + s]
  106. return singlevolt
  107. #获取当前行所有soc差...........................................................................................
  108. def _celldeltsoc_get(self,cellvolt_list,dict_baltime,capacity):
  109. cellsoc=[]
  110. celldeltsoc=[]
  111. for j in range(1, self.param.CellVoltNums+1): #获取每个电芯电压对应的SOC值
  112. cellvolt=cellvolt_list[j-1]
  113. ocv_soc=np.interp(cellvolt,self.param.LookTab_OCV,self.param.LookTab_SOC)
  114. if j in dict_baltime.keys():
  115. ocv_soc=ocv_soc+dict_baltime[j]*self.param.BalCurrent/(capacity*3600) #补偿均衡电流
  116. else:
  117. pass
  118. cellsoc.append(ocv_soc)
  119. cellsocmean=(sum(cellsoc)-max(cellsoc)-min(cellsoc))/(len(cellsoc)-2)
  120. for j in range(len(cellsoc)): #计算每个电芯的soc差
  121. celldeltsoc.append(cellsoc[j]-cellsocmean)
  122. return np.array(celldeltsoc), np.array(cellsoc)
  123. #寻找DVDQ的峰值点,并返回..........................................................................................................................
  124. def _dvdq_peak(self, time, soc, cellvolt, packcrnt):
  125. cellvolt = self._np_move_avg(cellvolt, 5, mode="same")
  126. Soc = 0
  127. Ah = 0
  128. Ah_total=0
  129. Volt = cellvolt[0]
  130. DV_Volt = []
  131. DQ_Ah = []
  132. DVDQ = []
  133. time1 = []
  134. soc1 = []
  135. soc2 = []
  136. xvolt=[]
  137. for m in range(1, len(time)):
  138. Step = (time[m] - time[m - 1]).total_seconds()
  139. Soc = Soc - packcrnt[m] * Step * 100 / (3600 * float(self.param.Capacity))
  140. Ah = Ah - packcrnt[m] * Step / 3600
  141. if (cellvolt[m]-Volt)>0.0012 and Ah>0.01:
  142. Ah_total=Ah_total+Ah
  143. DQ_Ah.append(Ah_total)
  144. DV_Volt.append(cellvolt[m]-Volt)
  145. DVDQ.append((DV_Volt[-1])/Ah)
  146. xvolt.append(cellvolt[m])
  147. Volt=cellvolt[m]
  148. Ah = 0
  149. soc1.append(Soc)
  150. time1.append(time[m])
  151. soc2.append(soc[m])
  152. #切片,去除前后10min的数据
  153. df_Data1 = pd.DataFrame({'time': time1,
  154. 'SOC': soc2,
  155. 'DVDQ': DVDQ,
  156. 'AhSoc': soc1,
  157. 'DQ_Ah':DQ_Ah,
  158. 'DV_Volt':DV_Volt,
  159. 'XVOLT':xvolt})
  160. start_time=df_Data1.loc[0,'time']
  161. start_time=start_time+datetime.timedelta(seconds=900)
  162. end_time=df_Data1.loc[len(time1)-1,'time']
  163. end_time=end_time-datetime.timedelta(seconds=1200)
  164. if soc2[0]<36:
  165. df_Data1=df_Data1[(df_Data1['SOC']>40) & (df_Data1['SOC']<80)]
  166. else:
  167. df_Data1=df_Data1[(df_Data1['time']>start_time) & (df_Data1['SOC']<80)]
  168. df_Data1=df_Data1[(df_Data1['XVOLT']>self.param.PeakVoltLowLmt) & (df_Data1['XVOLT']<self.param.PeakVoltUpLmt)]
  169. # print(packcrnt[int(len(time)/2)], min(self.celltemp))
  170. # ax1 = plt.subplot(3, 1, 1)
  171. # plt.plot(df_Data1['SOC'],df_Data1['DQ_Ah'],'g*-')
  172. # plt.xlabel('SOC/%')
  173. # plt.ylabel('DQ_Ah')
  174. # plt.legend()
  175. # ax1 = plt.subplot(3, 1, 2)
  176. # plt.plot(df_Data1['SOC'],df_Data1['XVOLT'],'y*-')
  177. # plt.xlabel('SOC/%')
  178. # plt.ylabel('Volt/V')
  179. # plt.legend()
  180. # ax1 = plt.subplot(3, 1, 3)
  181. # plt.plot(df_Data1['SOC'], df_Data1['DVDQ'], 'r*-')
  182. # plt.xlabel('SOC/%')
  183. # plt.ylabel('DV/DQ')
  184. # plt.legend()
  185. # # plt.show()
  186. if len(df_Data1)>2:
  187. PeakIndex = df_Data1['DVDQ'].idxmax()
  188. df_Data2 = df_Data1[(df_Data1['SOC'] > (df_Data1['SOC'][PeakIndex] - 0.5)) & (df_Data1['SOC'] < (df_Data1['SOC'][PeakIndex] + 0.5))]
  189. if len(df_Data2) > 1 and min(df_Data1['SOC'])+0.5<df_Data1['SOC'][PeakIndex]<max(df_Data1['SOC'])-1:
  190. return df_Data1['DQ_Ah'][PeakIndex]
  191. else:
  192. if min(df_Data1['SOC'])+0.5<df_Data1['SOC'][PeakIndex]<max(df_Data1['SOC'])-1:
  193. df_Data1=df_Data1.drop([PeakIndex])
  194. elif df_Data1['SOC'][PeakIndex]>max(df_Data1['SOC'])-1:
  195. df_Data1=df_Data1[df_Data1['SOC']<(df_Data1['SOC'][PeakIndex]-1)]
  196. else:
  197. df_Data1=df_Data1[df_Data1['SOC']>(df_Data1['SOC'][PeakIndex]+0.5)]
  198. if len(df_Data1)>2:
  199. PeakIndex = df_Data1['DVDQ'].idxmax()
  200. df_Data2 = df_Data1[(df_Data1['SOC'] > (df_Data1['SOC'][PeakIndex] - 0.5)) & (df_Data1['SOC'] < (df_Data1['SOC'][PeakIndex] + 0.5))]
  201. if len(df_Data2) > 1 and min(df_Data1['SOC'])+0.5<df_Data1['SOC'][PeakIndex]<max(df_Data1['SOC'])-1: #
  202. return df_Data1['DQ_Ah'][PeakIndex]
  203. else:
  204. return 0
  205. else:
  206. return 0
  207. else:
  208. return 0
  209. #获取所有电芯的As差
  210. def _cellDeltAs_get(self,chrg_st,chrg_end,dict_baltime):
  211. cellAs=[]
  212. celldeltAs=[]
  213. for j in range(1, self.param.CellVoltNums+1): #获取每个电芯电压>峰值电压的充入As数
  214. if j in dict_baltime.keys(): #补偿均衡电流
  215. As=-self.param.BalCurrent*dict_baltime[j]
  216. else:
  217. As=0
  218. As_tatol=0
  219. symbol=0
  220. for m in range(chrg_st+1,chrg_end):
  221. As=As-self.packcrnt[m]*(self.bmstime[m]-self.bmstime[m-1]).total_seconds()
  222. if symbol<5:
  223. if self.df_bms.loc[m,'CellVolt'+str(j)]>self.param.PeakCellVolt[symbol]:
  224. As_tatol=As_tatol+As
  225. symbol=symbol+1
  226. else:
  227. continue
  228. else:
  229. cellAs.append(As_tatol/5)
  230. break
  231. cellAsmean=(sum(cellAs)-max(cellAs)-min(cellAs))/(len(cellAs)-2)
  232. for j in range(len(cellAs)): #计算每个电芯的soc差
  233. celldeltAs.append(cellAs[j]-cellAsmean)
  234. return np.array(celldeltAs)
  235. #计算每个电芯的均衡时长..........................................................................................................................
  236. def _bal_time(self,dict_bal):
  237. dict_baltime={}
  238. dict_baltime1={}
  239. for key in dict_bal:
  240. count=1
  241. x=eval(key)
  242. while x>0:
  243. if x & 1==1: #判断最后一位是否为1
  244. if count in dict_baltime.keys():
  245. dict_baltime[count] = dict_baltime[count] + dict_bal[key]
  246. else:
  247. dict_baltime[count] = dict_bal[key]
  248. else:
  249. pass
  250. count += 1
  251. x >>= 1 #右移一位
  252. dict_baltime=dict(sorted(dict_baltime.items(),key=lambda dict_baltime:dict_baltime[0]))
  253. for key in dict_baltime: #解析均衡的电芯编号
  254. if self.celltype==1: #科易6040
  255. if key<14:
  256. dict_baltime1[key]=dict_baltime[key]
  257. elif key<18:
  258. dict_baltime1[key-1]=dict_baltime[key]
  259. else:
  260. dict_baltime1[key-3]=dict_baltime[key]
  261. elif self.celltype==1: #科易4840
  262. if key<4:
  263. dict_baltime1[key-1]=dict_baltime[key]
  264. elif key<8:
  265. dict_baltime1[key-1]=dict_baltime[key]
  266. elif key<14:
  267. dict_baltime1[key-3]=dict_baltime[key]
  268. elif key<18:
  269. dict_baltime1[key-4]=dict_baltime[key]
  270. else:
  271. dict_baltime1[key-6]=dict_baltime[key]
  272. else:
  273. dict_baltime1=dict_baltime
  274. return dict_baltime1
  275. #三元电池的内短路电流计算...........................................................................................................................................................
  276. def _ncm_intershort(self):
  277. df_res=pd.DataFrame(columns=['time_st', 'time_sp', 'sn', 'method','short_current','baltime'])
  278. df_ram_last=self.df_last
  279. df_ram_last1=self.df_last1
  280. df_ram_last3=self.df_last3
  281. #容量初始化
  282. if self.df_soh.empty:
  283. batsoh=self.df_bms.loc[0,'PackSOH']
  284. capacity=self.param.Capacity*batsoh/100
  285. else:
  286. batsoh=self.df_soh.loc[len(self.df_soh)-1,'soh']
  287. capacity=self.param.Capacity*batsoh/100
  288. #参数初始化
  289. if df_ram_last.empty:
  290. firsttime=1
  291. dict_bal={}
  292. else:
  293. deltsoc_last=df_ram_last.loc[0,'deltsoc']
  294. cellsoc_last=df_ram_last.loc[0,'cellsoc']
  295. time_last=df_ram_last.loc[0,'time']
  296. firsttime=0
  297. dict_bal={}
  298. if df_ram_last1.empty:
  299. firsttime1=1
  300. dict_bal1={}
  301. else:
  302. deltsoc_last1=df_ram_last1.loc[0,'deltsoc1']
  303. time_last1=df_ram_last1.loc[0,'time1']
  304. firsttime1=0
  305. dict_bal1={}
  306. if df_ram_last3.empty:
  307. standingtime=0
  308. standingtime1=0
  309. standingtime2=0
  310. else:
  311. standingtime=df_ram_last3.loc[0,'standingtime']
  312. standingtime1=df_ram_last3.loc[0,'standingtime1']
  313. standingtime2=df_ram_last3.loc[0,'standingtime2']
  314. dict_bal1={}
  315. if abs(self.packcrnt[0])<0.01 and standingtime>1 and standingtime1>1:
  316. standingtime=standingtime+(self.bmstime[0]-df_ram_last3.loc[0,'time3']).total_seconds()
  317. standingtime1=standingtime1+(self.bmstime[0]-df_ram_last3.loc[0,'time3']).total_seconds()
  318. else:
  319. pass
  320. for i in range(1,len(self.df_bms)-1):
  321. if firsttime1==0: #满电静置算法--计算均衡状态对应的均衡时间
  322. try:
  323. balstat=int(self.df_bms.loc[i,'单体均衡状态'])
  324. if balstat>0.5:
  325. bal_step=(self.bmstime[i+1]-self.bmstime[i]).total_seconds() #均衡步长
  326. bal_step=int(bal_step)
  327. if str(balstat) in dict_bal1.keys():
  328. dict_bal1[str(balstat)]=dict_bal1[str(balstat)]+bal_step
  329. else:
  330. dict_bal1[str(balstat)]=bal_step
  331. else:
  332. pass
  333. except:
  334. dict_bal1={}
  335. else:
  336. pass
  337. if abs(self.packcrnt[i]) < 0.1 and abs(self.packcrnt[i-1]) < 0.1 and abs(self.packcrnt[i+1]) < 0.1:
  338. delttime=(self.bmstime[i]-self.bmstime[i-1]).total_seconds()
  339. standingtime=standingtime+delttime
  340. standingtime1=standingtime1+delttime
  341. self._celltemp_weight(i)
  342. #长时间静置法计算内短路-开始.....................................................................................................................................
  343. if firsttime==1:
  344. if standingtime>self.StandardStandingTime*2: #静置时间满足要求
  345. standingtime=0
  346. cellvolt_now=self._avgvolt_get(i)
  347. if not cellvolt_now.empty:
  348. cellvolt_min=min(cellvolt_now)
  349. cellvolt_max=max(cellvolt_now)
  350. # cellvolt_last=self._avgvolt_get(i-1)
  351. # deltvolt=max(abs(cellvolt_now-cellvolt_last))
  352. cellsoc_max=np.interp(cellvolt_max,self.param.LookTab_OCV,self.param.LookTab_SOC)
  353. cellsoc_min=np.interp(cellvolt_min,self.param.LookTab_OCV,self.param.LookTab_SOC)
  354. if 2<cellvolt_min<4.5 and 2<cellvolt_max<4.5 and (45<cellsoc_max or cellsoc_max<30) and (45<cellsoc_min or cellsoc_min<30):
  355. dict_baltime={} #获取每个电芯的均衡时间
  356. deltsoc_last, cellsoc_last=self._celldeltsoc_get(cellvolt_now,dict_baltime,capacity)
  357. time_last=self.bmstime[i]
  358. firsttime=0
  359. df_ram_last.loc[0]=[self.sn,time_last,deltsoc_last,cellsoc_last] #更新RAM信息
  360. else:
  361. pass
  362. elif standingtime>3600*12:
  363. standingtime=0
  364. cellvolt_now=self._avgvolt_get(i)
  365. if not cellvolt_now.empty:
  366. cellvolt_min=min(cellvolt_now)
  367. cellvolt_max=max(cellvolt_now)
  368. # cellvolt_last=self._avgvolt_get(i-1)
  369. # deltvolt=max(abs(cellvolt_now-cellvolt_last))
  370. cellsoc_max=np.interp(cellvolt_max,self.param.LookTab_OCV,self.param.LookTab_SOC)
  371. cellsoc_min=np.interp(cellvolt_min,self.param.LookTab_OCV,self.param.LookTab_SOC)
  372. if 2<cellvolt_min<4.5 and 2<cellvolt_max<4.5 and (45<cellsoc_max or cellsoc_max<30) and (45<cellsoc_min or cellsoc_min<30):
  373. dict_baltime=self._bal_time(dict_bal) #获取每个电芯的均衡时间
  374. deltsoc_now, cellsoc_now=self._celldeltsoc_get(cellvolt_now,dict_baltime,capacity)
  375. time_now=self.bmstime[i]
  376. if -5<max(cellsoc_now-cellsoc_last)<5:
  377. df_ram_last.loc[0]=[self.sn,time_now,deltsoc_now,cellsoc_now] #更新RAM信息
  378. list_sub=deltsoc_now-deltsoc_last
  379. list_pud=(0.01*capacity*3600*1000)/(time_now-time_last).total_seconds()
  380. leak_current=list_sub*list_pud
  381. # leak_current=np.array(leak_current)
  382. leak_current=np.round(leak_current,3)
  383. leak_current=list(leak_current)
  384. df_res.loc[len(df_res)]=[time_last,time_now,self.sn,1,str(leak_current),str(dict_baltime)] #计算结果存入Dataframe
  385. time_last=time_now #更新时间
  386. deltsoc_last=deltsoc_now #更新soc差
  387. dict_bal={}
  388. else:
  389. firsttime=1
  390. else:
  391. try:
  392. balstat=int(self.df_bms.loc[i,'单体均衡状态'])
  393. if balstat>0.5:
  394. bal_step=(self.bmstime[i+1]-self.bmstime[i]).total_seconds() #均衡步长
  395. bal_step=int(bal_step)
  396. if str(balstat) in dict_bal.keys():
  397. dict_bal[str(balstat)]=dict_bal[str(balstat)]+bal_step
  398. else:
  399. dict_bal[str(balstat)]=bal_step
  400. else:
  401. pass
  402. except:
  403. dict_bal={}
  404. #满电静置法计算内短路-开始.....................................................................................................................................................
  405. if self.StandardStandingTime<standingtime1:
  406. standingtime1=0
  407. cellvolt_now1=self._avgvolt_get(i)
  408. if not cellvolt_now1.empty:
  409. cellvolt_max1=max(cellvolt_now1)
  410. cellvolt_min1=min(cellvolt_now1)
  411. # cellvolt_last1=self._avgvolt_get(i-1)
  412. # deltvolt1=max(abs(cellvolt_now1-cellvolt_last1))
  413. cellsoc_now1=np.interp(cellvolt_max1,self.param.LookTab_OCV,self.param.LookTab_SOC)
  414. if cellsoc_now1>self.param.FullChrgSoc-10 and 2<cellvolt_min1<4.5 and 2<cellvolt_max1<4.5:
  415. if firsttime1==1:
  416. dict_baltime1={} #获取每个电芯的均衡时间
  417. deltsoc_last1, cellsoc_last1=self._celldeltsoc_get(cellvolt_now1,dict_baltime1,capacity)
  418. time_last1=self.bmstime[i]
  419. firsttime1=0
  420. df_ram_last1.loc[0]=[self.sn,time_last1,deltsoc_last1] #更新RAM信息
  421. else:
  422. dict_baltime1=self._bal_time(dict_bal1) #获取每个电芯的均衡时间
  423. time_now1=self.bmstime[i]
  424. if (time_now1-time_last1).total_seconds()>3600*20:
  425. deltsoc_now1, cellsoc_now1=self._celldeltsoc_get(cellvolt_now1,dict_baltime1,capacity)
  426. df_ram_last1.loc[0]=[self.sn,time_now1,deltsoc_now1] #更新RAM信息
  427. list_sub1=deltsoc_now1-deltsoc_last1
  428. list_pud1=(0.01*capacity*3600*1000)/(time_now1-time_last1).total_seconds()
  429. leak_current1=list_sub1*list_pud1
  430. # leak_current1=np.array(leak_current1)
  431. leak_current1=np.round(leak_current1,3)
  432. leak_current1=list(leak_current1)
  433. df_res.loc[len(df_res)]=[time_last1,time_now1,self.sn,2,str(leak_current1),str(dict_baltime1)] #计算结果存入Dataframe
  434. time_last1=time_now1 #更新时间
  435. deltsoc_last1=deltsoc_now1 #更新soc差
  436. dict_bal1={}
  437. else:
  438. pass
  439. else:
  440. pass
  441. else:
  442. pass
  443. else:
  444. df_ram_last=pd.DataFrame(columns=['sn','time','deltsoc','cellsoc']) #电流>0,清空上次静置的SOC差
  445. dict_bal={}
  446. firsttime=1
  447. standingtime=0
  448. standingtime1=0
  449. pass
  450. #更新RAM的standingtime
  451. df_ram_last3.loc[0]=[self.sn,self.bmstime[len(self.bmstime)-1],standingtime,standingtime1,standingtime2]
  452. #返回计算结果
  453. if df_res.empty:
  454. return pd.DataFrame(), df_ram_last, df_ram_last1, df_ram_last3
  455. else:
  456. return df_res, df_ram_last, df_ram_last1, df_ram_last3
  457. #磷酸铁锂电池内短路计算程序.............................................................................................................................
  458. def _lfp_intershort(self):
  459. column_name=['time_st', 'time_sp', 'sn', 'method','short_current','baltime']
  460. df_res=pd.DataFrame(columns=column_name)
  461. df_ram_last=self.df_last
  462. df_ram_last1=self.df_last1
  463. df_ram_last2=self.df_last2
  464. df_ram_last3=self.df_last3
  465. df_ram_lfp=pd.DataFrame(columns=self.df_bms.columns.tolist())
  466. #容量初始化
  467. if self.df_soh.empty:
  468. batsoh=self.df_bms.loc[0,'PackSOH']
  469. capacity=self.param.Capacity*batsoh/100
  470. else:
  471. batsoh=self.df_soh.loc[len(self.df_soh)-1,'soh']
  472. capacity=self.param.Capacity*batsoh/100
  473. #参数初始化
  474. if df_ram_last.empty:
  475. firsttime=1
  476. dict_bal={}
  477. else:
  478. deltsoc_last=df_ram_last.loc[0,'deltsoc']
  479. cellsoc_last=df_ram_last.loc[0,'cellsoc']
  480. time_last=df_ram_last.loc[0,'time']
  481. firsttime=0
  482. dict_bal={}
  483. if df_ram_last1.empty:
  484. firsttime1=1
  485. dict_bal1={}
  486. else:
  487. deltsoc_last1=df_ram_last1.loc[0,'deltsoc1']
  488. time_last1=df_ram_last1.loc[0,'time1']
  489. firsttime1=0
  490. dict_bal1={}
  491. if df_ram_last2.empty:
  492. firsttime2=1
  493. charging=0
  494. dict_bal2={}
  495. else:
  496. deltAs_last2=df_ram_last2.loc[0,'deltAs2']
  497. time_last2=df_ram_last2.loc[0,'time2']
  498. firsttime2=0
  499. charging=0
  500. dict_bal2={}
  501. if df_ram_last3.empty:
  502. standingtime=0
  503. standingtime1=0
  504. standingtime2=0
  505. else:
  506. standingtime=df_ram_last3.loc[0,'standingtime']
  507. standingtime1=df_ram_last3.loc[0,'standingtime1']
  508. standingtime2=df_ram_last3.loc[0,'standingtime2']
  509. dict_bal1={}
  510. if abs(self.packcrnt[0])<0.01 and standingtime>1 and standingtime1>1:
  511. standingtime=standingtime+(self.bmstime[0]-df_ram_last3.loc[0,'time3']).total_seconds()
  512. standingtime1=standingtime1+(self.bmstime[0]-df_ram_last3.loc[0,'time3']).total_seconds()
  513. else:
  514. pass
  515. for i in range(1,len(self.df_bms)-1):
  516. #静置法计算内短路..........................................................................................................................
  517. if firsttime1==0: #满电静置算法--计算均衡状态对应的均衡时间
  518. try:
  519. balstat=int(self.df_bms.loc[i,'单体均衡状态'])
  520. if balstat>0.5:
  521. bal_step=(self.bmstime[i+1]-self.bmstime[i]).total_seconds() #均衡步长
  522. bal_step=int(bal_step)
  523. if str(balstat) in dict_bal1.keys():
  524. dict_bal1[str(balstat)]=dict_bal1[str(balstat)]+bal_step
  525. else:
  526. dict_bal1[str(balstat)]=bal_step
  527. else:
  528. pass
  529. except:
  530. dict_bal1={}
  531. else:
  532. pass
  533. if abs(self.packcrnt[i]) < 0.1 and abs(self.packcrnt[i-1]) < 0.1:
  534. delttime=(self.bmstime[i]-self.bmstime[i-1]).total_seconds()
  535. standingtime=standingtime+delttime
  536. standingtime1=standingtime1+delttime
  537. self._celltemp_weight(i)
  538. #长时间静置法计算内短路-开始.....................................................................................................................................
  539. if firsttime==1:
  540. if standingtime>self.StandardStandingTime: #静置时间满足要求
  541. cellvolt_now=self._avgvolt_get(i)
  542. if not cellvolt_now.empty:
  543. standingtime=0
  544. cellvolt_min=min(cellvolt_now)
  545. cellvolt_max=max(cellvolt_now)
  546. # cellvolt_last=self._avgvolt_get(i-1)
  547. # deltvolt=max(abs(cellvolt_now-cellvolt_last))
  548. cellsoc_max=np.interp(cellvolt_max,self.param.LookTab_OCV,self.param.LookTab_SOC)
  549. cellsoc_min=np.interp(cellvolt_min,self.param.LookTab_OCV,self.param.LookTab_SOC)
  550. if cellsoc_max<self.param.SocInflexion1-2 and 12<cellsoc_min:
  551. dict_baltime={} #获取每个电芯的均衡时间
  552. deltsoc_last, cellsoc_last=self._celldeltsoc_get(cellvolt_now,dict_baltime,capacity)
  553. time_last=self.bmstime[i]
  554. firsttime=0
  555. df_ram_last.loc[0]=[self.sn,time_last,deltsoc_last,cellsoc_last] #更新RAM信息
  556. else:
  557. pass
  558. else:
  559. pass
  560. elif standingtime>3600*12:
  561. cellvolt_now=np.array(self._avgvolt_get(i))
  562. if not cellvolt_now.empty:
  563. standingtime=0
  564. cellvolt_min=min(cellvolt_now)
  565. cellvolt_max=max(cellvolt_now)
  566. # cellvolt_last=np.array(self._avgvolt_get(i-1))
  567. # deltvolt=max(abs(cellvolt_now-cellvolt_last))
  568. cellsoc_max=np.interp(cellvolt_max,self.param.LookTab_OCV,self.param.LookTab_SOC)
  569. cellsoc_min=np.interp(cellvolt_min,self.param.LookTab_OCV,self.param.LookTab_SOC)
  570. if cellsoc_max<self.param.SocInflexion1-2 and 12<cellsoc_min:
  571. dict_baltime=self._bal_time(dict_bal) #获取每个电芯的均衡时间
  572. deltsoc_now, cellsoc_now=self._celldeltsoc_get(cellvolt_now, dict_baltime,capacity) #获取每个电芯的SOC差
  573. time_now=self.bmstime[i]
  574. if -5<max(cellsoc_now-cellsoc_last)<5:
  575. df_ram_last.loc[0]=[self.sn,time_now,deltsoc_now,cellsoc_now] #更新RAM信息
  576. list_sub=deltsoc_now-deltsoc_last
  577. list_pud=(0.01*capacity*3600*1000)/(time_now-time_last).total_seconds()
  578. leak_current=list_sub*list_pud
  579. # leak_current=np.array(leak_current)
  580. leak_current=np.round(leak_current,3)
  581. leak_current=list(leak_current)
  582. df_res.loc[len(df_res)]=[time_last,time_now,self.sn,1,str(leak_current),str(dict_baltime)] #计算结果存入Dataframe
  583. time_last=time_now #更新时间
  584. deltsoc_last=deltsoc_now #更新soc差
  585. dict_bal={}
  586. else:
  587. firsttime=1
  588. else:
  589. pass
  590. else:
  591. try:
  592. balstat=int(self.df_bms.loc[i,'单体均衡状态'])
  593. if balstat>0.5:
  594. bal_step=(self.bmstime[i+1]-self.bmstime[i]).total_seconds() #均衡步长
  595. bal_step=int(bal_step)
  596. if str(balstat) in dict_bal.keys():
  597. dict_bal[str(balstat)]=dict_bal[str(balstat)]+bal_step
  598. else:
  599. dict_bal[str(balstat)]=bal_step
  600. else:
  601. pass
  602. except:
  603. dict_bal={}
  604. #非平台区间静置法计算内短路-开始.....................................................................................................................................................
  605. if standingtime1>self.StandardStandingTime:
  606. cellvolt_now1=self._avgvolt_get(i)
  607. if not cellvolt_now1.empty:
  608. standingtime1=0
  609. cellvolt_max1=max(cellvolt_now1)
  610. cellvolt_min1=min(cellvolt_now1)
  611. # cellvolt_last1=self._avgvolt_get(i-1)
  612. # deltvolt1=max(abs(cellvolt_now1-cellvolt_last1))
  613. cellsoc_max1=np.interp(cellvolt_max1,self.param.LookTab_OCV,self.param.LookTab_SOC)
  614. cellsoc_min1=np.interp(cellvolt_min1,self.param.LookTab_OCV,self.param.LookTab_SOC)
  615. if cellsoc_max1<self.param.SocInflexion1-2 and 1<cellsoc_min1:
  616. if firsttime1==1:
  617. dict_baltime1=self._bal_time(dict_bal1) #获取每个电芯的均衡时间
  618. deltsoc_last1, cellsoc_last1=self._celldeltsoc_get(cellvolt_now1,dict_baltime1,capacity)
  619. time_last1=self.bmstime[i]
  620. firsttime1=0
  621. df_ram_last1.loc[0]=[self.sn,time_last1,deltsoc_last1] #更新RAM信息
  622. else:
  623. dict_baltime1=self._bal_time(dict_bal1) #获取每个电芯的均衡时间
  624. deltsoc_now1, cellsoc_now1=self._celldeltsoc_get(cellvolt_now1,dict_baltime1,capacity)
  625. time_now1=self.bmstime[i]
  626. df_ram_last1.loc[0]=[self.sn,time_now1,deltsoc_now1] #更新RAM信息
  627. if (time_now1-time_last1).total_seconds()>3600*24:
  628. list_sub1=deltsoc_now1-deltsoc_last1
  629. list_pud1=(0.01*capacity*3600*1000)/(time_now1-time_last1).total_seconds()
  630. leak_current1=list_sub1*list_pud1
  631. # leak_current1=np.array(leak_current1)
  632. leak_current1=np.round(leak_current1,3)
  633. leak_current1=list(leak_current1)
  634. df_res.loc[len(df_res)]=[time_last1,time_now1,self.sn,2,str(leak_current1),str(dict_baltime1)] #计算结果存入Dataframe
  635. time_last1=time_now1 #更新时间
  636. deltsoc_last1=deltsoc_now1 #更新soc差
  637. dict_bal1={}
  638. else:
  639. pass
  640. else:
  641. pass
  642. else:
  643. pass
  644. else:
  645. df_ram_last=pd.DataFrame(columns=['sn','time','deltsoc','cellsoc']) #电流>0,清空上次静置的SOC差
  646. dict_bal={}
  647. firsttime=1
  648. standingtime=0
  649. standingtime1=0
  650. pass
  651. if i==len(self.df_bms)-2 and abs(self.packcrnt[i+1]) < 0.1: #数据中断后仍在静置,将最后一条数据写入RAM
  652. df_ram_lfp.loc[0]=self.df_bms.iloc[-1]
  653. else:
  654. pass
  655. #获取充电数据——开始..............................................................................................................
  656. try:
  657. balstat=int(self.df_bms.loc[i,'单体均衡状态']) #统计均衡状态
  658. if balstat>0.5:
  659. bal_step=(self.bmstime[i+1]-self.bmstime[i]).total_seconds() #均衡步长
  660. bal_step=int(bal_step)
  661. if str(balstat) in dict_bal2.keys():
  662. dict_bal2[str(balstat)]=dict_bal2[str(balstat)]+bal_step
  663. else:
  664. dict_bal2[str(balstat)]=bal_step
  665. else:
  666. pass
  667. except:
  668. dict_bal2={}
  669. #判断充电状态
  670. if charging==0:
  671. if self.packcrnt[i]<=-1 and self.packcrnt[i+1]<=-1 and self.packcrnt[i-1]<=-1:
  672. if self.bms_soc[i]<40:
  673. cellvolt_now=self._cellvolt_get(i)
  674. if min(cellvolt_now)<self.param.CellFullChrgVolt-0.18:
  675. charging=1
  676. chrg_start=i
  677. else:
  678. pass
  679. else:
  680. pass
  681. else: #充电中
  682. cellvolt_now=self._cellvolt_get(i)
  683. if (self.bmstime[i+1]-self.bmstime[i]).total_seconds()>180 or (self.packcrnt[i]>-0.1 and self.packcrnt[i-1]>-0.1) or (self.packcrnt[i]<-self.param.Capacity and self.packcrnt[i+1]<-self.param.Capacity): #如果充电过程中时间间隔>180s,则舍弃该次充电
  684. charging=0
  685. continue
  686. elif min(cellvolt_now)>self.param.CellFullChrgVolt-0.15:
  687. self._celltemp_weight(i)
  688. if i-chrg_start>10 and self.celltemp>15:
  689. chrg_end=i+1
  690. charging=0
  691. #计算漏电流值...................................................................
  692. if firsttime2==1:
  693. firsttime2=0
  694. dict_baltime={}
  695. peaksoc_list=[]
  696. time = list(self.bmstime[chrg_start:chrg_end])
  697. packcrnt = list(self.packcrnt[chrg_start:chrg_end])
  698. soc = list(self.bms_soc[chrg_start:chrg_end])
  699. for j in range(1, self.param.CellVoltNums + 1):
  700. cellvolt = self._singlevolt_get(i,j,2) #取单体电压j的所有电压值
  701. cellvolt = list(cellvolt[chrg_start:chrg_end])
  702. peaksoc = self._dvdq_peak(time, soc, cellvolt, packcrnt)
  703. if peaksoc>1:
  704. peaksoc_list.append(peaksoc)
  705. else:
  706. break
  707. if len(peaksoc_list)==self.param.CellVoltNums:
  708. cellsocmean=(sum(peaksoc_list)-max(peaksoc_list)-min(peaksoc_list))/(len(peaksoc_list)-2)
  709. celldeltsoc=[x-cellsocmean for x in peaksoc_list] #计算每个电芯的soc差
  710. deltAs_last2=np.array(celldeltsoc)
  711. time_last2=self.bmstime[chrg_end]
  712. df_ram_last2.loc[0]=[self.sn,time_last2,deltAs_last2] #更新RAM信息
  713. else:
  714. dict_baltime={}
  715. peaksoc_list=[]
  716. time = list(self.bmstime[chrg_start:chrg_end])
  717. packcrnt = list(self.packcrnt[chrg_start:chrg_end])
  718. soc = list(self.bms_soc[chrg_start:chrg_end])
  719. for j in range(1, self.param.CellVoltNums + 1):
  720. cellvolt = self._singlevolt_get(i,j,2) #取单体电压j的所有电压值
  721. cellvolt = list(cellvolt[chrg_start:chrg_end])
  722. peaksoc = self._dvdq_peak(time, soc, cellvolt, packcrnt)
  723. if peaksoc>1:
  724. peaksoc_list.append(peaksoc)
  725. else:
  726. break
  727. if len(peaksoc_list)==self.param.CellVoltNums:
  728. cellsocmean=(sum(peaksoc_list)-max(peaksoc_list)-min(peaksoc_list))/(len(peaksoc_list)-2)
  729. celldeltsoc=[x-cellsocmean for x in peaksoc_list] #计算每个电芯的soc差
  730. deltAs_now2=np.array(celldeltsoc)
  731. time_now2=self.bmstime[chrg_end]
  732. list_sub2=deltAs_now2-deltAs_last2
  733. list_pud2=(3600*1000)/(time_now2-time_last2).total_seconds()
  734. leak_current2=list_sub2*list_pud2
  735. leak_current2=np.round(leak_current2,3)
  736. leak_current2=list(leak_current2)
  737. df_res.loc[len(df_res)]=[time_last2,time_now2,self.sn,3,str(leak_current2),str(dict_baltime)] #计算结果存入Dataframe
  738. deltAs_last2=deltAs_now2
  739. time_last2=time_now2
  740. dict_bal2={}
  741. df_ram_last2.loc[0]=[self.sn,time_last2,deltAs_last2] #更新RAM信息
  742. else:
  743. charging=0
  744. continue
  745. elif i==len(self.df_bms)-2: #数据中断后仍在充电,将前段充电数据写入RAM
  746. df_ram_lfp=self.df_bms.iloc[chrg_start:]
  747. df_ram_lfp['sn']=self.sn
  748. else:
  749. pass
  750. #更新RAM
  751. df_ram_last3.loc[0]=[self.sn,self.bmstime[len(self.bmstime)-1],standingtime,standingtime1,standingtime2]
  752. #返回结果
  753. if df_res.empty:
  754. return pd.DataFrame(), df_ram_last, df_ram_last1, df_ram_last2, df_ram_last3,df_ram_lfp
  755. else:
  756. return df_res, df_ram_last, df_ram_last1, df_ram_last2, df_ram_last3, df_ram_lfp