Просмотр исходного кода

process unhealth, power down

Signed-off-by: huhui <huhui@sharkgulf.com>
huhui 5 лет назад
Родитель
Сommit
3eda0b3776

+ 0 - 1
Application/app/sox/health.h

@@ -16,7 +16,6 @@ typedef struct {
 	uint32_t powerdown_lower_voltage:1;
 	uint32_t sigle_cell_lower_voltage:1;
 	uint32_t sigle_cell_over_voltage:1;
-	uint32_t small_current_short:1; //小电短路保护
 	uint32_t load_current_short:1; //大电短路保护
 }bms_health_t;
 

+ 92 - 14
Application/app/sox/state.c

@@ -8,29 +8,100 @@
 #include "iostate.h"
 
 static bms_state_t _bms_state;
+static shark_task_t _bms_main_task;
 static void _current_notify(void);
 static void _voltage_notify(void);
 static void _temperature_notify(void);
+static u32 _bms_main_task_handler(void);
 
 void bms_state_init(void){
 	_bms_state.cell_index_of_max_vol = 0xff;
+	_bms_main_task.handler = _bms_main_task_handler;
 	measure_task_init(_current_notify, _voltage_notify, _temperature_notify);
 	io_state_init();
 	health_init();
+	shark_task_add(&_bms_main_task);
 }
 
 bms_state_t *bms_state_get(void){
 	return &_bms_state;
 }
 
