|
|
@@ -17,8 +17,6 @@ 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 uint8_t is_force_full = 0;
|
|
|
-static uint8_t is_force_empty = 0;
|
|
|
uint32_t charger_remain_time = 0;
|
|
|
|
|
|
#define MAX_TIME_FULL_TO_EMPTY (5 * 24 * 3600) //充满到欠压5天内达到,可以校准最小电量
|
|
|
@@ -163,7 +161,6 @@ static __inline__ int can_modify_min_cap(void){
|
|
|
|
|
|
static void _force_capacity_full(void){
|
|
|
_soc.capacity = 100;
|
|
|
- is_force_full = 1;
|
|
|
force_full_ts = shark_get_seconds();
|
|
|
}
|
|
|
|
|
|
@@ -173,20 +170,19 @@ int soc_update_by_ocv(void){
|
|
|
if (_soc.flags & SOC_FLAG_CALIBRATED){
|
|
|
if (!chargering){
|
|
|
if (bms_health()->is_work_temp_normal) {
|
|
|
- if (!is_force_empty && (bms_health()->powerdown_lower_voltage || bms_health()->sigle_cell_lower_voltage || bms_health()->discharger_lower_voltage)) {
|
|
|
+ if (_soc.capacity && (bms_health()->powerdown_lower_voltage || bms_health()->sigle_cell_lower_voltage || bms_health()->discharger_lower_voltage)) {
|
|
|
if (can_modify_min_cap()){
|
|
|
_soc.coulomb_min = _soc.coulomb_now; //已经校准过了,而且电池在常温下进入powerdown,最小容量修正为当前容量
|
|
|
}else {
|
|
|
_soc.coulomb_now = _soc.coulomb_min;
|
|
|
}
|
|
|
_soc.capacity = 0;
|
|
|
- is_force_empty = 1;
|
|
|
changed = 1;
|
|
|
soc_warning("current coulomb %f\n", _soc.coulomb_now);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- if (chargering && !is_force_full){
|
|
|
+ if (chargering && _soc.capacity != 100){
|
|
|
if (bms_health()->sigle_cell_over_voltage) {
|
|
|
_force_capacity_full();
|
|
|
ocv_full_count = 0;
|
|
|
@@ -214,7 +210,7 @@ static void soc_calibrate(uint8_t prev_charge_status){
|
|
|
static int cali_full_count = 0;
|
|
|
if (!(_soc.flags & SOC_FLAG_CALIBRATED)){
|
|
|
if (chargering){//用ocv进行严格校准
|
|
|
- if (!is_force_full){
|
|
|
+ if (_soc.capacity != 100){
|
|
|
if ((measure_value()->load_current <= FULL_MIN_CURRENT) && (bms_state_get()->pack_voltage >= FULL_MAX_VOLTAGE)){
|
|
|
cali_full_count ++;
|
|
|
}
|
|
|
@@ -224,7 +220,7 @@ static void soc_calibrate(uint8_t prev_charge_status){
|
|
|
}
|
|
|
}
|
|
|
}else if (prev_charge_status){
|
|
|
- if(!is_force_full && ((bms_state_get()->pack_voltage >= FULL_MAX_VOLTAGE) || bms_health()->sigle_cell_over_voltage)){
|
|
|
+ if((_soc.capacity != 100) && ((bms_state_get()->pack_voltage >= FULL_MAX_VOLTAGE) || bms_health()->sigle_cell_over_voltage)){
|
|
|
soc_debug("calibrate Capacity to 100\n");
|
|
|
_force_capacity_full();
|
|
|
}
|
|
|
@@ -259,40 +255,41 @@ uint32_t soc_get_charger_remain_time(void){
|
|
|
|
|
|
static void soc_update_by_current_and_time(float current_now, float delta_time, uint8_t prev_charge_status){
|
|
|
double current = current_now / 1000.0f; //A
|
|
|
- double delta_q = current * delta_time;
|
|
|
+ double delta_q = current * delta_time;
|
|
|
+ uint8_t est_capaticy = _soc.capacity;
|
|
|
+ int update_capticy = 0;
|
|
|
+ double est_coulomb = _soc.coulomb_now + delta_q;//计算当前容量,充电加, 放电减
|
|
|
+
|
|
|
+ if (est_coulomb < 0){
|
|
|
+ est_coulomb = 0;
|
|
|
+ }else if (est_coulomb > _soc.coulomb_max) {
|
|
|
+ est_coulomb = _soc.coulomb_max;
|
|
|
+ }
|
|
|
+ est_capaticy = ((est_coulomb - _soc.coulomb_min)/(_soc.coulomb_max - _soc.coulomb_min) + 0.005f) * 100;//四舍五入
|
|
|
+
|
|
|
if (chargering){
|
|
|
delta_q = delta_q * _charger_coefficient;
|
|
|
_soc.charger_coulomb += abs(delta_q);
|
|
|
+ if (est_capaticy < 100 ){ //充电,容量不能等于100,需要靠电压和充电电流来矫正到100
|
|
|
+ update_capticy = 1;
|
|
|
+ }
|
|
|
}else {
|
|
|
delta_q = delta_q * _discharger_coefficient;
|
|
|
- _soc.dischrger_coulomb += abs(delta_q); //转为正数
|
|
|
- }
|
|
|
- _soc.coulomb_now = _soc.coulomb_now + delta_q; //充电加, 放电减
|
|
|
-
|
|
|
- if (_soc.coulomb_now < 0){
|
|
|
- _soc.coulomb_now = 0;
|
|
|
- }else if (_soc.coulomb_now > _soc.coulomb_max) {
|
|
|
- _soc.coulomb_now = _soc.coulomb_max;
|
|
|
- }
|
|
|
- uint8_t old_cap = _soc.capacity;
|
|
|
- if ((_soc.coulomb_now - _soc.coulomb_min) >= 0){
|
|
|
- _soc.capacity = ((_soc.coulomb_now - _soc.coulomb_min)/(_soc.coulomb_max - _soc.coulomb_min) + 0.005f) * 100;//四舍五入
|
|
|
- }else {
|
|
|
- _soc.capacity = 0;
|
|
|
- }
|
|
|
- if (_soc.capacity > 100){
|
|
|
- _soc.capacity = 100;
|
|
|
- }
|
|
|
- if (chargering && (_soc.capacity == 100) && (!is_force_full)){
|
|
|
- _soc.capacity = 99;//充电的时候必须通过ocv才能把电量校准到100
|
|
|
- }else if (!chargering && (_soc.capacity == 0) && !is_force_empty){
|
|
|
- _soc.capacity = 1;
|
|
|
+ _soc.dischrger_coulomb += abs(delta_q);
|
|
|
+ if (est_capaticy > 0) { //放电,容量不能等于0,需要靠欠压或者PowerDown 矫正到0
|
|
|
+ update_capticy = 1;
|
|
|
+ }
|
|
|
}
|
|
|
- if (is_force_empty && (_soc.capacity == 1)) {
|
|
|
- _soc.capacity = 0;
|
|
|
+ if (update_capticy) {
|
|
|
+ if (_soc.capacity != est_capaticy) {
|
|
|
+ _soc.capacity = est_capaticy;
|
|
|
+ }else {
|
|
|
+ update_capticy = 0;
|
|
|
+ }
|
|
|
+ _soc.coulomb_now = est_coulomb;
|
|
|
}
|
|
|
//通过电压校准SOC,只能在电压范围的两端校准
|
|
|
- soc_update_by_ocv();
|
|
|
+ update_capticy |= soc_update_by_ocv();
|
|
|
soc_calibrate(prev_charge_status);
|
|
|
|
|
|
//如果没有校准过,充电过程中,电量100%后,设置校准标志位
|
|
|
@@ -300,7 +297,7 @@ static void soc_update_by_current_and_time(float current_now, float delta_time,
|
|
|
_soc.coulomb_now = _soc.coulomb_max;//充满后,当前容量设置为最大容量
|
|
|
if ((_soc.flags & SOC_FLAG_CALIBRATED) == 0){
|
|
|
_soc.flags |= SOC_FLAG_CALIBRATED;
|
|
|
- nv_save_soc();
|
|
|
+ update_capticy = 1;
|
|
|
soc_warning("calibrate OK, charging coulomb: %f\n", _soc.charger_coulomb);
|
|
|
}else { //如果校准过,单电芯过压,100%的容量,设置最大容量为当前容量
|
|
|
if (bms_health()->sigle_cell_over_voltage){
|
|
|
@@ -314,7 +311,7 @@ static void soc_update_by_current_and_time(float current_now, float delta_time,
|
|
|
}
|
|
|
}
|
|
|
_soc.energy = bms_state_get()->pack_voltage/1000.f * (_soc.coulomb_now - _soc.coulomb_min);
|
|
|
- if (old_cap != _soc.capacity) {
|
|
|
+ if (update_capticy) {
|
|
|
nv_save_soc();
|
|
|
}
|
|
|
|
|
|
@@ -349,16 +346,6 @@ void soc_update(void){
|
|
|
start_least_square(1);
|
|
|
}
|
|
|
#endif
|
|
|
- if (chargering && is_force_empty){
|
|
|
- //欠压后,只有当充电0.5%后,才显示真实电量,防止骑行过程电量0,1跳变
|
|
|
- if (_soc.charger_coulomb / (_soc.coulomb_max - _soc.coulomb_min) >= 0.005) {
|
|
|
- is_force_empty = 0;
|
|
|
- }
|
|
|
- }else if (!chargering && is_force_full) {
|
|
|
- if (_soc.dischrger_coulomb / (_soc.coulomb_max - _soc.coulomb_min) >= 0.005) {
|
|
|
- is_force_full = 0;
|
|
|
- }
|
|
|
- }
|
|
|
soc_update_by_current_and_time(measure_value()->load_current, _delta_time(), pre_chargering);
|
|
|
soc_update_charger_remain_time();
|
|
|
}
|