333 lines
10 KiB
C
333 lines
10 KiB
C
#include "kit_table.h"
|
|
|
|
#include "bms_soc.h"
|
|
#include "bms_sop.h"
|
|
#include "bms_fault.h"
|
|
#include "bms_di_do.h"
|
|
#include "bms_eeprom.h"
|
|
#include "bms_signal.h"
|
|
#include "bms_statistic.h"
|
|
#include "bms_run_status.h"
|
|
|
|
#include "table_comm.h"
|
|
|
|
typedef struct
|
|
{
|
|
bool is_chg_forbid;
|
|
bool is_dis_forbid;
|
|
uint8_t chg_tab_idx;
|
|
|
|
uint32_t chg_forbid_dly;
|
|
uint32_t dis_forbid_dly;
|
|
|
|
uint32_t chg_forbid_dly1;
|
|
uint32_t dis_forbid_dly1;
|
|
uint16_t rate_data[kSopData_End];
|
|
uint16_t sop_data[kSopData_End];
|
|
}SopItem;
|
|
|
|
SopItem sop_item;
|
|
|
|
|
|
uint16_t bms_get_sop_data(SopData idx)
|
|
{
|
|
uint16_t tmp = 0;
|
|
if(idx < kSopData_End)
|
|
{
|
|
tmp = sop_item.sop_data[idx];
|
|
}
|
|
return tmp;
|
|
}
|
|
|
|
typedef enum
|
|
{
|
|
kEndChgCurStep_Normal,
|
|
kEndChgCurStep_First,
|
|
kEndChgCurStep_Second,
|
|
kEndChgCurStep_Full,
|
|
kEndChgCurStep_Forbid,
|
|
kEndChgCurStep_End,
|
|
}EndChgCurStep;
|
|
|
|
|
|
void bms_analyse_chg_sop(uint32_t base_time)
|
|
{
|
|
static uint16_t dly = 0;
|
|
bool is_forbid_chg;
|
|
uint16_t fault_cur, end_cur, fault_power, end_power, req_volt, total_volt;
|
|
uint16_t soc, min_temp, max_temp;
|
|
int32_t min_temp_cur, max_temp_cur;
|
|
|
|
soc = bms_get_soc() / 100;
|
|
min_temp = (int32_t)bms_get_statistic_data(kStatisticData_MinTemp) /10 - 50;
|
|
max_temp = (int32_t)bms_get_statistic_data(kStatisticData_MaxTemp) /10 - 50;
|
|
total_volt = bms_get_statistic_data(kStatisticData_TotalVolt) > 300 ? bms_get_statistic_data(kStatisticData_TotalVolt):300;
|
|
|
|
if(bsp_eeprom_get_data(kEEData_ChgDisMode_HighVoltStrategy, kEepromDataType_High) == kChgMode_CP)
|
|
{
|
|
if((sop_item.chg_tab_idx > 0) && (sop_item.chg_tab_idx < kSopTab_End))
|
|
{
|
|
kit_table_bilinear_search((ThreeDTabItem*)sop_table_list[sop_item.chg_tab_idx - 1], soc, min_temp, &min_temp_cur); //功率表分辨率 0.1Kwh
|
|
kit_table_bilinear_search((ThreeDTabItem*)sop_table_list[sop_item.chg_tab_idx - 1], soc, max_temp, &max_temp_cur);
|
|
end_power = (min_temp_cur < max_temp_cur) ? min_temp_cur : max_temp_cur;
|
|
end_cur = (uint32_t)end_power * 10000/total_volt; //电流分辨率0.1A
|
|
|
|
}
|
|
else
|
|
{
|
|
end_power = sop_item.rate_data[kSopData_ChgPower];
|
|
end_cur = (uint32_t)sop_item.rate_data[kSopData_ChgPower] * 10000/total_volt;
|
|
}
|
|
}
|
|
else if(bsp_eeprom_get_data(kEEData_ChgDisMode_HighVoltStrategy, kEepromDataType_High) == kChgMode_CC)
|
|
{
|
|
if((sop_item.chg_tab_idx > 0) && (sop_item.chg_tab_idx < kSopTab_End))
|
|
{
|
|
kit_table_bilinear_search((ThreeDTabItem*)sop_table_list[sop_item.chg_tab_idx - 1], soc, min_temp, &min_temp_cur);
|
|
kit_table_bilinear_search((ThreeDTabItem*)sop_table_list[sop_item.chg_tab_idx - 1], soc, max_temp, &max_temp_cur);
|
|
//end_cur = (min_temp_cur < max_temp_cur) ? min_temp_cur : max_temp_cur;
|
|
|
|
sop_item.sop_data[kSopData_MapCur] = end_cur = (min_temp_cur < max_temp_cur) ? min_temp_cur : max_temp_cur;
|
|
|
|
end_power = (uint32_t)end_cur * total_volt/100;
|
|
|
|
}
|
|
else
|
|
{
|
|
end_cur = sop_item.rate_data[kSopData_ChgCur];
|
|
end_power = (uint32_t)end_cur * total_volt/100;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
end_cur = 0;
|
|
end_power = 0;
|
|
}
|
|
|
|
req_volt = sop_item.rate_data[kSopData_ChgVolt];
|
|
|
|
fault_cur = 0;
|
|
fault_power = 0;
|
|
is_forbid_chg = false;
|
|
//故障降流
|
|
if((bms_is_chg_allow() == false)
|
|
|| (bms_get_circuit_status(kCircuitType_Chg) == kCircuitStatus_Off))
|
|
{
|
|
if(bms_is_single_full_chg() == true)
|
|
{
|
|
//有故障任要发送禁充指令
|
|
if(bms_is_chg_circuit_allow() == false)
|
|
{
|
|
is_forbid_chg = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
is_forbid_chg = true;
|
|
}
|
|
}
|
|
else if(bms_get_soc_status() == kSocStatus_Full)
|
|
{
|
|
//满充再单簇校准模式下不上发禁充
|
|
if(bms_is_single_full_chg() == false)
|
|
{
|
|
is_forbid_chg = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fault_cur = (uint32_t)end_cur * bms_get_fault_cur_rate(kRunStatus_Chg) / 100;
|
|
fault_power = (uint32_t)end_power * bms_get_fault_cur_rate(kRunStatus_Chg) / 100;
|
|
}
|
|
//末端单体电压降流
|
|
if(bms_get_signal(kSignalIdx_Chg2ndCurDown) == kSignalStatus_High)
|
|
{
|
|
end_cur = (uint32_t)end_cur * bsp_eeprom_get_data(kEEData_ChgSnd_FstCurDownRate, kEepromDataType_High) / 100;
|
|
end_power = (uint32_t)end_power * bsp_eeprom_get_data(kEEData_ChgSnd_FstCurDownRate, kEepromDataType_High) / 100;
|
|
}
|
|
else if(bms_get_signal(kSignalIdx_Chg1stCurDown) == kSignalStatus_High)
|
|
{
|
|
end_cur = (uint32_t)end_cur * bsp_eeprom_get_data(kEEData_ChgSnd_FstCurDownRate, kEepromDataType_Low) / 100;
|
|
end_power = (uint32_t)end_power * bsp_eeprom_get_data(kEEData_ChgSnd_FstCurDownRate, kEepromDataType_Low) / 100;
|
|
}
|
|
|
|
|
|
if(fault_cur > end_cur)
|
|
{
|
|
fault_cur = end_cur;
|
|
}
|
|
|
|
if(fault_power > end_power)
|
|
{
|
|
fault_power = end_power;
|
|
}
|
|
|
|
sop_item.sop_data[kSopData_ChgCur] = fault_cur;
|
|
sop_item.sop_data[kSopData_ChgPower] = fault_power;
|
|
|
|
|
|
if((fault_cur == 0) && (is_forbid_chg == true))
|
|
{
|
|
dly += base_time;
|
|
if(dly >= 500)
|
|
{
|
|
dly = 500;
|
|
if(bms_get_fault_cur_rate(kRunStatus_Chg) != 0)
|
|
{
|
|
sop_item.chg_forbid_dly = bsp_eeprom_get_data(kEEData_ForbidChgRelDelay, kEepromDataType_Full) * 6000;
|
|
}
|
|
|
|
sop_item.chg_forbid_dly1 = 0;
|
|
sop_item.is_chg_forbid = true;
|
|
bms_set_signal(kSignalIdx_ForbidChg, kSignalStatus_High);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dly = 0;
|
|
}
|
|
if(sop_item.is_chg_forbid == true)
|
|
{
|
|
sop_item.chg_forbid_dly += base_time;
|
|
sop_item.chg_forbid_dly1 += base_time;
|
|
sop_item.sop_data[kSopData_ChgCur] = sop_item.sop_data[kSopData_ChgPower] = 0;
|
|
if((sop_item.chg_forbid_dly1 >= 2000) && (sop_item.chg_forbid_dly >= bsp_eeprom_get_data(kEEData_ForbidChgRelDelay, kEepromDataType_Full) * 6000))
|
|
{
|
|
sop_item.is_chg_forbid = false;
|
|
sop_item.chg_forbid_dly1 = 2000;
|
|
sop_item.chg_forbid_dly = bsp_eeprom_get_data(kEEData_ForbidChgRelDelay, kEepromDataType_Full) * 6000;
|
|
bms_set_signal(kSignalIdx_ForbidChg, kSignalStatus_Low);
|
|
}
|
|
}
|
|
|
|
sop_item.sop_data[kSopData_ChgVolt] = req_volt;
|
|
}
|
|
|
|
void bms_set_dis_forbid_status(void)
|
|
{
|
|
sop_item.dis_forbid_dly = 0;
|
|
sop_item.is_dis_forbid = true;
|
|
bms_set_signal(kSignalIdx_ForbidDis, kSignalStatus_High);
|
|
}
|
|
|
|
void bms_set_chg_forbid_status(void)
|
|
{
|
|
sop_item.chg_forbid_dly = 0;
|
|
sop_item.is_chg_forbid = true;
|
|
bms_set_signal(kSignalIdx_ForbidChg, kSignalStatus_High);
|
|
}
|
|
|
|
void bms_analyse_dis_sop(uint32_t base_time)
|
|
{
|
|
static uint16_t dly;
|
|
uint16_t fault_cur, end_cur, fault_power, end_power,total_volt;
|
|
total_volt = bms_get_statistic_data(kStatisticData_TotalVolt) > 500 ? bms_get_statistic_data(kStatisticData_TotalVolt):500;
|
|
|
|
if(bsp_eeprom_get_data(kEEData_ChgDisMode_HighVoltStrategy, kEepromDataType_High) == kChgMode_CP)
|
|
{
|
|
end_power = fault_power = sop_item.rate_data[kSopData_DisPower];
|
|
end_cur = fault_cur = (uint32_t)sop_item.rate_data[kSopData_DisPower] * 10000 /total_volt;
|
|
}
|
|
else if(bsp_eeprom_get_data(kEEData_ChgDisMode_HighVoltStrategy, kEepromDataType_High) == kChgMode_CC)
|
|
{
|
|
end_power = fault_power = (uint32_t)sop_item.rate_data[kSopData_DisCur] * total_volt /100;
|
|
end_cur = fault_cur = sop_item.rate_data[kSopData_DisCur];
|
|
}
|
|
else
|
|
{
|
|
end_power = 0;
|
|
end_cur = 0;
|
|
}
|
|
//故障降流
|
|
if((bms_is_dis_allow() == false)
|
|
|| (bms_get_soc_status() == kSocStatus_Empty)
|
|
|| (bms_get_circuit_status(kCircuitType_Dis) == kCircuitStatus_Off) )
|
|
{
|
|
fault_cur = 0;
|
|
fault_power = 0;
|
|
}
|
|
else
|
|
{
|
|
fault_cur = (uint32_t)fault_cur * bms_get_fault_cur_rate(kRunStatus_Dis) / 100;
|
|
fault_power = (uint32_t)fault_power * bms_get_fault_cur_rate(kRunStatus_Dis) / 100;
|
|
}
|
|
|
|
if(fault_cur > end_cur)
|
|
{
|
|
fault_cur = end_cur;
|
|
}
|
|
|
|
if(fault_power > end_power)
|
|
{
|
|
fault_power = end_power;
|
|
}
|
|
sop_item.sop_data[kSopData_DisCur] = fault_cur;
|
|
sop_item.sop_data[kSopData_DisPower] = fault_power;
|
|
|
|
|
|
if(fault_cur == 0)
|
|
{
|
|
dly += base_time;
|
|
if(dly >= 500)
|
|
{
|
|
dly = 500;
|
|
if(bms_get_fault_cur_rate(kRunStatus_Dis) != 0)
|
|
{
|
|
sop_item.dis_forbid_dly = bsp_eeprom_get_data(kEEData_ForbidDisRelDelay, kEepromDataType_Full) * 6000;
|
|
}
|
|
sop_item.dis_forbid_dly1 = 0;
|
|
sop_item.is_dis_forbid = true;
|
|
bms_set_signal(kSignalIdx_ForbidDis, kSignalStatus_High);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dly = 0;
|
|
}
|
|
|
|
if(sop_item.is_dis_forbid == true)
|
|
{
|
|
sop_item.dis_forbid_dly += base_time;
|
|
sop_item.dis_forbid_dly1 += base_time;
|
|
sop_item.sop_data[kSopData_DisCur] = sop_item.sop_data[kSopData_DisPower] = 0;
|
|
if((sop_item.dis_forbid_dly1 >= 2000)
|
|
&& (sop_item.dis_forbid_dly >= bsp_eeprom_get_data(kEEData_ForbidDisRelDelay, kEepromDataType_Full) * 6000))
|
|
{
|
|
sop_item.is_dis_forbid = false;
|
|
sop_item.dis_forbid_dly1 = 2000;
|
|
sop_item.dis_forbid_dly = bsp_eeprom_get_data(kEEData_ForbidDisRelDelay, kEepromDataType_Full) * 6000;
|
|
bms_set_signal(kSignalIdx_ForbidDis, kSignalStatus_Low);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void bms_poll_sop(uint32_t base_time)
|
|
{
|
|
bms_analyse_dis_sop(base_time);
|
|
bms_analyse_chg_sop(base_time);
|
|
}
|
|
|
|
|
|
void bms_init_sop(void)
|
|
{
|
|
sop_item.chg_tab_idx = bsp_eeprom_get_data(kEEData_Sop_OcvIndex, kEepromDataType_High);
|
|
if(bsp_eeprom_get_data(kEEData_ChgDisMode_HighVoltStrategy, kEepromDataType_High) == kChgMode_CP)
|
|
{
|
|
sop_item.rate_data[kSopData_DisPower] = bsp_eeprom_get_data(kEEData_RatedDisPower, kEepromDataType_Full);
|
|
sop_item.rate_data[kSopData_ChgPower] = bsp_eeprom_get_data(kEEData_RatedChgPower, kEepromDataType_Full);
|
|
}
|
|
else if(bsp_eeprom_get_data(kEEData_ChgDisMode_HighVoltStrategy, kEepromDataType_High) == kChgMode_CC)
|
|
{
|
|
sop_item.rate_data[kSopData_DisCur] = bsp_eeprom_get_data(kEEData_RatedDisCur, kEepromDataType_Full);
|
|
sop_item.rate_data[kSopData_ChgCur] = bsp_eeprom_get_data(kEEData_RatedChgCur, kEepromDataType_Full);
|
|
}
|
|
else
|
|
{
|
|
;
|
|
}
|
|
sop_item.rate_data[kSopData_ChgVolt] = bsp_eeprom_get_data(kEEData_ReqCghVolt, kEepromDataType_Full);
|
|
}
|
|
|