CBMSBatChrg.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. import pandas as pd
  2. import numpy as np
  3. import bisect
  4. import datetime
  5. import matplotlib.pyplot as plt
  6. import matplotlib.dates as mdates
  7. import BatParam
  8. class BatChrg:
  9. def __init__(self,sn,celltype,df_bms,df_volt,df_temp,df_accum): #参数初始化
  10. self.sn=sn
  11. self.celltype=celltype
  12. self.param=BatParam.BatParam(celltype)
  13. self.df_volt=df_volt
  14. self.df_temp=df_temp
  15. self.df_bms=df_bms
  16. self.packcrnt=(df_volt['可充电储能装置电流(A)'].astype('float'))*self.param.PackCrntDec
  17. self.packvolt=df_volt['可充电储能装置电压(V)'].astype('float')
  18. self.bms_soc=df_bms['SOC']
  19. self.bmsstat=df_bms['充电状态']
  20. self.bmstime= pd.to_datetime(df_volt['上报时间'], format='%Y-%m-%d %H:%M:%S')
  21. self.param.CellVoltNums=int(df_volt.loc[5,'单体电池总数'])
  22. self.param.CellTempNums=int(df_temp.loc[5,'可充电储能温度探针个数'])
  23. self.param.PackVoltOvLv1=self.param.CellOvLv1*self.param.CellVoltNums
  24. self.param.PackVoltOvLv2=self.param.CellOvLv2*self.param.CellVoltNums
  25. self.param.PackVoltUvLv1=self.param.CellUvLv1*self.param.CellVoltNums
  26. self.param.PackVoltUvLv2=self.param.CellUvLv2*self.param.CellVoltNums
  27. def chrg(self):
  28. if self.celltype==1 or self.celltype==2 or self.celltype==3 or self.celltype==4 or self.celltype==100:
  29. df_res=self._ncm_chrg()
  30. return df_res
  31. elif self.celltype==99:
  32. df_res=self._lfp_diag()
  33. return df_res
  34. else:
  35. return pd.DataFrame()
  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_get(self,num):
  41. celltemp = []
  42. for j in range(1, self.param.CellTempNums+1):
  43. celltemp.append(self.df_temp.loc[num,str(j)+'.0'])
  44. return celltemp
  45. #获取当前行所有电压数据........................................................................................
  46. def _cellvolt_get(self,num):
  47. cellvolt=[]
  48. for j in range(1, self.param.CellVoltNums+1):
  49. cellvolt.append(self.df_volt.loc[num, str(j)+'.0'])
  50. return cellvolt
  51. #筛选充电数据..............................................................................................................................
  52. def _chrgdata(self):
  53. self.ChgStart=[]
  54. self.ChgEnd=[]
  55. if len(self.packvolt)>100:
  56. charging=0
  57. for i in range(3, len(self.bmstime) - 3):
  58. if charging==0:
  59. if i==3 and self.bmsstat[i]=='停车充电' and self.bmsstat[i+1]=='停车充电':
  60. self.ChgStart.append(i)
  61. charging=1
  62. elif self.bmsstat[i-1]!='停车充电' and self.bmsstat[i]=='停车充电':
  63. self.ChgStart.append(i)
  64. charging=1
  65. else:
  66. pass
  67. else:
  68. if (self.bmsstat[i-1]=='停车充电' or '充电完成') and self.packcrnt[i]>0:
  69. self.ChgEnd.append(i)
  70. charging=0
  71. elif i == (len(self.bmstime) - 4) and (self.bmsstat[i] == '停车充电' or '充电完成') and self.packcrnt[i]<-1:
  72. self.ChgEnd.append(len(self.bmstime)-2)
  73. charging=0
  74. #dvdq方法计算soh...........................................................................................................................
  75. def _dvdq_soh(self, chrg_st, chrg_end,cellvolt):
  76. Ah = 0 #参数赋初始值
  77. Volt = cellvolt[chrg_st]
  78. DV_Volt=[]
  79. DQ_Ah = []
  80. DVDQ = []
  81. time2 = []
  82. soc2 = []
  83. Ah_tatal=[0]
  84. xvolt=[]
  85. #计算DV和DQ值
  86. for j in range(chrg_st,chrg_end):
  87. Step=(self.bmstime[j+1]-self.bmstime[j]).total_seconds()
  88. Ah=Ah-self.packcrnt[j]*Step/3600
  89. if (cellvolt[j]-Volt)>0.002 and Ah>0:
  90. Ah_tatal.append(Ah_tatal[-1]+Ah)
  91. DQ_Ah.append(Ah)
  92. DV_Volt.append(cellvolt[j]-Volt)
  93. DVDQ.append((DV_Volt[-1])/DQ_Ah[-1])
  94. xvolt.append(cellvolt[j])
  95. Volt=cellvolt[j]
  96. Ah = 0
  97. time2.append(self.bmstime[j])
  98. soc2.append(float(self.bms_soc[j].strip('%')))
  99. #切片,去除前后10min的数据
  100. df_Data1 = pd.DataFrame({'time': time2,
  101. 'SOC': soc2,
  102. 'DVDQ': DVDQ,
  103. 'Ah_tatal': Ah_tatal[:-1],
  104. 'DQ_Ah':DQ_Ah,
  105. 'DV_Volt':DV_Volt,
  106. 'XVOLT':xvolt})
  107. start_time=df_Data1.loc[0,'time']
  108. start_time=start_time+datetime.timedelta(seconds=900)
  109. end_time=df_Data1.loc[len(time2)-1,'time']
  110. end_time=end_time-datetime.timedelta(seconds=600)
  111. # if soc2[0]<36:
  112. # df_Data1=df_Data1[(df_Data1['SOC']>40) & (df_Data1['SOC']<80)]
  113. # else:
  114. df_Data1=df_Data1[(df_Data1['time']>start_time) & (df_Data1['time']<end_time)]
  115. # df_Data1=df_Data1[(df_Data1['XVOLT']>self.param.PeakVoltLowLmt) & (df_Data1['XVOLT']<self.param.PeakVoltUpLmt)]
  116. # plt.figure()
  117. # print(self.packcrnt[int((chrg_st+chrg_end)/2)], min(self.celltemp))
  118. # ax1 = plt.subplot(3, 1, 1)
  119. # plt.plot(df_Data1['XVOLT'],df_Data1['DVDQ'],'r*-')
  120. # plt.xlabel('Volt/V')
  121. # plt.ylabel('DV/DQ')
  122. # plt.legend()
  123. ax1 = plt.subplot(2, 1, 1)
  124. plt.plot(df_Data1['SOC'],df_Data1['XVOLT'],'y*-')
  125. plt.xlabel('SOC/%')
  126. plt.ylabel('Volt/V')
  127. plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
  128. plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
  129. plt.legend()
  130. ax1 = plt.subplot(2, 1, 2)
  131. plt.plot(df_Data1['SOC'], df_Data1['DVDQ'], 'r*-')
  132. plt.xlabel('SOC/%')
  133. plt.ylabel('析锂指标')
  134. plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
  135. plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
  136. plt.legend()
  137. # plt.show()
  138. #..........................................三元电池充电画像.....................。。。......................................
  139. def _ncm_chrg(self):
  140. if not self.df_volt.empty:
  141. self._chrgdata()
  142. print(self.ChgStart,self.ChgEnd)
  143. # name=str(self.sn)
  144. # with pd.ExcelWriter(r'D:\00WorkSpace\01Python\data_analyze_platform\USER\03hezhong\99Result\\'+name+'.xlsx') as writer:
  145. for i in range(len(self.ChgStart)):
  146. # df_chgvolt=pd.DataFrame()
  147. # chrg_time=self.df_volt['上报时间'][self.ChgStart[i]:self.ChgEnd[i]]
  148. # chrg_soc=self.df_bms['SOC'][self.ChgStart[i]:self.ChgEnd[i]]
  149. # chrg_crnt=self.df_bms['总电流(A)'][self.ChgStart[i]:self.ChgEnd[i]]
  150. for k in range(1, self.param.CellVoltNums+1):
  151. s = str(k)
  152. cellvolt = self.df_volt[s+'.0']
  153. self._dvdq_soh(self.ChgStart[i],self.ChgEnd[i],cellvolt) #dvdq计算soh
  154. plt.show()
  155. # plt.figure(figsize=(20,10))
  156. # ax1 = plt.subplot(3, 1, 1)
  157. # plt.plot(chrg_soc,'y*-')
  158. # plt.ylabel('SOC/A')
  159. # plt.legend()
  160. # plt.title(str(self.sn)+str(self.df_volt.loc[self.ChgStart[i],'上报时间']))
  161. # ax2 = plt.subplot(3, 1, 2)
  162. # plt.plot(chrg_crnt,'y*-')
  163. # plt.ylabel('Crnt/A')
  164. # plt.legend()
  165. # for j in range(1, self.param.CellTempNums+1):
  166. # celltemp=self.df_temp[str(j)+'.0'][self.ChgStart[i]:self.ChgEnd[i]]
  167. # ax3 = plt.subplot(3, 1, 3)
  168. # plt.plot(celltemp,'y*-')
  169. # plt.xlabel('time')
  170. # plt.ylabel('Temp/℃')
  171. # plt.legend()
  172. # plt.savefig('./'+str(self.sn)+str(i)+'电流温度.png')
  173. # plt.figure()
  174. # for j in range(1, self.param.CellVoltNums+1):
  175. # cellvolt=self.df_volt[str(j)+'.0'][self.ChgStart[i]:self.ChgEnd[i]]
  176. # df_chgvolt[j]=cellvolt
  177. # df_chgvolt.plot(linestyle=':',marker='*', figsize=(30,10))
  178. # plt.title(str(self.sn)+str(self.df_volt.loc[self.ChgStart[i],'上报时间']))
  179. # plt.savefig('./'+str(self.sn)+str(i)+'电压.png')
  180. # if j <13:
  181. # color1='r'
  182. # elif j<25:
  183. # color1='orange'
  184. # elif j<37:
  185. # color1='y'
  186. # elif j<49:
  187. # color1='g'
  188. # elif j<61:
  189. # color1='c'
  190. # elif j<73:
  191. # color1='b'
  192. # elif j<85:
  193. # color1='m'
  194. # else:
  195. # color1='pink'
  196. # cellvolt=self.df_volt[str(j)+'.0'][self.ChgStart[i]:self.ChgEnd[i]]
  197. # # ax1 = plt.subplot(3, 1, 1)
  198. # plt.plot(chrg_time,cellvolt,color=color1,linestyle='-',marker='*')
  199. # plt.xlabel('SOC/%')
  200. # plt.ylabel('Volt/V')
  201. # plt.legend(loc='upper left')
  202. # plt.title(str(self.sn)+str(self.df_volt.loc[self.ChgStart[i],'上报时间']))
  203. # 标准差计算及电芯电压排序...................................................................................
  204. # std_error=[]
  205. # df_rank=pd.DataFrame(columns=list(range(1,self.param.CellVoltNums+1)))
  206. # for j in range(self.ChgStart[i],self.ChgEnd[i]):
  207. # cellvolt=self._cellvolt_get(j)
  208. # std_error.append(np.std(cellvolt,ddof=1)) #标准差计算
  209. # cellvolt=pd.Series(cellvolt)
  210. # cellvolt_rank=(cellvolt.rank(method='min')).tolist()
  211. # df_rank.loc[len(df_rank)]=cellvolt_rank
  212. # for j in range(1,self.param.CellVoltNums+1):
  213. # df_rank[j].plot(linestyle='-',marker='*')
  214. # # plt.legend()
  215. # # plt.title(str(self.sn)+str(self.df_volt.loc[self.ChgStart[i],'上报时间']))
  216. # # plt.savefig('./'+str(self.sn)+str(i)+'电压排名.png')
  217. # # plt.show()
  218. # sheetname=str(self.df_volt.loc[self.ChgStart[i],'上报时间']).replace(':','-')
  219. # df_rank.to_excel(writer,sheet_name=sheetname)
  220. # writer.save()
  221. # writer.close()
  222. # plt.figure(figsize=(20,10))
  223. # plt.plot(std_error,'r*-')
  224. # plt.xlabel('time')
  225. # plt.ylabel('std_error')
  226. # plt.legend()
  227. # plt.title(str(self.sn)+str(self.df_volt.loc[self.ChgStart[i],'上报时间']))
  228. # plt.savefig('./'+str(self.sn)+str(i)+'标准差.png')
  229. return pd.DataFrame()