123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- # 获取数据
- from LIB.BACKEND import DBManager
- import os
- import pandas as pd
- import numpy as np
- import datetime
- # import matplotlib.pyplot as plt
- #参数输入
- Capacity = 54
- PackFullChrgVolt=69.99
- CellFullChrgVolt=3.5
- CellVoltNums=20
- CellTempNums=4
- FullChrgSoc=98
- PeakSoc=57
- # #40Ah-OCV
- # LookTab_SOC = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100]
- # LookTab_OCV = [3.3159, 3.4502, 3.4904, 3.5277, 3.5590, 3.5888, 3.6146, 3.6312, 3.6467, 3.6642, 3.6865, 3.7171, 3.7617,
- # 3.8031, 3.8440, 3.8888, 3.9376, 3.9891, 4.0451, 4.1068, 4.1830]
- #55Ah-OCV
- LookTab_SOC = [0.00, 2.40, 6.38, 10.37, 14.35, 18.33, 22.32, 26.30, 30.28, 35.26, 40.24, 45.22, 50.20, 54.19, 58.17, 60.16, 65.14, 70.12, 75.10, 80.08, 84.06, 88.05, 92.03, 96.02, 100.00]
- LookTab_OCV = [2.7151, 3.0298, 3.1935, 3.2009, 3.2167, 3.2393, 3.2561, 3.2703, 3.2843, 3.2871, 3.2874, 3.2868, 3.2896, 3.2917, 3.2967, 3.3128, 3.3283, 3.3286, 3.3287, 3.3288, 3.3289, 3.3296, 3.3302, 3.3314, 3.3429]
- #定义滑动滤波函数
- def np_move_avg(a, n, mode="same"):
- return (np.convolve(a, np.ones((n,)) / n, mode=mode))
- #参数初始化
- dvdq_soh=[]
- dvdq_soh_err=[]
- bms_soh=[]
- dvdq_time=[]
- dvdq_sohcfd=[]
- sn_list=[]
- #获取数据时间段
- now_time=datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- now_time=datetime.datetime.strptime(now_time,'%Y-%m-%d %H:%M:%S')
- start_time=now_time-datetime.timedelta(days=30)
- end_time=str(now_time)
- strat_time=str(start_time)
- #输入一个含有‘SN号’的xlsx
- SNdata = pd.read_excel('骑享资产梳理-20210621.xlsx', sheet_name='6060')
- SNnums=SNdata['SN号']
- for k in range(15):
-
- SNnum=str(SNnums[k])
- sn = SNnum
- st = '2021-07-06 00:00:00'
- et = '2021-07-07 20:00:00'
- dbManager = DBManager.DBManager()
- df_data = dbManager.get_data(sn=sn, start_time=st, end_time=et, data_groups=['bms'])
- data = df_data['bms']
- packcrnt=data['总电流[A]']
- packvolt=data['总电压[V]']
- SOC=data['SOC[%]']
- SOH=data['SOH[%]']
- bmsstat=data['充电状态']
- time= pd.to_datetime(data['时间戳'], format='%Y-%m-%d %H:%M:%S')
- #第一步:筛选充电数据
- ChgStart=[]
- ChgEnd=[]
- for i in range(3, len(time) - 3):
- if i==3 and bmsstat[i]==2 and bmsstat[i+1]==2 and bmsstat[i+2]==2:
- ChgStart.append(i)
- elif bmsstat[i-2]!=2 and bmsstat[i-1]!=2 and bmsstat[i]==2:
- ChgStart.append(i)
- elif bmsstat[i-1]==2 and bmsstat[i]!=2 and bmsstat[i+1]!=2:
- ChgEnd.append(i)
- elif i == (len(time) - 4) and bmsstat[len(bmsstat)-1] == 2 and bmsstat[len(bmsstat)-2] == 2:
- ChgEnd.append(len(time)-1)
- #第二步:筛选充电起始Soc<48%,电芯温度>15℃,且满充的数据
- ChgStartValid1=[]
- ChgEndValid1=[]
- ChgStartValid2=[]
- ChgEndValid2=[]
- for i in range(min(len(ChgStart),len(ChgEnd))):
- #获取最小温度值
- celltemp = []
- for j in range(1, CellTempNums+1):
- s = str(j)
- temp = data['单体温度' + s]
- celltemp.append(temp[ChgEnd[i]])
- #寻找最大电压值
- cellvolt = []
- for j in range(1, CellVoltNums+1):
- s = str(j)
- volt = max(data['单体电压' + s][ChgStart[i]:ChgEnd[i]]/1000)
- cellvolt.append(volt)
- #筛选满足2点法计算的数据
- StandingTime=0
- if max(cellvolt)>CellFullChrgVolt and SOC[ChgStart[i]]<30 and min(celltemp)>5:
- for k in reversed(range(ChgStart[i])):
- if abs(packcrnt[k - 2]) < 0.01:
- StandingTime = StandingTime + (time[k] - time[k-1]).total_seconds()
- if StandingTime > 600: # 筛选静置时间>10min
- ChgStartValid1.append(ChgStart[i])
- ChgEndValid1.append(ChgEnd[i])
- break
- else:
- break
- #筛选满足DV/DQ方法的数据
- if max(cellvolt)>CellFullChrgVolt and SOC[ChgStart[i]]<45 and min(celltemp)>5:
- if ((time[ChgEnd[i]]-time[ChgStart[i]]).total_seconds())/(ChgEnd[i]-ChgStart[i])<60:
- ChgStartValid2.append(ChgStart[i])
- ChgEndValid2.append(ChgEnd[i])
- #第三步:计算充电Soc和Soh
- # 两点法计算soh
- Soc=[]
- Time=[]
- Soc_Err=[]
- Bms_Soc=[]
- Soh1=[]
- Time1=[]
- Bms_Soh1=[]
- Soh_Err1=[]
- for i in range(len(ChgStartValid1)):
- #寻找最大电压值
- cellvolt = []
- for j in range(1, CellVoltNums+1):
- s = str(j)
- volt = max(data['单体电压' + s])
- cellvolt.append(volt)
- voltmax_index = cellvolt.index(max(cellvolt)) + 1
- cellvolt = data['单体电压' + str(voltmax_index)] / 1000
- #soc
- Soc.append(np.interp(cellvolt[ChgStartValid1[i]-3],LookTab_OCV,LookTab_SOC))
- Time.append(time[ChgStartValid1[i]-3])
- Bms_Soc.append(SOC[ChgStartValid1[i]-3])
- Soc_Err.append(Bms_Soc[-1]-Soc[-1])
- #soh
- Ocv_Soc=np.interp(cellvolt[ChgStartValid1[i]-3],LookTab_OCV,LookTab_SOC)
- Ah=0
- for j in range(ChgStartValid1[i],ChgEndValid1[i]):
- #计算soc
- Step=(time[j]-time[j-1]).total_seconds()
- Time.append(time[j])
- Bms_Soc.append(SOC[j])
- if Soc[-1]-(packcrnt[j]*Step*100)/(3600*Capacity)<100:
- Soc.append(Soc[-1]-(packcrnt[j]*Step*100)/(3600*Capacity))
- else:
- Soc.append(100)
- Soc_Err.append(Bms_Soc[-1] - Soc[-1])
- #两点法计算soh
- Ah=Ah-packcrnt[j]*Step/3600
- Soh1.append(Ah*100/((FullChrgSoc-Ocv_Soc)*0.01*Capacity))
- Bms_Soh1.append(SOH[i])
- Soh_Err1.append(Bms_Soh1[-1]-Soh1[-1])
- Time1.append(time[ChgStartValid1[i]])
- # DV/DQ法计算soh
- Soh2=[]
- Time2=[]
- Bms_Soh2=[]
- Soh_Err2=[]
- SohCfd = []
- sn_list=[]
- for i in range(len(ChgStartValid2)):
- #寻找最大电压值
- cellvolt1 = []
- cellvolt=[]
- for j in range(1, CellVoltNums+1):
- s = str(j)
- volt = data['单体电压' + s]
- cellvolt1.append(volt[ChgEndValid2[i]])
- voltmax1_index = cellvolt1.index(max(cellvolt1)) + 1
- cellvolt1 = data['单体电压' + str(voltmax1_index)] / 1000
- #电压采用滑动平均滤波
- cellvolt=np_move_avg(cellvolt1, 3, mode="same")
- #参数赋初始值
- Ah = 0
- Volt = cellvolt[ChgStartValid2[i]]
- DV_Volt=[]
- DQ_Ah = []
- DVDQ = []
- time2 = []
- soc2 = []
- Ah_tatal=[0]
- xvolt=[]
- #计算DV和DQ值
- for j in range(ChgStartValid2[i],ChgEndValid2[i]):
- Step=(time[j+1]-time[j]).total_seconds()
- Ah=Ah-packcrnt[j]*Step/3600
- if (cellvolt[j]-Volt)>0.0009 and Ah>0:
- Ah_tatal.append(Ah_tatal[-1]+Ah)
- DQ_Ah.append(Ah)
- DV_Volt.append(cellvolt[j]-Volt)
- DVDQ.append((DV_Volt[-1])/DQ_Ah[-1])
- xvolt.append(cellvolt[j])
- Volt=cellvolt[j]
- Ah = 0
- time2.append(time[j])
- soc2.append(SOC[j])
- #切片Soc>50且Soc<80
- Data1 = pd.DataFrame({'SOC': soc2,
- 'DVDQ': DVDQ,
- 'Ah_tatal': Ah_tatal[:-1],
- 'DQ_Ah':DQ_Ah,
- 'DV_Volt':DV_Volt,
- 'XVOLT':xvolt})
- Data1=Data1[(Data1['SOC']>50) & (Data1['SOC']<80)]
- #寻找峰值并计算Soh和置信度
- # 获取最小温度值
- celltemp = []
- for j in range(1, CellTempNums+1):
- s = str(j)
- temp = data['单体温度' + s]
- celltemp.append(temp[ChgStartValid2[i]])
- if len(Data1['DVDQ'])>1:
- PeakIndex=Data1['DVDQ'].idxmax()
- #筛选峰值点附近±0.5%SOC内的数据
- Data2=Data1[(Data1['SOC']>(Data1['SOC'][PeakIndex]-0.5)) & (Data1['SOC']<(Data1['SOC'][PeakIndex]+0.5))]
- if len(Data2)>2:
- Ah_tatal1 = Data1['Ah_tatal']
- DVDQ = Data1['DVDQ']
- soc2 = Data1['SOC']
- xvolt = Data1['XVOLT']
- if soc2[PeakIndex]>50 and soc2[PeakIndex]<80:
- DVDQ_SOH=(Ah_tatal[-1]-Ah_tatal1[PeakIndex]) * 100 / ((FullChrgSoc - PeakSoc) * 0.01 * Capacity)
- if DVDQ_SOH<95:
- DVDQ_SOH=DVDQ_SOH*0.3926+58.14
- if DVDQ_SOH>70 and DVDQ_SOH<120:
- Soh2.append(DVDQ_SOH)
- Bms_Soh2.append(SOH[ChgStartValid2[i]])
- Soh_Err2.append(Bms_Soh2[-1] - Soh2[-1])
- Time2.append(time[ChgStartValid2[i]])
- sn_list.append(SNnum)
- #计算置信度
- if min(celltemp)<10:
- SohCfd.append(50)
- elif min(celltemp)<20:
- SohCfd.append(80)
- else:
- SohCfd.append(100)
- else:
- Data1=Data1.drop([PeakIndex])
- PeakIndex = Data1['DVDQ'].idxmax()
- Data2 = Data1[(Data1['SOC'] > (Data1['SOC'][PeakIndex] - 0.5)) & (Data1['SOC'] < (Data1['SOC'][PeakIndex] + 0.5))]
- if len(Data2) > 3:
- Ah_tatal1 = Data1['Ah_tatal']
- DVDQ = Data1['DVDQ']
- soc2 = Data1['SOC']
- xvolt = Data1['XVOLT']
- if soc2[PeakIndex]>50 and soc2[PeakIndex]<80:
- DVDQ_SOH=(Ah_tatal[-1]-Ah_tatal1[PeakIndex]) * 100 / ((FullChrgSoc - PeakSoc) * 0.01 * Capacity)
- if DVDQ_SOH<95:
- DVDQ_SOH=DVDQ_SOH*0.3926+58.14
- if DVDQ_SOH>70 and DVDQ_SOH<120:
- Soh2.append(DVDQ_SOH)
- Bms_Soh2.append(SOH[ChgStartValid2[i]])
- Soh_Err2.append(Bms_Soh2[-1] - Soh2[-1])
- Time2.append(time[ChgStartValid2[i]])
- sn_list.append(SNnum)
- #计算置信度
- if min(celltemp)<10:
- SohCfd.append(50)
- elif min(celltemp)<20:
- SohCfd.append(80)
- else:
- SohCfd.append(100)
- #处理数据
- if len(Soh2)>5:
- Soh2=np_move_avg(Soh2,5,mode="valid")
- result_soh2={'时间': Time2[4::],
- 'SN号':sn_list[4::],
- 'BMS_SOH': Bms_Soh2[4::],
- 'SOH': Soh2,
- 'SOH误差': Soh_Err2[4::]}
- else:
- result_soh2={'时间': Time2,
- 'SN号':sn_list,
- 'BMS_SOH': Bms_Soh2,
- 'SOH': Soh2,
- 'SOH误差': Soh_Err2}
- #第四步:将数据存入Excel
- Result_Soh2=pd.DataFrame(result_soh2)
- Result_Soh2.to_csv('BMS_SOH_'+SNnum+'.csv',encoding='GB18030')
|