/** ****************************************************************************** * @file alarm.c * @author AMG Energy Solution Team * @version V1.0.0 * @date 07-Feb-2022 * @brief This file provides all the codes of alarm process functions. ****************************************************************************** * @attention * * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * *

© COPYRIGHT 2022 AMG

****************************************************************************** */ /** @addtogroup mBMS2 * @{ */ /* Includes ------------------------------------------------------------------*/ #include "afe_comm.h" #include "asutil.h" #include "console.h" #include "device_param.h" #include "dflash_sf1.h" #include "includes.h" #include "temp.h" #include "vi.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ #define SLEEP_VOLTAGE 4500 #define WAKEUP_VOLTAGE 4600 #define SLEEP_MODE_TIME 60 * 1000 #define CELL_DEVIATION_CHECK_VOLTAGE 4500 #define CV_DIFF_PROTECT_HOLD_TIME \ (24UL * 60UL * 60UL * 1000UL) // 24 hours in ms (86,400,000 ms) #define TEMP_DIFF_PROTECT_THRESHOLD 30 // 3.0C (0.1C unit) #define TEMP_DIFF_PROTECT_HOLD_TIME \ (24UL * 60UL * 60UL * 1000UL) // 24 hours in ms #define OCC_CRITICAL_CLEAR_TIME 60 * 1000 #define PRECHARGE_TIME_DEFAULT 2 * 1000 /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ uint8_t SleepMode = false; uint8_t DeepSleepMode = false; uint32_t smode_tick = 60 * 1000; uint32_t PreChargeTime = PRECHARGE_TIME_DEFAULT; uint32_t OCCTime = 0; uint32_t OCDTime = 0; uint32_t CV_Diff_ProtectTime = CV_DIFF_PROTECT_HOLD_TIME; uint32_t CV_Diff_ProtectHoldTime = CV_DIFF_PROTECT_HOLD_TIME; // Default: 24 hours (configurable in RAM) uint32_t Temp_Diff_ProtectTime = TEMP_DIFF_PROTECT_HOLD_TIME; uint32_t Temp_Diff_ProtectHoldTime = TEMP_DIFF_PROTECT_HOLD_TIME; uint16_t Temp_Diff_Threshold = TEMP_DIFF_PROTECT_THRESHOLD; // Default: 30 (3.0 deg C) int32_t OCC_Occur_Current; int32_t OCD_Occur_Current; uint32_t OCC_CRITICAL_Tick = 60 * 1000; uint8_t OCC_Fail_Count = 0; uint8_t OCC_3Times_Fail = false; /* Private function prototypes -----------------------------------------------*/ void dec_precharge_time(uint32_t tick); void dec_occ_time(uint32_t tick); void dec_occ_critical_time(uint32_t tick); void dec_ocd_time(uint32_t tick); void dec_sleepmode_time(uint32_t tick); void dec_cv_diff_time(uint32_t tick); void dec_temp_diff_time(uint32_t tick); void ProcessSafety_COV(void); void ProcessSafety_CUV(void); void ProcessSafety_OTA(void); void ProcessSafety_LTA(void); void ProcessSafety_OCC(void); void ProcessSafety_OCD(void); void ProcessSafety_SOC(void); void ProcessSafety_CellVoltageDiff(void); void ProcessSafety_TempDiff(void); void Process_FetControl(void); void ProcessStatusCheck(void); /* Private functions ---------------------------------------------------------*/ void ClearODCTick(void) { OCDTime = device_param.safety.current.OC_Dsg_Rec_Time * 1000; } void dec_alarm_tick(uint32_t tick) { dec_precharge_time(tick); dec_occ_time(tick); dec_occ_critical_time(tick); dec_ocd_time(tick); dec_cv_diff_time(tick); dec_temp_diff_time(tick); dec_sleepmode_time(tick); } void dec_sleepmode_time(uint32_t tick) { if (smode_tick > 0) { if (smode_tick > tick) smode_tick -= tick; else smode_tick = 0; } } uint8_t GetSleepMode(void) { return SleepMode; } void SetSleepMode(uint8_t mode) { SleepMode = mode; } uint8_t GetDeepSleepMode(void) { return DeepSleepMode; } void SetDeepSleepMode(uint8_t mode) { DeepSleepMode = mode; } void CheckSleepMode(void) { if (GetSleepMode() == 1) { if (device_status.op_status == 1) { SetSleepMode(0); smode_tick = SLEEP_MODE_TIME; } } else { if (((device_status.protect.bit.cell_under_voltage) || (device_status.protect.bit.under_voltage)) && (device_value.BatVoltage < SLEEP_VOLTAGE)) { if (smode_tick == 0) SetSleepMode(1); } else { smode_tick = SLEEP_MODE_TIME; } } } void ProcessAlarm(void) { if (device_status.battery_status.bit.INIT) { device_status.protect.bit.afe_fail = device_status.error.bit.AFE | device_status.error.bit.afe_fail; if (device_status.error.bit.AFE == false) { ProcessSafety_COV(); ProcessSafety_CUV(); } ProcessSafety_OTA(); ProcessSafety_LTA(); ProcessSafety_OCC(); ProcessSafety_OCD(); ProcessSafety_SOC(); ProcessSafety_CellVoltageDiff(); ProcessSafety_TempDiff(); Process_FetControl(); // CheckSleepMode(); } ProcessStatusCheck(); } void dec_precharge_time(uint32_t tick) { if (PreChargeTime > 0) { if (PreChargeTime > tick) PreChargeTime -= tick; else PreChargeTime = 0; } } void ProcessSafety_COV(void) { /* Cell Over Voltage Check */ for (int i = 0; i < DEVICE_MAX_CELL; i++) { /* Cell Over Voltage Protection */ if (device_status.cov_protection_cell.uValue & BIT(i)) { // Release check if (device_value.Cell.voltage[i] < device_param.safety.voltage.COV_Recovery) device_status.cov_protection_cell.uValue &= ~BIT(i); } else { // Alarm check if (device_value.Cell.voltage[i] > device_param.safety.voltage.COV_Threshold) device_status.cov_protection_cell.uValue |= BIT(i); } /* Cell Over Voltage Warning */ if (device_status.cov_warning_cell.uValue & BIT(i)) { // Release check if (device_value.Cell.voltage[i] < device_param.safety.voltage.COV_Recovery) device_status.cov_warning_cell.uValue &= ~BIT(i); } else { // Alarm check if (device_value.Cell.voltage[i] > device_param.safety.voltage.COV_Warning) device_status.cov_warning_cell.uValue |= BIT(i); } } if (device_status.cov_protection_cell.uValue != 0) device_status.protect.bit.cell_over_voltage = true; else device_status.protect.bit.cell_over_voltage = false; if (device_status.cov_warning_cell.uValue != 0) device_status.warning.bit.cell_over_voltage = true; else device_status.warning.bit.cell_over_voltage = false; /* System Over charge protection */ if (device_status.protect.bit.over_voltage) { // Release check if (device_value.BatVoltage < device_param.safety.voltage.SOV_Recovery) device_status.protect.bit.over_voltage = false; } else { // Alarm check if (device_value.BatVoltage > device_param.safety.voltage.SOV_Threshold) device_status.protect.bit.over_voltage = true; } /* System Over Voltage Warning */ if (device_status.warning.bit.over_voltage) { // Release check if (device_value.BatVoltage < device_param.safety.voltage.SOV_Recovery) device_status.warning.bit.over_voltage = false; } else { // Alarm check if (device_value.BatVoltage > device_param.safety.voltage.SOV_Warning) device_status.warning.bit.over_voltage = true; } } void ProcessSafety_CUV(void) { /* Cell under voltage check */ for (int i = 0; i < DEVICE_MAX_CELL; i++) { /* Cell under voltage protection */ if (device_status.cuv_protection_cell.uValue & BIT(i)) { // Recovery Check // if (device_value.Cell.voltage[i] > //device_param.safety.voltage.CUV_Recovery) // device_status.cuv_protection_cell.uValue //&= ~BIT(i); } else { // Protection Check if (device_value.Cell.voltage[i] < device_param.safety.voltage.CUV_Threshold) device_status.cuv_protection_cell.uValue |= BIT(i); } /* Cell under voltage warning */ if (device_status.cuv_warning_cell.uValue & BIT(i)) { // Recovery Check if (device_value.Cell.voltage[i] > device_param.safety.voltage.CUV_Recovery) device_status.cuv_warning_cell.uValue &= ~BIT(i); } else { // Warning Check if (device_value.Cell.voltage[i] < device_param.safety.voltage.CUV_Warning) device_status.cuv_warning_cell.uValue |= BIT(i); } } if (device_status.cuv_protection_cell.uValue != 0) device_status.protect.bit.cell_under_voltage = true; else device_status.protect.bit.cell_under_voltage = false; if (device_status.cuv_warning_cell.uValue != 0) device_status.warning.bit.cell_under_voltage = true; else device_status.warning.bit.cell_under_voltage = false; /* Cell Voltage Fault Check (Below 1000mV or above 4500mV abnormal voltage * cutoff charging) */ uint8_t cell_fault = false; for (int i = 0; i < DEVICE_MAX_CELL; i++) { if ((device_value.Cell.voltage[i] <= 1000) || (device_value.Cell.voltage[i] >= 4500)) { cell_fault = true; break; } } if (cell_fault) { device_status.error.bit.afe_fail = true; device_status.protect.bit.afe_fail = true; } else { device_status.error.bit.afe_fail = false; } /* System under voltage protection */ if (device_status.protect.bit.under_voltage) { // // Release check // if (device_value.BatVoltage > //device_param.safety.voltage.SUV_Recovery) // device_status.protection.bit.under_voltage = false; } else { // Alarm check if (device_value.BatVoltage < device_param.safety.voltage.SUV_Threshold) device_status.protect.bit.under_voltage = true; } /* System under voltage warning */ if (device_status.warning.bit.under_voltage) { // Release check if (device_value.BatVoltage > device_param.safety.voltage.SUV_Recovery) device_status.warning.bit.under_voltage = false; } else { // Alarm check if (device_value.BatVoltage < device_param.safety.voltage.SUV_Warning) device_status.warning.bit.under_voltage = true; } if (device_status.protect.bit.under_voltage) { if (device_status.op_status == 0x0001) { device_status.protect.bit.under_voltage = 0; } } if (device_status.protect.bit.cell_under_voltage) { if (device_status.op_status == 0x0001) { device_status.protect.bit.cell_under_voltage = 0; device_status.cuv_protection_cell.uValue = 0; } } } void ProcessSafety_OTA(void) { /* Temperature Sensor Fault Check */ if (IsTempSensorFailed()) { device_status.error.bit.temp_sensor = true; } else { device_status.error.bit.temp_sensor = false; } /* Charge High Temperature */ for (int i = 0; i < (DEVICE_MAX_TEMP - 2); i++) { if (ADState(i) != AD_FAIL) { int16_t aTemp = device_value.Temp.temperature[i]; /* Over Temperature Charge Protection */ if (device_status.otc_protection_temp.uValue & BIT(i)) { // Recovery Check if (aTemp < device_param.safety.temperature.OT_Chg_Recovery) device_status.otc_protection_temp.uValue &= ~BIT(i); } else { // Protection Check, when charging if (device_status.battery_status.bit.MD == 0) { if (aTemp > device_param.safety.temperature.OT_Chg_Threshold) device_status.otc_protection_temp.uValue |= BIT(i); } } /* Over Temperature Charge Warning */ if (device_status.otc_warning_temp.uValue & BIT(i)) { // Recovery Check if (aTemp < device_param.safety.temperature.OT_Chg_Recovery) device_status.otc_warning_temp.uValue &= ~BIT(i); } else { // Warning Check, when charging if (device_status.battery_status.bit.MD == 0) { if (aTemp > device_param.safety.temperature.OT_Chg_Warning) device_status.otc_warning_temp.uValue |= BIT(i); } } } else { device_status.otc_warning_temp.uValue |= BIT(i); device_status.otc_protection_temp.uValue &= ~BIT(i); } } /* OTC Protection */ if (device_status.otc_protection_temp.uValue != 0) device_status.protect.bit.chg_high_temp = true; else device_status.protect.bit.chg_high_temp = false; /* OTC Warning */ if (device_status.otc_warning_temp.uValue != 0) device_status.warning.bit.chg_high_temp = true; else device_status.warning.bit.chg_high_temp = false; /* High Temperature Discharge */ for (int i = 0; i < (DEVICE_MAX_TEMP - 2); i++) { if (ADState(i) != AD_FAIL) { int16_t aTemp = device_value.Temp.temperature[i]; /* Over Temperature Discharge Protection */ if (device_status.otd_protection_temp.uValue & BIT(i)) { // Recovery Check if (aTemp < device_param.safety.temperature.OT_Dsg_Recovery) device_status.otd_protection_temp.uValue &= ~BIT(i); } else { // Protection Check, when charging if (device_status.battery_status.bit.MD == 1) { if (aTemp > device_param.safety.temperature.OT_Dsg_Threshold) device_status.otd_protection_temp.uValue |= BIT(i); } } /* Over Temperature Charge Warning */ if (device_status.otd_warning_temp.uValue & BIT(i)) { // Recovery Check if (aTemp < device_param.safety.temperature.OT_Dsg_Recovery) device_status.otd_warning_temp.uValue &= ~BIT(i); } else { // Warning Check, when charging if (device_status.battery_status.bit.MD == 1) { if (aTemp > device_param.safety.temperature.OT_Dsg_Warning) device_status.otd_warning_temp.uValue |= BIT(i); } } } else { device_status.otd_warning_temp.uValue |= BIT(i); device_status.otd_protection_temp.uValue &= ~BIT(i); } } /* OTD Protection */ if (device_status.otd_protection_temp.uValue != 0) device_status.protect.bit.dsg_high_temp = true; else device_status.protect.bit.dsg_high_temp = false; /* OTD Warning */ if (device_status.otd_warning_temp.uValue != 0) device_status.warning.bit.dsg_high_temp = true; else device_status.warning.bit.dsg_high_temp = false; } void ProcessSafety_LTA(void) { /* Charge Low Temperature */ for (int i = 0; i < (DEVICE_MAX_TEMP - 2); i++) { if (ADState(i) != AD_FAIL) { int16_t aTemp = device_value.Temp.temperature[i]; /* Over Temperature Charge Protection */ if (device_status.ltc_protection_temp.uValue & BIT(i)) { // Recovery Check if (aTemp > device_param.safety.temperature.LT_Chg_Recovery) device_status.ltc_protection_temp.uValue &= ~BIT(i); } else { // Protection Check, when charging if (device_status.battery_status.bit.MD == 0) { if (aTemp < device_param.safety.temperature.LT_Chg_Threshold) device_status.ltc_protection_temp.uValue |= BIT(i); } } /* Low Temperature Charge Warning */ if (device_status.ltc_warning_temp.uValue & BIT(i)) { // Recovery Check if (aTemp > device_param.safety.temperature.LT_Chg_Recovery) device_status.ltc_warning_temp.uValue &= ~BIT(i); } else { // Warning Check, when charging if (device_status.battery_status.bit.MD == 0) { if (aTemp < device_param.safety.temperature.LT_Chg_Warning) device_status.ltc_warning_temp.uValue |= BIT(i); } } } else { device_status.ltc_warning_temp.uValue |= BIT(i); device_status.ltc_protection_temp.uValue &= ~BIT(i); } } /* LTC Protection */ if (device_status.ltc_protection_temp.uValue != 0) device_status.protect.bit.chg_low_temp = true; else device_status.protect.bit.chg_low_temp = false; /* LTC Warning */ if (device_status.ltc_warning_temp.uValue != 0) device_status.warning.bit.chg_low_temp = true; else device_status.warning.bit.chg_low_temp = false; /* Low Temperature Discharge */ for (int i = 0; i < (DEVICE_MAX_TEMP - 2); i++) { if (ADState(i) != AD_FAIL) { int16_t aTemp = device_value.Temp.temperature[i]; /* Low Temperature Discharge Protection */ if (device_status.ltd_protection_temp.uValue & BIT(i)) { // Recovery Check if (aTemp > device_param.safety.temperature.LT_Dsg_Recovery) device_status.ltd_protection_temp.uValue &= ~BIT(i); } else { // Protection Check, when charging if (device_status.battery_status.bit.MD == 1) { if (aTemp < device_param.safety.temperature.LT_Dsg_Threshold) device_status.ltd_protection_temp.uValue |= BIT(i); } } /* Over Temperature Charge Warning */ if (device_status.ltd_warning_temp.uValue & BIT(i)) { // Recovery Check if (aTemp > device_param.safety.temperature.LT_Dsg_Recovery) device_status.ltd_warning_temp.uValue &= ~BIT(i); } else { // Warning Check, when charging if (device_status.battery_status.bit.MD == 1) { if (aTemp < device_param.safety.temperature.LT_Dsg_Warning) device_status.ltd_warning_temp.uValue |= BIT(i); } } } else { device_status.ltd_warning_temp.uValue |= BIT(i); device_status.ltd_protection_temp.uValue &= ~BIT(i); } } /* LTD Protection */ if (device_status.ltd_protection_temp.uValue != 0) device_status.protect.bit.dsg_low_temp = true; else device_status.protect.bit.dsg_low_temp = false; /* LTD Warning */ if (device_status.ltd_warning_temp.uValue != 0) device_status.warning.bit.dsg_low_temp = true; else device_status.warning.bit.dsg_low_temp = false; } void dec_occ_time(uint32_t tick) { if (OCCTime > 0) { if (OCCTime > tick) OCCTime -= tick; else OCCTime = 0; } } void dec_occ_critical_time(uint32_t tick) { if (OCC_CRITICAL_Tick > 0) { if (OCC_CRITICAL_Tick > tick) OCC_CRITICAL_Tick -= tick; else OCC_CRITICAL_Tick = 0; } } void ProcessSafety_OCC(void) { /* Over charge current protection */ if (device_status.protect.bit.chg_over_current) { // release check: DO NOT auto-recover if repeated OCC fail occurred // (Latched) if (OCC_3Times_Fail) { device_status.protect.bit.chg_over_current = true; } else { if ((device_value.Current / 1) < (device_param.safety.current.OC_Chg_Recovery * 10)) { if (OCCTime == 0) device_status.protect.bit.chg_over_current = false; } else { OCCTime = device_param.safety.current.OC_Chg_Rec_Time * 1000; OCC_CRITICAL_Tick = OCC_CRITICAL_CLEAR_TIME; } } } else { // alarm check if ((device_value.Current / 1) > (device_param.safety.current.OC_Chg_Threshold * 10)) { OCC_Occur_Current = device_value.Current; device_status.protect.bit.chg_over_current = true; OCCTime = device_param.safety.current.OC_Chg_Rec_Time * 1000; if (OCC_Fail_Count < 3) { OCC_Fail_Count++; OCC_CRITICAL_Tick = OCC_CRITICAL_CLEAR_TIME; } if (OCC_Fail_Count >= 3) { OCC_3Times_Fail = true; OCC_CRITICAL_Tick = OCC_CRITICAL_CLEAR_TIME; } } } if (OCC_3Times_Fail == false) { if (OCC_Fail_Count > 0) { if (OCC_CRITICAL_Tick == 0) { OCC_Fail_Count = 0; } } } else { device_status.protect.bit.chg_over_current = true; } device_status.battery_status.bit.TCA = OCC_3Times_Fail; device_status.protect.bit.critial_over_current = OCC_3Times_Fail; /* Over current charge warning */ if (device_status.warning.bit.chg_over_current) { // release check if ((device_value.Current / 1) < (device_param.safety.current.OC_Chg_Recovery * 10)) device_status.warning.bit.chg_over_current = false; } else { // alarm check if ((device_value.Current / 1) > (device_param.safety.current.OC_Chg_Warning * 10)) device_status.warning.bit.chg_over_current = true; } } void dec_ocd_time(uint32_t tick) { if (OCDTime > tick) OCDTime -= tick; else OCDTime = 0; } void ProcessSafety_OCD(void) { /* Over current discharge protection */ if (device_status.protect.bit.dsg_over_current) { // release check if ((device_value.Current / 1) > (device_param.safety.current.OC_Dsg_Recovery * 10)) { if (OCDTime == 0) device_status.protect.bit.dsg_over_current = false; } else OCDTime = device_param.safety.current.OC_Dsg_Rec_Time * 1000; } else { // alarm check if ((device_value.Current / 1) < (device_param.safety.current.OC_Dsg_Threshold * 10)) { OCD_Occur_Current = device_value.Current; device_status.protect.bit.dsg_over_current = true; OCDTime = device_param.safety.current.OC_Dsg_Rec_Time * 1000; } } /* Over current discharge warning */ if (device_status.warning.bit.dsg_over_current) { // release check if ((device_value.Current / 1) > (device_param.safety.current.OC_Dsg_Recovery * 10)) device_status.warning.bit.dsg_over_current = false; } else { // alarm check if ((device_value.Current / 1) < (device_param.safety.current.OC_Dsg_Warning * 10)) device_status.warning.bit.dsg_over_current = true; } } void ProcessSafety_SOC(void) { /* Low capacity warning */ if (device_status.warning.bit.low_capacity) { // release check if ((device_value.RelativeStateOfCharge) > (device_param.safety.soc.Low_Soc_Recovery * 10)) device_status.warning.bit.low_capacity = false; } else { // alarm check if ((device_value.RelativeStateOfCharge) < (device_param.safety.soc.Low_Soc_Warning * 10)) device_status.warning.bit.low_capacity = true; } } void dec_cv_diff_time(uint32_t tick) { if (CV_Diff_ProtectTime > tick) CV_Diff_ProtectTime -= tick; else CV_Diff_ProtectTime = 0; } uint32_t GetCvDiffTime(void) { return (CV_Diff_ProtectTime / 1000); } uint32_t GetTpDiffTime() { return (Temp_Diff_ProtectTime / 1000); } void ProcessSafety_CellVoltageDiff(void) { device_status.warning.bit.cell_voltage_diff = 0; if (device_value.BatVoltage >= CELL_DEVIATION_CHECK_VOLTAGE) { /* Cell Voltage Diff protection (Cutoff charge if diff >= 200mV holds for * 24h, latch until MCU reset) */ if (device_status.protect.bit.cell_voltage_diff) { // KT Requirement: Once tripped, latch protection and do not auto-recover // until MCU reset } else { // Alarm check: Cutoff charge if cell diff >= 200mV holds for // CV_Diff_ProtectHoldTime (default 24h) if (device_value.Cell.avg.diff >= device_param.safety.cv_diff.Cell_Voltage_Diff_Threshold) { if (CV_Diff_ProtectTime == 0) { device_status.protect.bit.cell_voltage_diff = true; } } else { CV_Diff_ProtectTime = CV_Diff_ProtectHoldTime; } } } else { if (device_status.protect.bit.cell_voltage_diff == false) { CV_Diff_ProtectTime = CV_Diff_ProtectHoldTime; } } } void Set_CV_Diff_ProtectHoldTime(uint32_t hold_time_ms) { if (hold_time_ms == 0) { CV_Diff_ProtectHoldTime = CV_DIFF_PROTECT_HOLD_TIME; } else { CV_Diff_ProtectHoldTime = hold_time_ms; } if (device_status.protect.bit.cell_voltage_diff == false) { CV_Diff_ProtectTime = CV_Diff_ProtectHoldTime; } } void dec_temp_diff_time(uint32_t tick) { if (Temp_Diff_ProtectTime > tick) Temp_Diff_ProtectTime -= tick; else Temp_Diff_ProtectTime = 0; } void ProcessSafety_TempDiff(void) { /* Temp Diff protection (Cutoff charge if temp diff >= 3.0 deg C holds for * 24h, latch until MCU reset) */ if (device_status.protect.bit.temp_diff) { // KT Requirement: Once tripped, latch protection and do not auto-recover // until MCU reset } else { // Alarm check: Cutoff charge if temp diff >= TEMP_DIFF_PROTECT_THRESHOLD // (3.0 deg C) holds for Temp_Diff_ProtectHoldTime if ((device_status.error.bit.temp_sensor == false) && (device_value.Temp.avg.diff >= Temp_Diff_Threshold)) { if (Temp_Diff_ProtectTime == 0) { device_status.protect.bit.temp_diff = true; } } else { Temp_Diff_ProtectTime = Temp_Diff_ProtectHoldTime; } } } void Set_Temp_Diff_ProtectHoldTime(uint32_t hold_time_ms) { if (hold_time_ms == 0) { Temp_Diff_ProtectHoldTime = TEMP_DIFF_PROTECT_HOLD_TIME; } else { Temp_Diff_ProtectHoldTime = hold_time_ms; } if (device_status.protect.bit.temp_diff == false) { Temp_Diff_ProtectTime = Temp_Diff_ProtectHoldTime; } } void Set_Temp_Diff_Threshold(uint16_t th) { if (th == 0) Temp_Diff_Threshold = TEMP_DIFF_PROTECT_THRESHOLD; else Temp_Diff_Threshold = th; } uint16_t Get_Temp_Diff_Threshold(void) { return Temp_Diff_Threshold; } #define OP_STS_STANDBY 0x0000 #define OP_STS_CHARGING 0x0001 #define OP_STS_DISCHARGING 0x0002 #define OP_STS_FLOATING 0x0003 #define OP_STS_WARMINUP 0x0004 void Process_FetControl(void) { if ((device_status.protect.bit.afe_fail) || (device_status.error.bit.temp_sensor)) { device_status.battery_status.bit.CHG_C = false; device_status.battery_status.bit.DSG_C = false; device_status.battery_status.bit.ZVC_C = false; return; } // Charge Protection Check if (device_status.protect.bit.cell_over_voltage) // Cell Over Voltage { device_status.battery_status.bit.CHG_C = false; // device_status.battery_status.bit.DSG_C = true; device_status.battery_status.bit.ZVC_C = false; } else if (device_status.protect.bit.over_voltage) // System Over Voltage { device_status.battery_status.bit.CHG_C = false; // device_status.battery_status.bit.DSG_C = true; device_status.battery_status.bit.ZVC_C = false; } else if (device_status.protect.bit.chg_over_current) // Charge Over Current { device_status.battery_status.bit.CHG_C = false; // device_status.battery_status.bit.DSG_C = true; device_status.battery_status.bit.ZVC_C = false; } else if (device_status.protect.bit.chg_high_temp) // Charge High Temperature { device_status.battery_status.bit.CHG_C = false; // device_status.battery_status.bit.DSG_C = true; device_status.battery_status.bit.ZVC_C = false; } else if (device_status.protect.bit.chg_low_temp) // Charge Low Temperature { device_status.battery_status.bit.CHG_C = false; // device_status.battery_status.bit.DSG_C = true; device_status.battery_status.bit.ZVC_C = false; } // uint32_t OCC_CRITICAL_Tick = 60 * 1000; // uint8_t OCC_Fail_Count = 0; // uint8_t OCC_3Times_Fail = false; else if (OCC_3Times_Fail || device_status.protect.bit.critial_over_current) { device_status.battery_status.bit.CHG_C = false; // device_status.battery_status.bit.DSG_C = true; device_status.battery_status.bit.ZVC_C = false; } else if (device_status.protect.bit.cell_voltage_diff || device_status.protect.bit .temp_diff) // Cell Voltage Diff & Temp Diff Protection (Cutoff // charge if held 24h) { device_status.battery_status.bit.CHG_C = false; device_status.battery_status.bit.ZVC_C = false; } else { device_status.battery_status.bit.CHG_C = true; device_status.battery_status.bit.ZVC_C = false; } // Dischare Protecion Check if (device_status.protect.bit.cell_under_voltage) // Cell Under Voltage { // device_status.battery_status.bit.CHG_C = false; device_status.battery_status.bit.DSG_C = false; } else if (device_status.protect.bit.under_voltage) // System Under Voltage { // device_status.battery_status.bit.CHG_C = false; device_status.battery_status.bit.DSG_C = false; } else if (device_status.protect.bit .dsg_over_current) // Discharge Over Current { // device_status.battery_status.bit.CHG_C = false; device_status.battery_status.bit.DSG_C = false; } else if (device_status.protect.bit .dsg_high_temp) // Discharge High Temperature { // device_status.battery_status.bit.CHG_C = false; device_status.battery_status.bit.DSG_C = false; } else if (device_status.protect.bit .dsg_low_temp) // Discharge Low Temperature { // device_status.battery_status.bit.CHG_C = false; device_status.battery_status.bit.DSG_C = false; } else // No Protection { device_status.battery_status.bit.DSG_C = true; } if (device_status.protect.bit.cell_voltage_diff || device_status.protect.bit.temp_diff) { device_status.battery_status.bit.CHG_C = false; device_status.battery_status.bit.ZVC_C = false; } } void ProcessStatusCheck(void) { // Alarm Status if (device_status.battery_status.bit.INIT == false) { device_status.alarm_status = 0x0003; // Warming Up } else if (device_status.protect.value != 0) { device_status.alarm_status = 0x0002; // Protection } else if (device_status.warning.value != 0) { device_status.alarm_status = 0x0001; // Warning } else { device_status.alarm_status = 0x0000; // Normal } // Operating Status if (device_status.battery_status.bit.INIT == false) { device_status.op_status = 0x0004; // Warming Up } else { if (device_status.battery_status.bit.RXM == false) { switch (device_status.op_status) { case OP_STS_STANDBY: // Standby case OP_STS_FLOATING: // Floating if (device_value.CCurrent > (device_param.chg_ctrl.current_thr.Charge_Detection_Threshold / 100)) { device_status.op_status = OP_STS_CHARGING; } else if (device_value.DCurrent > (device_param.chg_ctrl.current_thr .Discharge_Detection_Threshold / 100)) { device_status.op_status = OP_STS_DISCHARGING; } break; case OP_STS_CHARGING: // Charging if (device_value.DCurrent > (device_param.chg_ctrl.current_thr.Discharge_Detection_Threshold / 100)) { device_status.op_status = OP_STS_DISCHARGING; } else if ((device_value.CCurrent < ((device_param.chg_ctrl.current_thr .Charge_Detection_Threshold - 1000) / 100)) || (device_status.battery_status.bit.CHG_C == false)) { device_status.op_status = OP_STS_STANDBY; } break; case OP_STS_DISCHARGING: // Discharging if (device_value.CCurrent > (device_param.chg_ctrl.current_thr.Charge_Detection_Threshold / 100)) { device_status.op_status = OP_STS_CHARGING; } else if (device_value.DCurrent < ((device_param.chg_ctrl.current_thr .Discharge_Detection_Threshold - 1000) / 100)) { device_status.op_status = OP_STS_STANDBY; // Standby } break; case OP_STS_WARMINUP: // Warming Up device_status.op_status = OP_STS_STANDBY; // Standby break; default: device_status.op_status = OP_STS_STANDBY; // Standby break; } // if (device_status.op_status == OP_STS_WARMINUP) //{ device_status.op_status = OP_STS_STANDBY; //// Standby } else { if (device_value.CCurrent > //(device_param.chg_ctrl.current_thr.Charge_Detection_Threshold / 100)) { // device_status.op_status = //OP_STS_CHARGING; } else if (device_value.DCurrent > //(device_param.chg_ctrl.current_thr.Discharge_Detection_Threshold / 100)) //{ device_status.op_status = OP_STS_DISCHARGING; // } // } } else { switch (device_status.op_status) { case OP_STS_STANDBY: // Stand by // if (device_value.BatVoltage >= //(device_param.chg_ctrl.chg_cfg.ST_Chg_Voltage)) { if (device_value.BatVoltage >= 5200) { if (device_status.protect.value == 0) { device_status.op_status = OP_STS_FLOATING; // Floating } } break; case OP_STS_FLOATING: // Float Charge // if (device_value.BatVoltage < //(device_param.chg_ctrl.chg_cfg.ST_Chg_Voltage - //(device_param.chg_ctrl.term_cfg.Taper_Voltage / 10))) { if (device_value.BatVoltage <= 5180) { device_status.op_status = OP_STS_STANDBY; // Floating } break; default: if ((device_value.BatVoltage >= 5200) && (device_status.protect.value == 0)) { device_status.op_status = OP_STS_FLOATING; // Floating } else { device_status.op_status = OP_STS_STANDBY; // Standby } break; } } if (device_status.op_status == OP_STS_DISCHARGING) { device_status.battery_status.bit.CHG_C = true; } } } /*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/