CBMSBatInterShort.py 47 KB

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