forked from gary/BCU
2
0
Fork 0
BCU/app/stm32fxxx_app/app/logic_same_circuit_ctrl.c

313 lines
11 KiB
C
Raw Normal View History

2024-11-26 15:52:49 +08:00
#include "iso_check.h"
#include "version_manager.h"
#include "fault_manager.h"
#include "signal_manager.h"
#include "dido_manager.h"
#include "eeprom_manager.h"
#include "hv_adc_manager.h"
#include "logic_ctrl.h"
//确保在继电器断开时调用
bool logic_adhesion_check(uint32_t base_time, DoType type)
{
static uint16_t adhesion_dly = 0;
bool is_chekc = true;
uint16_t tv, hv, rate;
FaultLevel fault = kFaultLevel_Normal;
DoErrSrc do_err_src = bms_get_do_err_src(type);
//do_err_src += 1;
if(bms_get_run_status() == kRunStatus_Init)
{
return false;
}
switch(do_err_src)
{
case kDoErrSrc_HV1:
case kDoErrSrc_HV2:
//母线簇用电压检测粘连
tv = bms_get_high_volt(kHvType_Bat);
if((tv >= 300) && (bms_get_circuit_cmd_status() == kCircuitStatus_On))
{
if(bms_get_bus_bar_bcu() == bms_get_tag_data(kTagData_DevAddr))
{
hv = bms_get_high_volt((HvType)(kHvType_Hv1 + do_err_src - 1));
rate = get_eeprom_data(kEep_HV2_HV1VoltRate, (EepromDataType)(kEepromDataType_Low + do_err_src - 1));
if(hv >= ((uint32_t)tv * rate / 100))
{
fault = kFaultLevel_Third;
}
}
}
else
{
is_chekc = false;
}
break;
case kDoErrSrc_DI1:
case kDoErrSrc_DI2:
case kDoErrSrc_DI3:
case kDoErrSrc_DI4:
case kDoErrSrc_DI5:
case kDoErrSrc_DI6:
case kDoErrSrc_DI7:
case kDoErrSrc_DI8:
case kDoErrSrc_DI9:
//if(bms_get_signal((SignalIdx)(do_err_src - kDoErrSrc_DI1)) == kSignalStatus_High)
if(bms_get_signal((SignalIdx)(do_err_src - kDoErrSrc_DI1)) != bms_get_di_polarity(do_err_src - kDoErrSrc_DI1))
{
fault = kFaultLevel_Third;
}
break;
default:
break;
}
//通过电流判断粘连
if((fault != kFaultLevel_Third) && (KIT_ABS(bms_get_current()) > 50))
{
fault = kFaultLevel_Third;
}
//gary 增加连续3秒粘连问题在报粘连故障
if(fault == kFaultLevel_Third && is_chekc == true)
{
adhesion_dly += base_time;
if(adhesion_dly > 3000)
{
adhesion_dly = 0;
bms_set_do_fault(type, kDoStatus_Adhesion);
bms_set_fault_level(kFaultCode_DoAdhesion, fault, kFaultHandle_CutNoRelIdx);
}
else
{
return false;
}
}
return is_chekc;
}
void logic_open_check(uint32_t base_time)
{
uint16_t tv, hv, rate;
DoErrSrc do_err_src = bms_get_do_err_src(kDoType_Chg);
2024-11-26 15:52:49 +08:00
FaultLevel fault = kFaultLevel_Normal;
static uint16_t dly;
switch(do_err_src)
{
case kDoErrSrc_HV1:
case kDoErrSrc_HV2:
tv = bms_get_high_volt(kHvType_Bat);
hv = bms_get_high_volt((HvType)(kHvType_Hv1 + do_err_src - 1));
rate = get_eeprom_data(kEep_HV2_HV1VoltRate, (EepromDataType)(kEepromDataType_Low + do_err_src - 1));
if((tv >= 300 && (hv + 200 <= ((uint32_t)tv * rate / 100))) || (tv<100))
{
dly += base_time;
if(dly >= 1000)
{
fault = kFaultLevel_Third;
}
}
else
{
dly = 0;
}
break;
case kDoErrSrc_DI1:
case kDoErrSrc_DI2:
case kDoErrSrc_DI3:
case kDoErrSrc_DI4:
case kDoErrSrc_DI5:
case kDoErrSrc_DI6:
case kDoErrSrc_DI7:
case kDoErrSrc_DI8:
case kDoErrSrc_DI9:
//if(bms_get_signal((SignalIdx)(do_err_src - kDoErrSrc_DI1)) == kSignalStatus_High)
if(bms_get_signal((SignalIdx)(do_err_src - kDoErrSrc_DI1)) == bms_get_di_polarity(do_err_src - kDoErrSrc_DI1))
{
fault = kFaultLevel_Third;
}
break;
default:
break;
}
bms_set_fault_level(kFaultCode_DoOpen, fault, kFaultHandle_CutNoRelIdx);
}
void logic_same_circuit_ctrl(uint32_t base_time)
{
HvType prechg_type;
uint16_t prechg_volt = 0;
static uint16_t dly = 0;
static uint8_t prechg_cnt = 0;
static DoLogicStatus status = kDoLogicStatus_Reset;
uint16_t prechg_time = get_eeprom_data(kEep_PreChgTimeout_Count, kEepromDataType_Full);
uint8_t prechg_max_cnt = prechg_time & 0x00FF;
prechg_time = (prechg_time >> 8) * 1000;
switch(status)
{
case kDoLogicStatus_Reset:
if((get_eeprom_data(kEep_IsSoftReset, kEepromDataType_High) == 1)
&& (get_eeprom_data(kEep_IsSoftReset, kEepromDataType_Low) != 0))
{
dly += base_time;
//kEep_IsSoftReset高低只能清楚一个否则断电下带无法保存0
if(((bms_get_run_status() != kRunStatus_Init) && (bms_get_circuit_cmd_status() == kCircuitStatus_On)) || (dly >= 10000))
{
bms_crtl_do_status(kDoType_Chg, kDoCtrlStatus_On, RELAY_CTRL_NO_DLY);
bms_crtl_do_status(kDoType_Dis, kDoCtrlStatus_On, 100);
2024-11-26 15:52:49 +08:00
dly = 0;
status = kDoLogicStatus_On;
}
}
else
{
dly = 0;
status = kDoLogicStatus_Init;
}
break;
case kDoLogicStatus_Init:
//增加init状态防止预充中反复检测粘连 建议增加多次检测
//Gary 2024-07-25 连续粘连3秒才报粘连故障
dly += base_time;
if(logic_adhesion_check(base_time, kDoType_Chg) == true)
2024-11-26 15:52:49 +08:00
{
dly = 0;
status = kDoLogicStatus_Off;
}
break;
case kDoLogicStatus_Off:
if ((bms_is_dis_allow() == true) && (bms_is_chg_allow() == true))
{
if (prechg_max_cnt == 0) //读取配置:不预充
{
status = kDoLogicStatus_On;
bms_crtl_do_status(kDoType_Dis, kDoCtrlStatus_On, RELAY_CTRL_NO_DLY);
bms_crtl_do_status(kDoType_Chg, kDoCtrlStatus_On, 100);
2024-11-26 15:52:49 +08:00
}
else //读取配置:预充
{
if (prechg_cnt++ < prechg_max_cnt) //判断预充次数
{
status = kDoLogicStatus_Prechg;
//bms_crtl_do_status(kDoType_Chg, kDoCtrlStatus_On, RELAY_CTRL_NO_DLY); //闭合总正继电器
bms_crtl_do_status(kDoType_Dis, kDoCtrlStatus_On, RELAY_CTRL_NO_DLY);
2024-11-26 15:52:49 +08:00
bms_crtl_do_status(kDoType_PreChg, kDoCtrlStatus_On, 100);
}
else
{
bms_crtl_do_status(kDoType_Dis, kDoCtrlStatus_Off, 100);
2024-11-26 15:52:49 +08:00
bms_set_fault_level(kFaultCode_PreChg, kFaultLevel_Third, kFaultHandle_CutNoRelIdx);
}
}
}
break;
case kDoLogicStatus_Prechg:
dly += base_time;
if ((bms_is_dis_allow() == false) || (bms_is_chg_allow() == false))
{
prechg_cnt = 0;
2025-04-15 19:21:49 +08:00
status = kDoLogicStatus_Off;
2024-11-26 15:52:49 +08:00
bms_crtl_do_status(kDoType_PreChg, kDoCtrlStatus_Off, RELAY_CTRL_NO_DLY);
bms_crtl_do_status(kDoType_Dis, kDoCtrlStatus_Off, 100);
2024-11-26 15:52:49 +08:00
}
else if (dly >= prechg_time)//预充超时
2025-04-15 19:21:49 +08:00
{
2024-11-26 15:52:49 +08:00
dly = 0;
status = kDoLogicStatus_PrechgFail;
2025-04-15 19:21:49 +08:00
bms_crtl_do_status(kDoType_PreChg, kDoCtrlStatus_Off, RELAY_CTRL_NO_DLY);
2024-11-26 15:52:49 +08:00
}
else
{
prechg_volt = bms_get_high_volt(kHvType_Bat);//sfj 获取B+B-电压
if (prechg_volt >= 300)
{
prechg_type = (HvType)get_eeprom_data(kEep_PreChgVoltType_Rate,kEepromDataType_High);
prechg_volt = prechg_volt * get_eeprom_data(kEep_PreChgVoltType_Rate,kEepromDataType_Low) / 100;
2024-11-26 15:52:49 +08:00
if(bms_get_high_volt(prechg_type) >= prechg_volt)
{
dly = 0;
prechg_cnt = 0;
status = kDoLogicStatus_On;
bms_crtl_do_status(kDoType_Chg, kDoCtrlStatus_On, RELAY_CTRL_NO_DLY); //闭合总正继电器
2024-11-26 15:52:49 +08:00
bms_crtl_do_status(kDoType_PreChg, kDoCtrlStatus_Off, 500); //延时500ms断开预充继电器
}
}
}
break;
case kDoLogicStatus_PrechgFail:
dly += base_time;
if (dly >= KIT_SECOND_CONVERT(1))
{
dly = 0;
status = kDoLogicStatus_Off;
}
break;
case kDoLogicStatus_On:
dly += base_time;
if(dly >= 10000)
{
dly = 10000;
logic_open_check(base_time);
}
if((bms_is_dis_allow() == false) || (bms_is_chg_allow() == false))
{
dly = 0;
status = kDoLogicStatus_WaitOff;
}
break;
case kDoLogicStatus_WaitOff:
dly += base_time;
if ((KIT_ABS(bms_get_current() / 10) <= get_eeprom_data(kEep_CutOffCurrent, kEepromDataType_Full)) //电流阈值可配置,分辨率 1A
&& (dly >= get_eeprom_data(kEep_PwrOffDly_MinOnlineCluster, kEepromDataType_High) * 1000)) //高压下电延迟
{
dly = 0;
status = kDoLogicStatus_WaitAdhesion;
bms_crtl_do_status(kDoType_Chg, kDoCtrlStatus_Off, RELAY_CTRL_NO_DLY);
bms_crtl_do_status(kDoType_Dis, kDoCtrlStatus_Off, 100);
2024-11-26 15:52:49 +08:00
}
break;
case kDoLogicStatus_WaitAdhesion:
dly += base_time;
if(dly >= KIT_SECOND_CONVERT(5))
{
dly = 0;
status = kDoLogicStatus_Init;
}
break;
default:
dly = 0;
status = kDoLogicStatus_Init;
break;
}
}
void logic_same_circuit_poll(uint32_t base_time, uint8_t idx)
{
DoStatus pos_rly_st, neg_rly_st;
CircuitStatus circuit_st = kCircuitStatus_On;
logic_same_circuit_ctrl(base_time);
pos_rly_st = bms_get_do_status_by_type(kDoType_Chg);
neg_rly_st = (bms_is_do_config(kDoType_Dis) == true) ? bms_get_do_status_by_type(kDoType_Dis) : kDoStatus_On;
2024-11-26 15:52:49 +08:00
//neg_rly_st = kDoStatus_On;
if(((pos_rly_st != kDoStatus_On) && (pos_rly_st != kDoStatus_ForceOn))
|| ((neg_rly_st != kDoStatus_On) && (neg_rly_st != kDoStatus_ForceOn)))
{
circuit_st = kCircuitStatus_Off;
}
bms_set_circuit_status(kCircuitType_Dis, circuit_st);
bms_set_circuit_status(kCircuitType_Chg, circuit_st);
bms_set_circuit_status(kCircuitType_Main, circuit_st);
}