Files

989 lines
33 KiB
C

/**
******************************************************************************
* @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.
*
* <h2><center>&copy; COPYRIGHT 2022 AMG</center></h2>
******************************************************************************
*/
/** @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******/