|
|
@@ -7,10 +7,12 @@
|
|
|
#include "state.h"
|
|
|
|
|
|
static soc_t _soc;
|
|
|
-static uint8_t charing = 0;
|
|
|
+static uint8_t chargering = 0;
|
|
|
static u64 time_ms = 0;
|
|
|
static float _charger_coefficient = 1.0f;
|
|
|
static float _discharger_coefficient = 1.0f;
|
|
|
+uint32_t charger_remain_time = 0;
|
|
|
+#define DEFALUT_MAX_COULOMB (MAX_HA * 3600.0f)
|
|
|
|
|
|
static void calibrate_soc_by_ocv(void);
|
|
|
|
|
|
@@ -21,7 +23,15 @@ void soc_init(void){
|
|
|
if (nv_restore_soc() != 0){
|
|
|
soc_warning("SOC: nv storage is not inited, use default value!!\n");
|
|
|
_soc.coulomb_min = 0;
|
|
|
- _soc.coulomb_max = 30.0f * 3600.0f; //30HA,这个值最总需要soh模块给
|
|
|
+ _soc.coulomb_max = DEFALUT_MAX_COULOMB; //30HA,这个值最总需要soh模块给
|
|
|
+ _soc.flags = 0;
|
|
|
+ _soc.charger_coulomb = 0;
|
|
|
+ _soc.pre_charger_coulomb = 0;
|
|
|
+ _soc.dischrger_coulomb = 0;
|
|
|
+ _soc.pre_discharger_coulomb = 0;
|
|
|
+ _soc.total_coulomb = 0;
|
|
|
+ }
|
|
|
+ if ((_soc.flags & SOC_FLAG_CALIBRATED) == 0){
|
|
|
calibrate_soc_by_ocv();
|
|
|
nv_save_soc();
|
|
|
}
|
|
|
@@ -48,7 +58,7 @@ static void calibrate_soc_by_ocv(void){
|
|
|
}else {
|
|
|
_soc.capacity = 100;
|
|
|
}
|
|
|
- _soc.coulomb_now = _soc.coulomb_max * _soc.capacity / 100.0f;
|
|
|
+ _soc.coulomb_now = (_soc.coulomb_max - _soc.coulomb_min) * _soc.capacity / 100.0f + _soc.coulomb_min;
|
|
|
soc_warning("SOC: calibrate_soc_by_ocv -> capacity = %d, pack_voltage = %d\n", _soc.capacity, pack_vol);
|
|
|
}
|
|
|
|
|
|
@@ -58,17 +68,71 @@ static __inline__ float _delta_time(void){
|
|
|
return (float)delta / (1000.0f); //秒
|
|
|
}
|
|
|
|
|
|
+void soc_update_by_ocv(void){
|
|
|
+ if (_soc.flags & SOC_FLAG_CALIBRATED){
|
|
|
+ if (bms_health()->powerdown_lower_voltage){
|
|
|
+ _soc.coulomb_min = _soc.coulomb_now; //已经校准过了,而且电池进入powerdown,最小容量修正为当前容量
|
|
|
+ _soc.capacity = 0;
|
|
|
+ soc_warning("current coulomb %f\n", _soc.coulomb_now);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (chargering){
|
|
|
+ if (bms_state_get()->pack_voltage >= (54000)){
|
|
|
+ _soc.capacity = 100;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }else {
|
|
|
+ if (chargering){//用ocv进行严格校准
|
|
|
+ if (measure_value()->load_current <= 300.0f){
|
|
|
+ //判断总电压
|
|
|
+ if (bms_state_get()->pack_voltage >= 54000){
|
|
|
+ _soc.capacity = 100;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void soc_update_charger_remain_time(void){
|
|
|
+ if (!chargering) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ float delta_c = _soc.coulomb_max - _soc.coulomb_now;
|
|
|
+ float current = measure_value()->load_current / 1000.0f; //A
|
|
|
+ uint32_t remain = delta_c / current / 60; //分钟
|
|
|
+ if (charger_remain_time == 0){
|
|
|
+ charger_remain_time = remain;
|
|
|
+ }else if (remain < charger_remain_time){
|
|
|
+ charger_remain_time = remain;
|
|
|
+ }
|
|
|
+ if (_soc.capacity == 100) {
|
|
|
+ charger_remain_time = 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+uint32_t soc_get_cycle(void){
|
|
|
+ return _soc.total_coulomb/MAX_HA;
|
|
|
+}
|
|
|
+
|
|
|
+uint32_t soc_get_charger_remain_time(void){
|
|
|
+ return charger_remain_time;
|
|
|
+}
|
|
|
+
|
|
|
void soc_update(void){
|
|
|
- if (!charing && bms_state_get()->charging){
|
|
|
+ if (!chargering && bms_state_get()->charging){
|
|
|
+ _soc.pre_charger_coulomb = _soc.charger_coulomb;
|
|
|
_soc.charger_coulomb = 0;//clear charing
|
|
|
- charing = 1;
|
|
|
- }else if (charing && !bms_state_get()->charging){
|
|
|
- charing = 0;
|
|
|
+ _soc.total_coulomb += _soc.pre_charger_coulomb / 3600.0f;
|
|
|
+ chargering = 1;
|
|
|
+ }else if (chargering && !bms_state_get()->charging){
|
|
|
+ _soc.pre_discharger_coulomb = _soc.dischrger_coulomb;
|
|
|
_soc.dischrger_coulomb = 0; //clear discharger
|
|
|
+ _soc.total_coulomb += _soc.pre_discharger_coulomb / 3600.0f;
|
|
|
+ chargering = 0;
|
|
|
}
|
|
|
float current = measure_value()->load_current / 1000.0f; //A
|
|
|
float delta_q = current * _delta_time();
|
|
|
- if (charing){
|
|
|
+ if (chargering){
|
|
|
delta_q = delta_q * _charger_coefficient;
|
|
|
_soc.charger_coulomb += abs(delta_q);
|
|
|
}else {
|
|
|
@@ -84,9 +148,29 @@ void soc_update(void){
|
|
|
}
|
|
|
uint8_t old_cap = _soc.capacity;
|
|
|
_soc.capacity = (_soc.coulomb_now - _soc.coulomb_min)/(_soc.coulomb_max - _soc.coulomb_min) * 100;
|
|
|
+ if (chargering && (_soc.capacity == 100)){
|
|
|
+ _soc.capacity = 99;//充电的时候必须通过ovc才能把电量校准到100
|
|
|
+ }else if (!chargering && (_soc.capacity == 0)){
|
|
|
+ _soc.capacity = 1;
|
|
|
+ }
|
|
|
+ //通过电压校准SOC,只能在电压范围的两端校准
|
|
|
+ soc_update_by_ocv();
|
|
|
+
|
|
|
+ //如果没有校准过,充电过程中,电量100%后,设置校准标志位
|
|
|
+ if (chargering && (_soc.flags & SOC_FLAG_CALIBRATED) == 0){
|
|
|
+ if (_soc.capacity == 100){
|
|
|
+ _soc.coulomb_now = _soc.coulomb_max;
|
|
|
+ _soc.flags |= SOC_FLAG_CALIBRATED;
|
|
|
+ nv_save_soc();
|
|
|
+ soc_warning("calibrate OK, charging coulomb: %f\n", _soc.charger_coulomb);
|
|
|
+ }
|
|
|
+ }
|
|
|
if (old_cap != _soc.capacity) {
|
|
|
nv_save_soc();
|
|
|
}
|
|
|
+
|
|
|
+ soc_update_charger_remain_time();
|
|
|
+
|
|
|
}
|
|
|
|
|
|
soc_t *get_soc(void){
|