|
|
@@ -19,18 +19,20 @@ 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;
|
|
|
+static float _discharger_no_full_coef = 1.0f;
|
|
|
static uint32_t charger_remain_time = 0;
|
|
|
-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*/};
|
|
|
+static uint8_t version_changed = 0;
|
|
|
+static const float _discharger_gain[] = {1.0f/*>0度*/, 1.03f/*-2<t<=0*/, 1.04f/*-5<t<=-2*/, 1.05f/*-10<t<=-5*/, 1.06f/*-15<t<=-10*/, 1.08f/*-20<t<=-15*/};
|
|
|
#define MAX_TIME_FULL_TO_EMPTY (5 * 24 * 3600) //充满到欠压5天内达到,可以校准最小电量
|
|
|
#define MAX_TIME_EMPTY_TO_FULL (24 * 3600) //欠压到充满24小时内达到,可以校准最小电量
|
|
|
#define DEFALUT_MAX_COULOMB (MAX_HA * 3600.0f)
|
|
|
#define DEFALUT_MIN_COULOMB (25.0f * 3600.0f)
|
|
|
-#define FULL_MAX_VOLTAGE_CHARGING (54000)//mV
|
|
|
-#define FULL_MAX_VOLTAGE_STOP_CHARGING (53500)
|
|
|
+#define FULL_MAX_VOLTAGE_CHARGING (53500)//mV
|
|
|
+#define FULL_MAX_VOLTAGE_STOP_CHARGING (53000)
|
|
|
#define AGINT_TEST_MAX_VOLTAGE_CHARGING (53000) //mV
|
|
|
#define FULL_MAX_VOLTAGE (54000) //mV
|
|
|
#define FULL_MIN_CURRENT (500.0f) //mA
|
|
|
-static double start_charger_coulomb = 0.0f; //开始充电时候的容量
|
|
|
+//static double start_charger_coulomb = 0.0f; //开始充电时候的容量
|
|
|
static void calibrate_soc_by_ocv(void);
|
|
|
static void _soc_clear(void);
|
|
|
|
|
|
@@ -68,7 +70,10 @@ void soc_init(void){
|
|
|
}
|
|
|
}
|
|
|
if (soc_get_version() != SOC_CURRENT_VERSION) {
|
|
|
- //DO SOMETHING, FOR SOC VERSION CHANGED
|
|
|
+ _soc.current_real_coulomb = (_soc.coulomb_now - _soc.coulomb_min);
|
|
|
+ version_changed = 1;
|
|
|
+ soc_set_version(SOC_CURRENT_VERSION);
|
|
|
+ nv_save_all_soc();
|
|
|
}
|
|
|
soc_log();
|
|
|
}
|
|
|
@@ -88,12 +93,13 @@ void soc_set_version(u8 version) {
|
|
|
static void _soc_clear(void){
|
|
|
_soc.coulomb_min = 0;
|
|
|
_soc.coulomb_max = DEFALUT_MAX_COULOMB; //30HA,这个值最总需要soh模块给
|
|
|
- _soc.flags = 0;
|
|
|
+ _soc.flags = SOC_FLAG_VERSION(SOC_CURRENT_VERSION);
|
|
|
_soc.charger_coulomb = 0;
|
|
|
_soc.pre_charger_coulomb = 0;
|
|
|
_soc.dischrger_coulomb = 0;
|
|
|
_soc.pre_discharger_coulomb = 0;
|
|
|
_soc.total_coulomb = 0;
|
|
|
+ _soc.current_real_coulomb = 0;
|
|
|
}
|
|
|
|
|
|
void soc_clear_calibrate(int keep_cycle) {
|
|
|
@@ -172,6 +178,8 @@ static void soc_update_discharger_coeff(void){
|
|
|
}
|
|
|
if ((abs(measure_value()->load_current) > 10.0f) && (abs(measure_value()->load_current) < 500)) {
|
|
|
coff = 1.05f;
|
|
|
+ }else {
|
|
|
+ coff = _discharger_no_full_coef;
|
|
|
}
|
|
|
_discharger_coefficient = _discharger_coefficient * coff;
|
|
|
}
|
|
|
@@ -222,12 +230,11 @@ void soc_log(void){
|
|
|
soc_debug("C max: %.4f\n", TOHA(_soc.coulomb_max));
|
|
|
soc_debug("C char: %.4f\n", TOHA(_soc.charger_coulomb));
|
|
|
soc_debug("C dischar: %.4f\n", TOHA(_soc.dischrger_coulomb));
|
|
|
- soc_debug("C pre char: %.4f\n", TOHA(_soc.pre_discharger_coulomb));
|
|
|
- soc_debug("C pre dischar: %.4f\n", TOHA(_soc.pre_charger_coulomb));
|
|
|
+ soc_debug("C version: %d, %d\n", soc_get_version(), version_changed);
|
|
|
soc_debug("C tol: %.2f\n", _soc.total_coulomb);
|
|
|
- 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("C real_coulomb: %f\n", _soc.current_real_coulomb);
|
|
|
+ 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, %d\n", _discharger_coefficient, _discharger_no_full_coef);
|
|
|
if (chargering){
|
|
|
soc_debug("C remain %d\n", charger_remain_time);
|
|
|
}
|
|
|
@@ -311,26 +318,38 @@ bool soc_is_force_full(void) {
|
|
|
static void _force_capacity_full(void){
|
|
|
is_force_full = true;
|
|
|
force_full_time = shark_get_seconds();
|
|
|
- double curr_real_cap = start_charger_coulomb + _soc.charger_coulomb;
|
|
|
double curr_min_cap = 0.0f;
|
|
|
- if (can_modify_min_when_full()) { //前面出现过电芯欠压, 当前容量没到最大容量
|
|
|
- if (curr_real_cap > _soc.coulomb_max) {
|
|
|
- curr_min_cap = _soc.coulomb_min - (curr_real_cap - _soc.coulomb_max);
|
|
|
- }else {
|
|
|
- curr_min_cap = _soc.coulomb_max - curr_real_cap + _soc.coulomb_min;
|
|
|
- }
|
|
|
- if (curr_min_cap < 0.0f) {
|
|
|
- curr_min_cap = 0.0f;
|
|
|
+
|
|
|
+ if ((_soc.flags & SOC_FLAG_CALIBRATED) == 0){
|
|
|
+ _soc.current_real_coulomb = _soc.coulomb_max;
|
|
|
+ _discharger_no_full_coef = 1.0f;
|
|
|
+ }else {
|
|
|
+ if (bms_state_get()->pack_voltage >= 52500) {
|
|
|
+ _soc.current_real_coulomb = _soc.coulomb_max - _soc.coulomb_min;
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_soc.current_real_coulomb < _soc.coulomb_max) {
|
|
|
+ curr_min_cap = _soc.coulomb_max - _soc.current_real_coulomb;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (can_modify_min_when_full()) { //前面出现过电芯欠压, 当前容量没到最大容量
|
|
|
//don't trust if curr_min_cap big than before
|
|
|
- if (curr_min_cap < _soc.coulomb_min) {
|
|
|
+ if (curr_min_cap <= _soc.coulomb_min) {
|
|
|
_soc.coulomb_min = _soc.coulomb_min * (1.0f - min_cap_lfp) + curr_min_cap * min_cap_lfp; //lowpass filter
|
|
|
}
|
|
|
}
|
|
|
- u32 cap_x10 = (u32)(curr_real_cap / 3600.0f * 10);
|
|
|
+ if (curr_min_cap <= _soc.coulomb_min) {
|
|
|
+ _discharger_no_full_coef = 1.0f;
|
|
|
+ }else {
|
|
|
+ double delta_min = curr_min_cap - _soc.coulomb_min;
|
|
|
+ _discharger_no_full_coef = 1.0f + delta_min/(_soc.coulomb_max - _soc.coulomb_min);
|
|
|
+ }
|
|
|
+
|
|
|
+ push_event(Charger_no_full_ceof, (u32)(_discharger_no_full_coef * 10000));
|
|
|
+ u32 cap_x10 = (u32)(_soc.current_real_coulomb / 3600.0f * 10);
|
|
|
u32 min_x10 = (u32)(curr_min_cap / 3600.0f * 10);
|
|
|
push_event(Charger_Full_cap2, ((min_x10 & 0xFFFF) << 16) | (cap_x10 & 0xFFFF));
|
|
|
-
|
|
|
//充满后,当前容量设置为最大容量
|
|
|
_soc.capacity = 100;
|
|
|
_soc.coulomb_now = _soc.coulomb_max;
|
|
|
@@ -375,30 +394,36 @@ static int _soc_update_by_ocv(uint8_t prev_charge_status){
|
|
|
push_event(Min_Cap_For_DisCharger2, (bms_state_get()->pack_voltage << 16) | (cap_x10 & 0xFFFF));
|
|
|
force_empty_ts = shark_get_seconds();
|
|
|
_soc.capacity = 0;
|
|
|
+ _soc.current_real_coulomb = 0.0f;
|
|
|
return 1;
|
|
|
}
|
|
|
}
|
|
|
- if (chargering || prev_charge_status) {
|
|
|
- if (chargering && (_soc.capacity != 100)) {
|
|
|
- if (bms_health()->sigle_cell_over_voltage && _is_normal_charging()) { //单电芯过压强制充满
|
|
|
+ if ((chargering || prev_charge_status) && (_soc.capacity != 100)) {
|
|
|
+ if (chargering) {
|
|
|
+ if (bms_health()->sigle_cell_over_voltage) { //单电芯过压强制充满
|
|
|
_force_capacity_full();
|
|
|
push_event(Charger_Full, bms_state_get()->pack_voltage);
|
|
|
ocv_full_count = 0;
|
|
|
changed = 1;
|
|
|
- }else if (bms_state_get()->pack_voltage >= (FULL_MAX_VOLTAGE_CHARGING) && _is_normal_charging()){
|
|
|
- if (ocv_full_count++ >= 100) { //连续100次(电流采集25(小于4A)或者5ms一次)电压和电流满足条件,强制充满
|
|
|
+ }else if (bms_state_get()->pack_voltage >= (FULL_MAX_VOLTAGE_CHARGING)){
|
|
|
+ if (ocv_full_count++ >= CELLS_NUM) { //连续100次(电流采集25(小于4A)或者5ms一次)电压和电流满足条件,强制充满
|
|
|
_force_capacity_full();
|
|
|
- push_event(Charger_Full, 4);
|
|
|
+ push_event(Charger_Full, bms_state_get()->pack_voltage);
|
|
|
ocv_full_count = 0;
|
|
|
changed = 1;
|
|
|
}
|
|
|
+ }else if (bms_state_get()->pack_voltage >= FULL_MAX_VOLTAGE) {
|
|
|
+ _force_capacity_full();
|
|
|
+ push_event(Charger_Full, bms_state_get()->pack_voltage);
|
|
|
+ ocv_full_count = 0;
|
|
|
+ changed = 1;
|
|
|
}else {
|
|
|
ocv_full_count = 0;
|
|
|
}
|
|
|
- } else if (!chargering && prev_charge_status && (_soc.capacity != 100)){
|
|
|
+ } else if (prev_charge_status){
|
|
|
if ((bms_state_get()->pack_voltage >= FULL_MAX_VOLTAGE_STOP_CHARGING) && _is_normal_charging()){//充电容量几乎接近最大容量
|
|
|
_force_capacity_full();
|
|
|
- push_event(Charger_Full, 5);
|
|
|
+ push_event(Charger_Full, 1);
|
|
|
changed = 1;
|
|
|
}
|
|
|
}
|
|
|
@@ -424,7 +449,7 @@ static void soc_calibrate(uint8_t prev_charge_status){
|
|
|
push_event(Charger_Full, 13);
|
|
|
}
|
|
|
}else {
|
|
|
- if ((bms_state_get()->pack_voltage >= FULL_MAX_VOLTAGE_CHARGING) && _is_normal_charging()){
|
|
|
+ if ((bms_state_get()->pack_voltage >= FULL_MAX_VOLTAGE_CHARGING)){
|
|
|
_force_capacity_full();
|
|
|
push_event(Charger_Full, 10);
|
|
|
}else if (bms_health()->sigle_cell_over_voltage) {
|
|
|
@@ -510,12 +535,21 @@ static void soc_update_by_current_and_time(float current_now, float delta_time,
|
|
|
}
|
|
|
if (chargering){
|
|
|
delta_q = delta_q * _charger_coefficient;
|
|
|
+ _soc.current_real_coulomb += abs(delta_q);
|
|
|
+ if (_soc.current_real_coulomb > _soc.coulomb_max) {
|
|
|
+ _soc.current_real_coulomb = _soc.coulomb_max;
|
|
|
+ }
|
|
|
_soc.charger_coulomb += abs(delta_q);
|
|
|
if ((est_capaticy < 100) && (est_capaticy >= _soc.capacity)){ //充电,容量不能等于100,需要靠电压和充电电流来矫正到100
|
|
|
update_capticy = 1;
|
|
|
}
|
|
|
}else {
|
|
|
_soc.dischrger_coulomb += abs(delta_q);
|
|
|
+ _soc.current_real_coulomb -= abs(delta_q) / _discharger_no_full_coef;
|
|
|
+ if (_soc.current_real_coulomb < 0) {
|
|
|
+ _soc.current_real_coulomb = 0;
|
|
|
+ }
|
|
|
+
|
|
|
if (est_coulomb < _soc.coulomb_min) {
|
|
|
_soc.coulomb_min = est_coulomb;
|
|
|
}
|
|
|
@@ -543,9 +577,7 @@ static void soc_update_by_current_and_time(float current_now, float delta_time,
|
|
|
soc_warning("calibrate OK, charging coulomb: %f\n", _soc.charger_coulomb);
|
|
|
}
|
|
|
}
|
|
|
- if (_soc.coulomb_now >= _soc.coulomb_min) {
|
|
|
- _soc.energy = bms_state_get()->pack_voltage/1000.f * (_soc.coulomb_now - _soc.coulomb_min);
|
|
|
- }
|
|
|
+
|
|
|
if (update_capticy) {
|
|
|
nv_save_soc();
|
|
|
}
|
|
|
@@ -564,8 +596,7 @@ void soc_update(void){
|
|
|
_soc.pre_charger_coulomb = _soc.charger_coulomb;
|
|
|
_soc.charger_coulomb = 0;//clear charing
|
|
|
_soc.total_coulomb += _soc.pre_charger_coulomb / 3600.0f;
|
|
|
- chargering = 1;
|
|
|
- start_charger_coulomb = _soc.coulomb_now;
|
|
|
+ chargering = 1;
|
|
|
#if LEAST_SQUARE==1
|
|
|
start_least_square(0);
|
|
|
#endif
|
|
|
@@ -576,6 +607,11 @@ void soc_update(void){
|
|
|
_soc.total_coulomb += _soc.pre_discharger_coulomb / 3600.0f;
|
|
|
chargering = 0;
|
|
|
charger_remain_time = 0;
|
|
|
+ if (_is_normal_charging() && (_soc.capacity != 100)) {
|
|
|
+ u32 charger_cap_x10 = (u32)(_soc.charger_coulomb / 3600.0f * 10);
|
|
|
+ u32 cur_cap_x10 = (u32)(_soc.coulomb_now / 3600.0f * 10);
|
|
|
+ push_event(Charger_no_full_capaticy, ((cur_cap_x10 & 0xFFFF) << 16) | (charger_cap_x10 & 0xFFFF));
|
|
|
+ }
|
|
|
soc_warning("changed to dischargering, current = %d\n", measure_value()->load_current);
|
|
|
}
|
|
|
#if LEAST_SQUARE==1
|