|
|
@@ -17,10 +17,11 @@ static float soc_delta_time = 0;
|
|
|
static float max_soc_delta_time = 0;
|
|
|
static float _charger_coefficient = 1.0f;
|
|
|
static float _discharger_coefficient = 1.0f;
|
|
|
-uint32_t charger_remain_time = 0;
|
|
|
-uint8_t battery_temp_state = 0;
|
|
|
+static uint32_t charger_remain_time = 0;
|
|
|
+static bool _is_cell_lower_vol = false;
|
|
|
static const float _discharger_gain[] = {1.0f/*>0度*/, 1.002f/*-2<t<=0*/, 1.005f/*-5<t<=-2*/, 1.008f/*-10<t<=-5*/, 1.02f/*-15<t<=-10*/, 1.04f/*-20<t<=-15*/};
|
|
|
#define MAX_TIME_FULL_TO_EMPTY (5 * 24 * 3600) //充满到欠压5天内达到,可以校准最小电量
|
|
|
+#define MAX_TIME_EMPTY_TO_FULL (8 * 24 * 3600) //充满到欠压5天内达到,可以校准最小电量
|
|
|
#define DEFALUT_MAX_COULOMB (MAX_HA * 3600.0f)
|
|
|
#define DEFALUT_MIN_COULOMB (25.0f * 3600.0f)
|
|
|
#define FULL_MAX_VOLTAGE_CHARGING (53500)//mV
|
|
|
@@ -29,6 +30,8 @@ static const float _discharger_gain[] = {1.0f/*>0
|
|
|
#define FULL_MIN_CURRENT (500.0f) //mA
|
|
|
static int _full_reason = 0;
|
|
|
static int _force_full = 0;
|
|
|
+static int _force_full_minc = 0;
|
|
|
+static double start_charger_coulomb = 0.0f; //开始充电时候的容量
|
|
|
static void calibrate_soc_by_ocv(void);
|
|
|
static void _soc_clear(void);
|
|
|
|
|
|
@@ -58,10 +61,29 @@ void soc_init(void){
|
|
|
if ((_soc.flags & SOC_FLAG_CALIBRATED) == 0){
|
|
|
calibrate_soc_by_ocv();
|
|
|
nv_save_soc();
|
|
|
+ }else {
|
|
|
+ if (_soc.capacity == 100) {
|
|
|
+ force_full_ts = shark_get_seconds() + 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (soc_get_version() != SOC_CURRENT_VERSION) {
|
|
|
+ //DO SOMETHING, FOR SOC VERSION CHANGED
|
|
|
}
|
|
|
soc_log();
|
|
|
}
|
|
|
|
|
|
+u8 soc_get_version(void) {
|
|
|
+ return SOC_FLAG_TO_VER(_soc.flags);
|
|
|
+}
|
|
|
+
|
|
|
+void soc_set_version(u8 version) {
|
|
|
+ if (version > 7) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ _soc.flags &= ~SOC_FLAG_VERSON_MASK;
|
|
|
+ _soc.flags |= SOC_FLAG_VERSION(version);
|
|
|
+}
|
|
|
+
|
|
|
static void _soc_clear(void){
|
|
|
_soc.coulomb_min = 0;
|
|
|
_soc.coulomb_max = DEFALUT_MAX_COULOMB; //30HA,这个值最总需要soh模块给
|
|
|
@@ -196,7 +218,8 @@ void soc_log(void){
|
|
|
soc_debug("C energy: %f\n", _soc.energy);
|
|
|
soc_debug("C delta time %f,%f, -- %d\n", max_soc_delta_time, soc_delta_time, force_full_ts);
|
|
|
soc_debug("C discharger coefficient = %f\n", _discharger_coefficient);
|
|
|
- soc_debug("forcce full = %d, %d\n", _full_reason, _force_full);
|
|
|
+ soc_debug("forcce full = %d, %d, %d, %d\n", _full_reason, _force_full, _force_full_minc, force_full_ts);
|
|
|
+ soc_debug("Discharger: %s\n", _is_cell_lower_vol?"Lower vol":"Normal");
|
|
|
if (chargering){
|
|
|
soc_debug("C remain %d\n", charger_remain_time);
|
|
|
}
|
|
|
@@ -251,10 +274,37 @@ static __inline__ int can_modify_min_cap(void){
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static __inline__ int can_modify_min_when_full(void){
|
|
|
+ if (force_full_ts == 0) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if (shark_get_seconds() > force_full_ts){
|
|
|
+ if ((shark_get_seconds() - force_full_ts) > MAX_TIME_EMPTY_TO_FULL) {
|
|
|
+ return 0;
|
|
|
+ }else {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
static void _force_capacity_full(void){
|
|
|
_soc.capacity = 100;
|
|
|
+ if (can_modify_min_when_full()) { //前面出现过电芯欠压, 当前容量没到最大容量
|
|
|
+ double curr_real_cap = start_charger_coulomb + _soc.charger_coulomb;
|
|
|
+ if (curr_real_cap > _soc.coulomb_max) {
|
|
|
+ _soc.coulomb_min = 0;
|
|
|
+ }else {
|
|
|
+ _soc.coulomb_min = _soc.coulomb_max - curr_real_cap;
|
|
|
+ }
|
|
|
+ soc_warning("current real cap %f\n", curr_real_cap);
|
|
|
+ _force_full_minc ++;
|
|
|
+ }
|
|
|
_soc.coulomb_now = _soc.coulomb_max;//充满后,当前容量设置为最大容量
|
|
|
+
|
|
|
force_full_ts = shark_get_seconds();
|
|
|
+ _is_cell_lower_vol = false;
|
|
|
_force_full = 2;
|
|
|
}
|
|
|
|
|
|
@@ -263,20 +313,6 @@ static int _soc_is_under_voltage(void) {
|
|
|
bms_health()->discharger_lower_voltage);
|
|
|
}
|
|
|
|
|
|
-#if 0
|
|
|
-static int _soc_force_capaticy(uint8_t capaticy){
|
|
|
- float cap = (float)capaticy / 100.0f;
|
|
|
- float min = (_soc.coulomb_now - cap * _soc.coulomb_max)/(1.0f - cap);
|
|
|
- if (min > 0.0f) {
|
|
|
- _soc.coulomb_min = min;
|
|
|
- _soc.capacity = capaticy;
|
|
|
- force_full_ts = 0xFFFFFFFF;
|
|
|
- return 1;
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
static int _soc_update_by_ocv(uint8_t prev_charge_status){
|
|
|
static int ocv_full_count = 0;
|
|
|
//static int ocv_force_capaticy = 0;
|
|
|
@@ -293,47 +329,28 @@ static int _soc_update_by_ocv(uint8_t prev_charge_status){
|
|
|
}else if (health_is_mid_current()) {
|
|
|
_soc.coulomb_min = _soc.coulomb_now * 1.0f;
|
|
|
}else if (health_is_big_current()){
|
|
|
- _soc.coulomb_min = _soc.coulomb_now * 0.95f;
|
|
|
+ _soc.coulomb_min = _soc.coulomb_now * 0.975f;
|
|
|
}else {
|
|
|
- _soc.coulomb_min = _soc.coulomb_now * 0.90f;
|
|
|
+ _soc.coulomb_min = _soc.coulomb_now * 0.95f;
|
|
|
}
|
|
|
_soc.coulomb_now = _soc.coulomb_min;
|
|
|
soc_warning("calicablite coulomb_min %f\n", _soc.coulomb_min);
|
|
|
}else {
|
|
|
_soc.coulomb_now = _soc.coulomb_min;
|
|
|
}
|
|
|
+ _is_cell_lower_vol = true;
|
|
|
_soc.capacity = 0;
|
|
|
return 1;
|
|
|
- }
|
|
|
-#if 0
|
|
|
- else if ((!prev_charge_status) && (bms_state_get()->cell_min_vol <= 2900) && (_soc.capacity > 10)) {
|
|
|
- /* 如果单电芯最小电压小于2.9v,并且容量大于10%,需要校准到10% */
|
|
|
- if (ocv_force_capaticy++ >= 10) {
|
|
|
- return _soc_force_capaticy(10);
|
|
|
- }
|
|
|
- }else {
|
|
|
- ocv_force_capaticy = 0;
|
|
|
- }
|
|
|
-#endif
|
|
|
+ }
|
|
|
}
|
|
|
if (chargering || prev_charge_status) {
|
|
|
- //ocv_force_capaticy = 0;
|
|
|
- /*
|
|
|
- if (bms_state_get()->ps_charger_mask && !bms_state_get()->ps_charger_in) { //ps100 上报无充电器,不做处理
|
|
|
- ocv_full_count = 0;
|
|
|
- return changed;
|
|
|
- }*/
|
|
|
- if (chargering && bms_health()->sigle_cell_over_voltage) { //单电芯过压强制充满
|
|
|
- _force_capacity_full();
|
|
|
- _full_reason = 3;
|
|
|
- if (bms_state_get()->pack_voltage < SIGAL_CELL_OV_MAX_PACK_VOL) {
|
|
|
- force_full_ts = 0; //单电芯过压,总电压小于SIGAL_CELL_OV_MAX_PACK_VOL, 放电欠压后不校准最小容量
|
|
|
- }
|
|
|
- ocv_full_count = 0;
|
|
|
- return 1;
|
|
|
- }
|
|
|
- if (chargering && (_soc.capacity != 100)) {
|
|
|
- if (bms_state_get()->pack_voltage >= (FULL_MAX_VOLTAGE_CHARGING) && (measure_value()->load_current <= FULL_MIN_CURRENT)){
|
|
|
+ if (chargering && (_soc.capacity != 100)) {
|
|
|
+ if (bms_health()->sigle_cell_over_voltage) { //单电芯过压强制充满
|
|
|
+ _force_capacity_full();
|
|
|
+ _full_reason = 3;
|
|
|
+ ocv_full_count = 0;
|
|
|
+ changed = 1;
|
|
|
+ }else if (bms_state_get()->pack_voltage >= (FULL_MAX_VOLTAGE_CHARGING) && (measure_value()->load_current <= FULL_MIN_CURRENT)){
|
|
|
if (ocv_full_count++ >= 100) { //连续100次(小电流采集30ms一次,就是3s时间)电压和电流满足条件,强制充满
|
|
|
_force_capacity_full();
|
|
|
_full_reason = 4;
|
|
|
@@ -343,7 +360,7 @@ static int _soc_update_by_ocv(uint8_t prev_charge_status){
|
|
|
}else {
|
|
|
ocv_full_count = 0;
|
|
|
}
|
|
|
- }else if (!chargering && prev_charge_status && (_soc.capacity != 100)){
|
|
|
+ } else if (!chargering && prev_charge_status && (_soc.capacity != 100)){
|
|
|
if ((bms_state_get()->pack_voltage >= FULL_MAX_VOLTAGE) && (_soc.charger_coulomb >= (0.1f * 3600.0f))){//充电容量几乎接近最大容量
|
|
|
_force_capacity_full();
|
|
|
_full_reason = 5;
|
|
|
@@ -383,7 +400,6 @@ static void soc_calibrate(uint8_t prev_charge_status){
|
|
|
if (_soc.capacity && _soc_is_under_voltage()) {
|
|
|
_soc.capacity = 0;
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -475,15 +491,6 @@ static void soc_update_by_current_and_time(float current_now, float delta_time,
|
|
|
_soc.flags |= SOC_FLAG_CALIBRATED;
|
|
|
update_capticy = 1;
|
|
|
soc_warning("calibrate OK, charging coulomb: %f\n", _soc.charger_coulomb);
|
|
|
- }else { //如果校准过,单电芯过压,100%的容量,设置最大容量为当前容量
|
|
|
- if (bms_health()->sigle_cell_over_voltage){
|
|
|
-#if 0 /* 暂时去掉,最大容量不变化,只校准欠压后的可放电的最小容量 */
|
|
|
- if ((_soc.coulomb_now >= DEFALUT_MIN_COULOMB) && (_soc.coulomb_now <= DEFALUT_MAX_COULOMB)) {
|
|
|
- _soc.coulomb_max = _soc.coulomb_now;
|
|
|
- soc_warning("signal cell over vol, cap full, reset coul max to coul now: %f\n", _soc.coulomb_max);
|
|
|
- }
|
|
|
-#endif
|
|
|
- }
|
|
|
}
|
|
|
}
|
|
|
if (_soc.coulomb_now >= _soc.coulomb_min) {
|
|
|
@@ -508,6 +515,7 @@ void soc_update(void){
|
|
|
_soc.charger_coulomb = 0;//clear charing
|
|
|
_soc.total_coulomb += _soc.pre_charger_coulomb / 3600.0f;
|
|
|
chargering = 1;
|
|
|
+ start_charger_coulomb = _soc.coulomb_now - _soc.coulomb_min;
|
|
|
#if LEAST_SQUARE==1
|
|
|
start_least_square(0);
|
|
|
#endif
|