Files
LFP_48V_mBMS_FW/mBMS_APP_V3117/APP/alarm.c

1097 lines
28 KiB
C

/* Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*
* High Level description:
* http://www.ti.com/lit/ds/symlink/bq28400.pdf
* Thechnical Reference:
* http://www.ti.com/lit/ug/sluu431/sluu431.pdf
*/
#include "includes.h"
#include "dflash_sf1.h"
#include "device_param.h"
#include "asutil.h"
#include "console.h"
#include "PL455_comm.h"
#include "temp.h"
#include "vi.h"
#define SLEEP_VOLTAGE 4200
#define WAKEUP_VOLTAGE 4500
#define SLEEP_MODE_TIME 60 * 1000
#define CELL_DEVIATION_CHECK_VOLTAGE 4500
#define OCC_CRITICAL_CLEAR_TIME 60 * 1000
#define PRECHARGE_TIME_DEFAULT 2 * 1000
#define CV_DIFF_PROTECT_HOLD_TIME (24UL * 60UL * 60UL * 1000UL) // 24 hours in 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
u8 SleepMode = false;
u32 smode_tick = 60 * 1000;
u32 PreChargeTime = PRECHARGE_TIME_DEFAULT;
u32 OCCTime = 0;
u32 OCDTime = 0;
u32 CV_Diff_ProtectTime = CV_DIFF_PROTECT_HOLD_TIME;
u32 CV_Diff_ProtectHoldTime = CV_DIFF_PROTECT_HOLD_TIME; // Default: 24 hours (configurable in RAM)
u32 Temp_Diff_ProtectTime = TEMP_DIFF_PROTECT_HOLD_TIME;
u32 Temp_Diff_ProtectHoldTime = TEMP_DIFF_PROTECT_HOLD_TIME;
u16 Temp_Diff_Threshold = TEMP_DIFF_PROTECT_THRESHOLD; // Default: 30 (3.0 deg C)
s32 OCC_Occur_Current;
s32 OCD_Occur_Current;
u32 OCC_CRITICAL_Tick = 60 * 1000;
u8 OCC_Fail_Count = 0;
u8 OCC_3Times_Fail = false;
void dec_precharge_time(u32 tick);
void dec_occ_time(u32 tick);
void dec_occ_critical_time(u32 tick);
void dec_ocd_time(u32 tick);
void dec_sleepmode_time(u32 tick);
void dec_cv_diff_time(u32 tick);
void dec_temp_diff_time(u32 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);
void ClearODCTick(void)
{
OCDTime = device_param.safety.current.OC_Dsg_Rec_Time * 1000;
}
void dec_alarm_tick(u32 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(u32 tick)
{
if (smode_tick > 0)
{
if (smode_tick > tick)
smode_tick -= tick;
else
smode_tick = 0;
}
}
u8 GetSleepMode(void)
{
return SleepMode;
}
void SetSleepMode(u8 mode)
{
SleepMode = mode;
}
void CheckSleepMode(void)
{
if (SleepMode == true)
{
if (device_status.op_status == 1)
{
SleepMode = false;
smode_tick = SLEEP_MODE_TIME;
}
}
else
{
if ((device_status.protection.bit.cell_under_voltage) || (device_status.protection.bit.under_voltage))
{
if (smode_tick == 0)
SleepMode = true;
}
else
{
smode_tick = SLEEP_MODE_TIME;
}
}
}
void ProcessAlarm(void)
{
if (device_status.battery_status.bit.INIT)
{
device_status.protection.bit.afe_fail = device_status.battery_status.bit.AFE | device_status.error.bit.afe_fail;
if (device_status.battery_status.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(u32 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.protection.bit.cell_over_voltage = true;
else
device_status.protection.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.protection.bit.over_voltage)
{
// Release check
if (device_value.BatVoltage < device_param.safety.voltage.SOV_Recovery)
device_status.protection.bit.over_voltage = false;
}
else
{
// Alarm check
if (device_value.BatVoltage > device_param.safety.voltage.SOV_Threshold)
device_status.protection.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.protection.bit.cell_under_voltage = true;
else
device_status.protection.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.protection.bit.afe_fail = true;
}
else
{
device_status.error.bit.afe_fail = false;
}
/* System under voltage protection */
if (device_status.protection.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.protection.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.protection.bit.under_voltage)
{
if (device_status.op_status == 0x0001)
{
device_status.protection.bit.under_voltage = 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; i++)
{
if (ADState(i) != AD_FAIL)
{
s16 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);
}
}
}
}
/* OTC Protection */
if (device_status.otc_protection_temp.uValue != 0)
device_status.protection.bit.chg_high_temp = true;
else
device_status.protection.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; i++)
{
if (ADState(i) != AD_FAIL)
{
s16 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);
}
}
}
}
/* OTD Protection */
if (device_status.otd_protection_temp.uValue != 0)
device_status.protection.bit.dsg_high_temp = true;
else
device_status.protection.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; i++)
{
if (ADState(i) != AD_FAIL)
{
s16 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);
}
}
}
}
/* LTC Protection */
if (device_status.ltc_protection_temp.uValue != 0)
device_status.protection.bit.chg_low_temp = true;
else
device_status.protection.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; i++)
{
if (ADState(i) != AD_FAIL)
{
s16 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);
}
}
}
}
/* LTD Protection */
if (device_status.ltd_protection_temp.uValue != 0)
device_status.protection.bit.dsg_low_temp = true;
else
device_status.protection.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(u32 tick)
{
if (OCCTime > 0)
{
if (OCCTime > tick)
OCCTime -= tick;
else
OCCTime = 0;
}
}
void dec_occ_critical_time(u32 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.protection.bit.chg_over_current)
{
// release check: DO NOT auto-recover if repeated OCC fail occurred (Latched)
if (OCC_3Times_Fail)
{
device_status.protection.bit.chg_over_current = true;
}
else
{
if ((device_value.Current / 1) < (device_param.safety.current.OC_Chg_Recovery * 10))
{
if (OCCTime == 0)
device_status.protection.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.protection.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;
}
}
}
device_status.battery_status.bit.TCA = OCC_3Times_Fail;
device_status.protection.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(u32 tick)
{
if (OCDTime > tick)
OCDTime -= tick;
else
OCDTime = 0;
}
void ProcessSafety_OCD(void)
{
/* Over current discharge protection */
if (device_status.protection.bit.dsg_over_current)
{
// release check
if ((device_value.Current / 1) > (device_param.safety.current.OC_Dsg_Recovery * 10))
{
if (OCDTime == 0)
device_status.protection.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.protection.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(u32 tick)
{
if (CV_Diff_ProtectTime > tick)
CV_Diff_ProtectTime -= tick;
else
CV_Diff_ProtectTime = 0;
}
u32 GetCvDiffTime(void)
{
return (CV_Diff_ProtectTime / 1000);
}
u32 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.protection.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.protection.bit.cell_voltage_diff = true;
}
}
else
{
CV_Diff_ProtectTime = CV_Diff_ProtectHoldTime;
}
}
}
else
{
if (device_status.protection.bit.cell_voltage_diff == false)
{
CV_Diff_ProtectTime = CV_Diff_ProtectHoldTime;
}
}
}
void Set_CV_Diff_ProtectHoldTime(u32 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.protection.bit.cell_voltage_diff == false)
{
CV_Diff_ProtectTime = CV_Diff_ProtectHoldTime;
}
}
void dec_temp_diff_time(u32 tick)
{
if (Temp_Diff_ProtectTime > tick)
Temp_Diff_ProtectTime -= tick;
else
Temp_Diff_ProtectTime = 0;
}
void ProcessSafety_TempDiff(void)
{
/* Temp Diff protection (24h continuous >= 3.0C diff cut off charging) */
if (device_status.protection.bit.temp_diff)
{
// Latch protection until reset
}
else
{
if ((device_status.error.bit.temp_sensor == false) && (device_value.Temp.avg.diff >= Temp_Diff_Threshold))
{
if (Temp_Diff_ProtectTime == 0)
{
device_status.protection.bit.temp_diff = true;
}
}
else
{
Temp_Diff_ProtectTime = Temp_Diff_ProtectHoldTime;
}
}
}
void Set_Temp_Diff_ProtectHoldTime(u32 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.protection.bit.temp_diff == false)
{
Temp_Diff_ProtectTime = Temp_Diff_ProtectHoldTime;
}
}
void Set_Temp_Diff_Threshold(u16 th)
{
if (th == 0)
Temp_Diff_Threshold = TEMP_DIFF_PROTECT_THRESHOLD;
else
Temp_Diff_Threshold = th;
}
u16 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_WARMINUP 0x0003
void Process_FetControl(void)
{
if ((device_status.protection.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.protection.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.protection.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.protection.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.protection.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.protection.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;
}
//u32 OCC_CRITICAL_Tick = 60 * 1000;
//u8 OCC_Fail_Count = 0;
//u8 OCC_3Times_Fail = false;
else if (OCC_3Times_Fail || device_status.protection.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.protection.bit.cell_voltage_diff || device_status.protection.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;
}
// Discharge Protection Check
if (device_status.protection.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.protection.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.protection.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.protection.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.protection.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.protection.bit.cell_voltage_diff || device_status.protection.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.protection.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 0x0003: // Floating
if (device_value.CCurrent > (device_param.chg_ctrl.current_thr.Charge_Detection_Threshold / 100))
{
device_status.op_status = 0x0001;
}
else if (device_value.DCurrent > (device_param.chg_ctrl.current_thr.Discharge_Detection_Threshold / 100))
{
device_status.op_status = 0x0002;
}
break;
case 0x0001: // Charging
if (device_value.DCurrent > (device_param.chg_ctrl.current_thr.Discharge_Detection_Threshold / 100))
{
device_status.op_status = 0x0002;
}
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 0x0002: // Discharging
if (device_value.CCurrent > (device_param.chg_ctrl.current_thr.Charge_Detection_Threshold / 100))
{
device_status.op_status = 0x0001;
}
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 0x0004: // Warming Up
device_status.op_status = 0x0000; // Standby
break;
default:
device_status.op_status = 0x0000; // Standby
break;
}
// if (device_status.op_status == 0x0004)
// device_status.op_status = 0x0000; // Standby
// else
// {
// if (device_value.CCurrent > (device_param.chg_ctrl.current_thr.Charge_Detection_Threshold / 100))
// {
// device_status.op_status = 0x0001;
// }
// else if (device_value.DCurrent > (device_param.chg_ctrl.current_thr.Discharge_Detection_Threshold / 100))
// {
// device_status.op_status = 0x0002;
// }
// }
}
else
{
switch (device_status.op_status)
{
case 0x0000: // Stand by
// if (device_value.BatVoltage >= (device_param.chg_ctrl.chg_cfg.ST_Chg_Voltage))
if (device_value.BatVoltage >= 5200)
{
if (device_status.protection.value == 0)
device_status.op_status = 0x0003; // Floating
}
break;
case 0x0003: // 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 = 0x0000; // Floating
}
break;
default:
// if ((device_value.BatVoltage >= (device_param.chg_ctrl.chg_cfg.ST_Chg_Voltage))
if ((device_value.BatVoltage >= 5200)
&& (device_status.protection.value == 0))
device_status.op_status = 0x0003; // Floating
else
device_status.op_status = 0x0000; // Standby
break;
}
}
if (device_status.op_status == OP_STS_DISCHARGING)
{
device_status.battery_status.bit.CHG_C = true;
}
}
}