|
|
@@ -29,7 +29,7 @@ static void _temperature_notify(void);
|
|
|
static u32 _bms_main_task_handler(void);
|
|
|
static void _debug_timer_handler(shark_timer_t *t);
|
|
|
static void _process_power_down(void);
|
|
|
-static uint8_t calc_cell_voltage(void);
|
|
|
+static void calc_cell_voltage(void);
|
|
|
static int _can_close_mos_no_hall(void);
|
|
|
|
|
|
static bms_state_t _bms_state;
|
|
|
@@ -413,7 +413,8 @@ static void _process_deepsleep(s32 health){
|
|
|
if (!bms_work_is_normal()){
|
|
|
return; //测试模式下不休眠
|
|
|
}
|
|
|
- if (ml5238_is_charging() || ml5238_is_discharging() || io_state()->charger_detect_irq || _bms_state.charging){
|
|
|
+ if (ml5238_is_charging() || ml5238_is_discharging() || io_state()->charger_detect_irq || _bms_state.charging ||
|
|
|
+ _bms_state.pack_balancing){
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
@@ -630,48 +631,148 @@ static void _current_notify(void){
|
|
|
* 木桶效应,目标是电压最高的那个cell,尽量压制,不让电压再升高,或者升高的尽量慢一些
|
|
|
*/
|
|
|
static void _balance_timer_handler(shark_timer_t *t);
|
|
|
-
|
|
|
static shark_timer_t _balance_timer = {.handler = _balance_timer_handler};
|
|
|
+static void _start_balance(uint16_t mask) {
|
|
|
+ int success = ml5238_cell_start_balance(mask);
|
|
|
+ if (success ) {
|
|
|
+ if (mask == 0) {
|
|
|
+ _bms_state.pack_balancing = 0;
|
|
|
+ }else {
|
|
|
+ _bms_state.pack_balancing = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
-static debounce_t _cell_balance = {.count = 0, .max_count = 120, .init_count = 0};
|
|
|
+static void _stop_balance(void) {
|
|
|
+ _start_balance(0);
|
|
|
+}
|
|
|
|
|
|
static void _balance_timer_handler(shark_timer_t *t){
|
|
|
- ml5238_cell_start_balance(0);
|
|
|
- _bms_state.pack_balancing = 0;
|
|
|
- debounce_reset(_cell_balance);
|
|
|
+ _stop_balance();
|
|
|
+ if (_bms_state.pack_balancing) {
|
|
|
+ shark_timer_post(&_balance_timer, 1);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-static uint32_t get_balance_mask(uint8_t current_max_index){
|
|
|
- return BIT(current_max_index);
|
|
|
-}
|
|
|
|
|
|
-static void check_cell_balance(uint8_t current_max_index){
|
|
|
- if (!_bms_state.charging || (_bms_state.cell_max_vol >= SIGLE_CELL_MAX_CHARGER_VOLTAGE) || !bms_work_is_normal()){ //not charging, need not do balance
|
|
|
- if (_bms_state.pack_balancing){
|
|
|
- debounce_reset(_cell_balance);
|
|
|
- _bms_state.pack_balancing = ml5238_cell_start_balance(0);
|
|
|
- shark_timer_cancel(&_balance_timer);
|
|
|
+static u16 _search_direct(u16 *delta_v, u8 current_cell, u8 *depth, u8 dir) {
|
|
|
+ u16 delta_next = 0;
|
|
|
+ u16 delta_prev = 0;
|
|
|
+ u8 idx_prev = 255;
|
|
|
+ u8 idx_next = 255;
|
|
|
+ u8 balance_idx = 255;
|
|
|
+ for (int i = 0; i < CELLS_NUM/2 + 1 ; i++) {
|
|
|
+ *depth ++;
|
|
|
+ //get the delta v of the prev and current
|
|
|
+ if (current_cell == 0) {
|
|
|
+ delta_prev = delta_v[CELLS_NUM - 1];
|
|
|
+ idx_prev = CELLS_NUM - 1;
|
|
|
+ }else {
|
|
|
+ delta_prev = delta_v[current_cell - 1];
|
|
|
+ idx_prev = current_cell - 1;
|
|
|
+ }
|
|
|
+ //get the delta v of the next and current
|
|
|
+ if (current_cell == CELLS_NUM - 1) {
|
|
|
+ delta_next = delta_v[0];
|
|
|
+ idx_next = 0;
|
|
|
+ }else {
|
|
|
+ delta_next = delta_v[current_cell + 1];
|
|
|
+ idx_next = current_cell + 1;
|
|
|
+ }
|
|
|
+ //use the max delta v of the prev and next
|
|
|
+ if (delta_prev >= delta_next) {
|
|
|
+ if(delta_prev >= MAX_DIFF_BETWEEN_MIN_MAX_CELL){
|
|
|
+ balance_idx = idx_prev; //balance with prev cell
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }else {
|
|
|
+ if(delta_next >= MAX_DIFF_BETWEEN_MIN_MAX_CELL){
|
|
|
+ balance_idx = idx_next; //balance with next cell
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (dir == 1) {//search forword
|
|
|
+ current_cell = (current_cell + 1) % CELLS_NUM;
|
|
|
+ }else { //search backwork
|
|
|
+ if (current_cell == 0) {
|
|
|
+ current_cell = CELLS_NUM - 1;
|
|
|
+ }else {
|
|
|
+ current_cell -= 1;
|
|
|
+ }
|
|
|
}
|
|
|
- return;
|
|
|
- }
|
|
|
- if ((!_bms_state.pack_balancing && _bms_state.cell_max_vol < MAX_CELL_VOLTAGE_FOR_BALACNE) || _bms_state.pack_balancing){
|
|
|
- debounce_reset(_cell_balance);
|
|
|
- return;
|
|
|
}
|
|
|
- if (_bms_state.cell_max_vol >= MAX_CELL_VOLTAGE_FOR_BALACNE){
|
|
|
- debounce_inc(_cell_balance);
|
|
|
+ return balance_idx;
|
|
|
+}
|
|
|
+static u32 get_balance_maskV2(void) {
|
|
|
+ u16 delta_v[CELLS_NUM];
|
|
|
+ u16 *pcellv = measure_value()->cell_vol;
|
|
|
+
|
|
|
+ //calc the delta v of the Neighboring cells
|
|
|
+ delta_v[CELLS_NUM - 1] = abs(pcellv[CELLS_NUM-1] - pcellv[0]);
|
|
|
+ for (int i = 0; i < CELLS_NUM - 1; i++) {
|
|
|
+ delta_v[i] = pcellv[i] - pcellv[i + 1];
|
|
|
+ }
|
|
|
+ u8 depth_next, depth_prev;
|
|
|
+ u8 idx_next = _search_direct(delta_v, _bms_state.cell_index_of_max_vol, &depth_next, 1);// search from max to next....
|
|
|
+ u8 idx_prev = _search_direct(delta_v, _bms_state.cell_index_of_max_vol, &depth_next, 0);// search from max to prev
|
|
|
+ //chose the min depth whitch near from max voltage cell
|
|
|
+ if (depth_next < depth_prev) {
|
|
|
+ return BIT(idx_next);
|
|
|
+ }else if (depth_prev < depth_next) {
|
|
|
+ return BIT(idx_prev);
|
|
|
}else {
|
|
|
- debounce_reset(_cell_balance);
|
|
|
+ if (idx_next < CELLS_NUM) {
|
|
|
+ return BIT(idx_next);
|
|
|
+ }
|
|
|
+ if (idx_prev < CELLS_NUM) {
|
|
|
+ return BIT(idx_prev);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+#define BALANCE_TIME (10 * 60) //S
|
|
|
+static u8 g_is_charging = 0;
|
|
|
+static u8 can_do_balance(void) {
|
|
|
+ u8 balance = 0;
|
|
|
+ //when stop normal(not energy recovery) charging, need check balance
|
|
|
+ if (g_is_charging && (!_bms_state.charging && soc_is_normal_charging())) {
|
|
|
+ balance = 1;
|
|
|
+ }
|
|
|
+ g_is_charging = _bms_state.charging;
|
|
|
+ //if already balancing, do nothing
|
|
|
+ if (_bms_state.pack_balancing) {
|
|
|
+ balance = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return balance;
|
|
|
+}
|
|
|
+
|
|
|
+static u8 need_stop_balance(void) {
|
|
|
+ if (measure_value()->load_current < -50.0 || g_is_charging) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void check_cell_balance(void){
|
|
|
+ if (!can_do_balance()) {
|
|
|
+ if (need_stop_balance()) {
|
|
|
+ if (_bms_state.pack_balancing){
|
|
|
+ _stop_balance();
|
|
|
+ shark_timer_cancel(&_balance_timer);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return;
|
|
|
}
|
|
|
- if (!_bms_state.pack_balancing && debounce_reach_max(_cell_balance)){
|
|
|
- _bms_state.pack_balancing = 1;
|
|
|
- ml5238_cell_start_balance(get_balance_mask(current_max_index));
|
|
|
- shark_timer_post(&_balance_timer, 5 * 1000); //stop balance after 30s
|
|
|
- debounce_reset(_cell_balance);
|
|
|
+ u16 mask = get_balance_maskV2();
|
|
|
+ if (mask) {
|
|
|
+ _start_balance(mask);
|
|
|
+ shark_timer_post(&_balance_timer, BALANCE_TIME * 1000); //stop balance after BALANCE_TIME
|
|
|
}
|
|
|
}
|
|
|
#endif
|
|
|
-static uint8_t calc_cell_voltage(void){
|
|
|
+static void calc_cell_voltage(void){
|
|
|
uint16_t voltage = 0;
|
|
|
uint16_t max_cell = 0;
|
|
|
uint16_t min_cell = 0xf000;
|
|
|
@@ -693,14 +794,13 @@ static uint8_t calc_cell_voltage(void){
|
|
|
_bms_state.cell_min_vol = min_cell;
|
|
|
_bms_state.cell_index_of_min_vol = min_index;
|
|
|
_bms_state.cell_index_of_max_vol = max_index;
|
|
|
- return max_index;
|
|
|
}
|
|
|
|
|
|
static void _voltage_notify(void){
|
|
|
- uint8_t max_index = calc_cell_voltage();
|
|
|
+ calc_cell_voltage();
|
|
|
check_voltage_state(); //check health of cell voltage
|
|
|
#if (ALLOW_5238_BALANCE==1)
|
|
|
- check_cell_balance(max_index);
|
|
|
+ check_cell_balance();
|
|
|
#endif
|
|
|
}
|
|
|
|