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

313 lines
11 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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);
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);
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)
{
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);
}
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);
bms_crtl_do_status(kDoType_PreChg, kDoCtrlStatus_On, 100);
}
else
{
bms_crtl_do_status(kDoType_Dis, kDoCtrlStatus_Off, 100);
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;
status = kDoLogicStatus_Off;
bms_crtl_do_status(kDoType_PreChg, kDoCtrlStatus_Off, RELAY_CTRL_NO_DLY);
bms_crtl_do_status(kDoType_Dis, kDoCtrlStatus_Off, 100);
}
else if (dly >= prechg_time)//预充超时
{
dly = 0;
status = kDoLogicStatus_PrechgFail;
bms_crtl_do_status(kDoType_PreChg, kDoCtrlStatus_Off, RELAY_CTRL_NO_DLY);
}
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;
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); //闭合总正继电器
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);
}
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;
//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);
}