-static debounce_t _charging_detect = {.count = 0, .max_count = 10};
-static void check_charging(){
-	if (bms_health()->charger_over_current || bms_health()->load_current_short) {
+#define Health_Success 0
+#define Health_Discharger_Failt 1
+#define Health_charger_Fault 2
+#define Health_aux_Fault 4
+
+static s32 _process_unheath(void){
+	if (bms_health()->load_current_short) {//短路检测后,关闭充放电mos
 		ml5238_enable_discharger_mosfet(0);
 		ml5238_enable_charger_mosfet(0); //disable charger mosfet
 		_bms_state.charging = 0;
-		return;
-	}	
+		_bms_state.discharging = 0;
+		return (Health_Discharger_Failt | Health_charger_Fault);
+	}
+
+	if (bms_health()->charger_over_current || bms_health()->charger_over_temp || bms_health()->charger_lower_temp){
+		ml5238_enable_charger_mosfet(0); //disable charger mosfet
+		_bms_state.charging = 0;
+		return Health_charger_Fault;
+	}
+
+	if (bms_health()->discharger_over_temp || bms_health()->discharger_lower_temp || bms_health()->discharger_lower_voltage){
+		ml5238_enable_discharger_mosfet(0); //disable charger mosfet
+		_bms_state.discharging = 0;
+		return Health_Discharger_Failt;
+	}
+
+	if (io_state()->aux_lock_detect && AUX_VOL_IS_OPEN()) {
+		AUX_VOL_OPEN(0);
+		return Health_aux_Fault;
+	}
+	return Health_Success;
+}
+
+
+//处理PS100/310/320/360,充电底座,充电柜的指令或者bms自己发给自己的指令
+static void _process_user_request(s32 health){
+	if (_bms_state.user_request & USER_REQUEST_PENDING){
+		if ((health & Health_charger_Fault) == 0){
+			ml5238_enable_charger_mosfet(!!(_bms_state.user_request & USER_REQUEST_CHARGER));
+		}
+		if ((health & Health_Discharger_Failt) == 0){
+			ml5238_enable_discharger_mosfet(!!(_bms_state.user_request & USER_REQUEST_DISCHARGER));
+		}
+		if ((health & Health_aux_Fault) == 0){
+			AUX_VOL_OPEN(!!(_bms_state.user_request & USER_REQUEST_SMALLCURRENT));
+		}	
+		_bms_state.user_request = 0;//clear user request
+	}
+}
+
+static void _process_power_down(void){
+	if (bms_health()->powerdown_lower_voltage){
+		ml5238_enable_charger_detect(1);
+		delay_us(2* 1000);
+		if (!ml5238_charger_is_disconnect()){//have charger, do'nt power down
+			bms_health()->powerdown_lower_voltage = 0;
+			return;
+		}
+		AUX_VOL_OPEN(0);
+		CS1180_PWR_ENABLE(0);
+		ml5238_enable_discharger_mosfet(0);
+		ml5238_enable_charger_mosfet(0);		
+		ml5238_power_down();
+	}
+}
+
+static u32 _bms_main_task_handler(void){
+	s32 unhealth = _process_unheath();
+	_process_user_request(unhealth);
+	_process_power_down();
+	return 0;
+}
+
+static debounce_t _charging_detect = {.count = 0, .max_count = 10};
+static void check_charging(){
 	if (!_bms_state.charging) {
 		if (measure_value()->load_current >= MIN_START_CHARGER_CURRENT) {
 			debounce_inc(_charging_detect);
@@ -62,12 +133,12 @@ static void _current_notify(void){
 	check_charging();
 }
 
-/* 充电电流小于一定值,认为充满的时候,需要检查电芯的电压,如果发现有电芯电压过高,需要开启被动均衡 
+/* 需要检查电芯的电压,如果发现有电芯电压过高,需要开启被动均衡 
  * 充电过程中考虑balance,主要是希望cell 电压扩散后,保证1. 单电芯不能过压, 2. 单电芯不能比平均电压过低,导致
  * 木桶效应,目标是电压最高的那个cell,尽量压制,不让电压再升高,或者升高的尽量慢一些
 */
 static debounce_t _cell_balance = {.count = 10, .max_count = 20};
-static void check_cell_balance(void){
+static void check_cell_balance(uint8_t current_max_index){
 	if (!_bms_state.charging){ //not charging, need not do balance
 		if (_bms_state.pack_balancing){
 			_bms_state.pack_balancing = 0;
@@ -76,7 +147,9 @@ static void check_cell_balance(void){
 		}
 		return;
 	}
-
+	if (!_bms_state.pack_balancing && _bms_state.cell_min_vol < CELL_FUSION_VOLTAGE){
+		return;
+	}
 	if (_bms_state.cell_max_vol - _bms_state.cell_min_vol >= MAX_DIFF_BETWEEN_MIN_MAX_CELL){
 		debounce_inc(_cell_balance);
 	}else {
@@ -88,9 +161,13 @@ static void check_cell_balance(void){
 		_bms_state.pack_balancing = 0;
 		ml5238_cell_start_balance(0);
 	}
+	if (_bms_state.pack_balancing && (current_max_index != _bms_state.cell_index_of_max_vol)){
+		ml5238_cell_start_balance(BIT(current_max_index));
+	}
+	_bms_state.cell_index_of_max_vol = current_max_index;	
 }
 
-static void _voltage_notify(void){
+static uint8_t calc_cell_voltage(void){
 	uint16_t voltage = 0;
 	uint16_t max_cell = 0;
 	uint16_t min_cell = 0xf000;
@@ -108,12 +185,13 @@ static void _voltage_notify(void){
 	_bms_state.pack_voltage = voltage;
 	_bms_state.cell_max_vol = max_cell;
 	_bms_state.cell_min_vol = min_cell;	
+	return max_index;
+}
+
+static void _voltage_notify(void){
+	uint8_t max_index = calc_cell_voltage();
 	check_voltage_state(); //check health of cell voltage
-	check_cell_balance();
-	if (_bms_state.pack_balancing && (max_index != _bms_state.cell_index_of_max_vol)){
-		ml5238_cell_start_balance(BIT(max_index));
-	}
-	_bms_state.cell_index_of_max_vol = max_index;
+	check_cell_balance(max_index);
 }
 
 static void _temperature_notify(void){

+ 2 - 0
Application/app/sox/state.h

@@ -18,6 +18,7 @@
 #define MIN_START_LOADING_CURRENT 2  //ma, 如果有反向小于 MIN_START_LOADING_CURRENT的电流,认为在放电
 #define MAX_DIFF_BETWEEN_MIN_MAX_CELL 150 //0.15v ,压差超过这个值,开始balance
 #define MIN_DIFF_BETWEEN_MIN_MAX_CELL 050 //0.05v, 牙差低于这个数据,停止balance
+#define CELL_FUSION_VOLTAGE      3500 //LFP电池在3.5v的时候,开始发散,需要判断是否要balance
 typedef struct{
 	uint16_t discharging :1;
 	uint16_t charging: 1;
@@ -30,6 +31,7 @@ typedef struct{
 	int      user_request;
 }bms_state_t;
 
+#define USER_REQUEST_PENDING BIT(31) //是否有用户请求
 #define USER_REQUEST_CHARGER BIT(0)
 #define USER_REQUEST_DISCHARGER BIT(1)
 #define USER_REQUEST_SMALLCURRENT BIT(2)

+ 1 - 0
Application/bsp/gpio.h

@@ -10,6 +10,7 @@ void gpio_init(void);
 #define TEMP_OPEN(x) gpio_bit_write(GPIOF,GPIO_PIN_1,(bit_status)(x))
 /*switch for small current aux */
 #define AUX_VOL_OPEN(x) gpio_bit_write(GPIOB,GPIO_PIN_2,(bit_status)(x))
+#define AUX_VOL_IS_OPEN() !!gpio_output_bit_get(GPIOB, GPIO_PIN_2)
 /*aux pwr is locked */
 #define IS_AUX_VOL_LOCKED() gpio_input_bit_get(GPIOB, GPIO_PIN_11)
 /*switch for larger current DCDC  */

+ 14 - 2
Application/bsp/ml5238.c

@@ -24,10 +24,15 @@ void ml5238_register_notify_handler(ml5238_notify_hander handler){
 
 
 //used to detect charger over current
-int ml5238_charger_is_open(void){
+int ml5238_charger_is_disconnect(void){
 	uint8_t value = 0;
+	uint8_t fet = 0;
+	ml5238_read(ML5238_FET, &fet);	
 	ml5238_read(ML5238_PSENSE, &value);
-	return !(value & PSENSE_PSL);
+	if (fet & FET_DF){
+		return (value & PSENSE_PSH);
+	}
+	return (value & PSENSE_PSL);
 }
 
 int ml5238_enable_load_detect(int enable){
@@ -194,6 +199,13 @@ void ml5238_softreset(void)
 	}
 }
 
+void ml5238_power_down(void){
+	do {
+		ml5238_write(ML5238_PSENSE, PSENSE_EPSH|PSENSE_IPSH); //before power down, we must enable charger detect
+		ml5238_write(ML5238_POWER, POWER_PDWN);
+	}while(1);
+}
+
 static void __inline__ call_handler(int event){
 	if (_handler) {
 		_handler(event);

+ 4 - 0
Application/bsp/ml5238.h

@@ -9,6 +9,10 @@ int ml5238_short_current_detect(int mode);
 int ml5238_is_load_disconnect(void);
 int ml5238_enable_load_detect(int enable);
 void ml5238_cell_start_balance(uint16_t balance_mask);
+void ml5238_power_down(void);
+int ml5238_charger_is_disconnect(void);
+int ml5238_enable_charger_detect(int enable);
+
 
 typedef void (*ml5238_notify_hander)(int event);
 void ml5238_register_notify_handler(ml5238_notify_hander handler);