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

Merge remote-tracking branch 'origin/fast_discharger' into dev

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

+ 61 - 37
Application/app/bms_message.c

@@ -32,15 +32,62 @@ void bms_message_update_insert(int is_hall_detect){
 	}
 }
 
+static void response_base_info(can_frame_t *frame) {
+	uint8_t *data = NULL;
+	int data_len = 0;	
+	binfo_cmd_resp_t bresp;
+	bresp.capacity = get_soc()->capacity;
+	if (get_soc()->coulomb_now >= get_soc()->coulomb_min) {
+		bresp.energy = get_soc()->coulomb_now - get_soc()->coulomb_min;
+	}else{
+		bresp.energy = 0;
+	}
+	bresp.pack_current = measure_value()->load_current;
+	bresp.pack_voltage = bms_state_get()->pack_voltage;
+	bresp.max_temp = -100;
+	for (int i = 0; i < PACK_TEMPS_NUM; i ++){
+		if (bresp.max_temp < measure_value()->pack_temp[i]){
+			bresp.max_temp = measure_value()->pack_temp[i];
+		}
+	}
+	bresp.health = bms_health()->i_status;
+	if (bms_is_ps_charger_in()) {/*如果在底座或者车上(有充电器),提前置位过高/低温充电标志*/
+		bresp.health |= (bms_health()->lower_temp_deny_charger << 12 | bms_health()->over_temp_deny_charger << 14);
+	}
+	bresp.health &= ~(1 << 8);
+	bresp.health |= ((get_soc()->flags & SOC_FLAG_CALIBRATED) != 0) << 8;
+	stat_cmd_resp_t sresp;
+	sresp.insert = bms_insert;
+	sresp.is_charging = bms_state_get()->charging;
+	sresp.discharger_fet = ml5238_is_discharging();
+	sresp.charger_fet = ml5238_is_charging();
+	sresp.small_power = AUX_VOL_IS_OPEN();
+	sresp.is_balancing = bms_state_get()->pack_balancing;
+	sresp.health = (((uint16_t )(bms_health()->i_status)) != 0);
+	sresp.is_charger_in = io_state()->charger_detect_irq;
+	bresp.state = *((uint8_t*)&sresp);
+	data = (uint8_t *)&bresp;
+	data_len = sizeof(bresp);
+	if (frame->key == CAN_KEY_BMS_SET_POWER) {
+		u8 response[sizeof(bresp) + 1];
+		response[0] = 0;
+		memcpy(response + 1, data, data_len);
+		data = response;
+		data_len += 1;
+	}
+	protocol_send_bms_info(frame->head.can_addr, frame->key, data, data_len);
+}
+
 void process_bms_message(can_frame_t *frame, int len){
 	int result = 0;
 	uint8_t *data = NULL;
 	int data_len = 0;
 	// set_log_all(L_debug);
 	switch(frame->key) {
-		case CAN_KEY_BMS_SET_POWER:
+		case CAN_KEY_BMS_SET_POWER: 
 			if (len != sizeof(pwr_cmd_t) || frame->head.can_addr != 0x42){//开关大电必须42发过来
 				result = 1;
+				protocol_send_ack(frame->head.can_addr, frame->key, result);
 			}else {
 				pwr_cmd_t *cmd = (pwr_cmd_t *)frame->data;
 				uint32_t user_request = USER_REQUEST_PENDING;
@@ -66,49 +113,15 @@ void process_bms_message(can_frame_t *frame, int len){
 					}
 				}
 				bms_state_get()->user_request = user_request;
+				response_base_info(frame);
 			}
-			protocol_send_ack(frame->head.can_addr, frame->key, result);
 			break;
 		case CAN_KEY_BMS_BASE_INFO:{
 			if (len >= 1) {
 				uint8_t env = frame->data[0];
 				bms_set_ps_charger_in(1, (env == CW_CHE_SHANG_CHARGER || env == CW_CHONG_DIAN_ZUO));
 			}
-
-			binfo_cmd_resp_t bresp;
-			bresp.capacity = get_soc()->capacity;
-			if (get_soc()->coulomb_now >= get_soc()->coulomb_min) {
-				bresp.energy = get_soc()->coulomb_now - get_soc()->coulomb_min;
-			}else{
-				bresp.energy = 0;
-			}
-			bresp.pack_current = measure_value()->load_current;
-			bresp.pack_voltage = bms_state_get()->pack_voltage;
-			bresp.max_temp = -100;
-			for (int i = 0; i < PACK_TEMPS_NUM; i ++){
-				if (bresp.max_temp < measure_value()->pack_temp[i]){
-					bresp.max_temp = measure_value()->pack_temp[i];
-				}
-			}
-			bresp.health = bms_health()->i_status;
-			if (bms_is_ps_charger_in()) {/*如果在底座或者车上(有充电器),提前置位过高/低温充电标志*/
-				bresp.health |= (bms_health()->lower_temp_deny_charger << 12 | bms_health()->over_temp_deny_charger << 14);
-			}
-			bresp.health &= ~(1 << 8);
-			bresp.health |= ((get_soc()->flags & SOC_FLAG_CALIBRATED) != 0) << 8;
-			stat_cmd_resp_t sresp;
-			sresp.insert = bms_insert;
-			sresp.is_charging = bms_state_get()->charging;
-			sresp.discharger_fet = ml5238_is_discharging();
-			sresp.charger_fet = ml5238_is_charging();
-			sresp.small_power = AUX_VOL_IS_OPEN();
-			sresp.is_balancing = bms_state_get()->pack_balancing;
-			sresp.health = (((uint16_t )(bms_health()->i_status)) != 0);
-			sresp.is_charger_in = io_state()->charger_detect_irq;
-			bresp.state = *((uint8_t*)&sresp);
-			data = (uint8_t *)&bresp;
-			data_len = sizeof(bresp);
-			protocol_send_bms_info(frame->head.can_addr, frame->key, data, data_len);
+			response_base_info(frame);
 			break;
 		}
 		case CAN_KEY_BMS_CHARG_INFO:{
@@ -276,6 +289,17 @@ void process_bms_message(can_frame_t *frame, int len){
 			protocol_send_bms_info(frame->head.can_addr, frame->key, event, sizeof(event_record_t) * num + 1);
 			break;
 		}
+		case CAN_KEY_POWERDOWN: {
+			if (len < 4) {
+				return;
+			}
+			/*magic 0xFF005AA5*/
+			if (frame->data[0] == 0xA5 && frame->data[1] == 0x5A && frame->data[2] == 0x00 && frame->data[3] == 0xFF) {
+				bms_work_mode_set(WORK_MODE_PCBA_TEST, 1);
+				system_power_down();
+			}
+			break;
+		}
 		default:
 			break;
 	}

+ 2 - 1
Application/app/event_record.h

@@ -25,7 +25,8 @@ typedef enum {
 	Cell_Under_Vol2,    //19
 	Cell_Over_Vol2,     //20
 	Min_Cap_For_DisCharger2,
-	Cell_balance,
+	Charger_no_full_capaticy,
+	Charger_no_full_ceof,
 }event_id_t;
 
 typedef struct {

+ 1 - 0
Application/app/protocol.h

@@ -163,6 +163,7 @@ typedef struct {
 
 #define CAN_KEY_GET_EVENT 0xac /*»ñȡʼþÐÅÏ¢*/
 
+#define CAN_KEY_POWERDOWN 0xad /* power down, magic:0xFF005AA5*/
 
 #define CAN_KEY_IAP_ENTER   0xF0
 #define CAN_KEY_IAP_BEGIN   0xF1

+ 1 - 1
Application/app/sox/health.c

@@ -44,7 +44,7 @@ static float min_discharger_cell_recovery_vol[] = {1900, 2300};//
 static float min_discharger_pdown_vol[] = {26000, 30000}; //power down的最小电压
 static float min_discharger_pdown_cell_vol[] = {1600, 1800}; //power down的最小电芯电压
 
-#define MAX_TRY_FOR_AUX_SHORT 10
+#define MAX_TRY_FOR_AUX_SHORT 20
 
 /* health 模块,只检测状态,不做任何控制,如果有异常情况,控制中心会统一处理  */
 static void check_ml5238_state(int event);

+ 73 - 37
Application/app/sox/soc.c

@@ -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	

+ 2 - 2
Application/app/sox/soc.h

@@ -2,7 +2,7 @@
 #include "libs/shark_libs.h"
 #include "bsp/shark_bsp.h"
 
-#define SOC_CURRENT_VERSION 0
+#define SOC_CURRENT_VERSION 1
 #define SOC_FLAG_VERSON_MASK (0x0E)
 #define SOC_FLAG_CALIBRATED (0x1 << 0) //已经校准
 #define SOC_FLAG_VERSION(v) (((v)<<1)& SOC_FLAG_VERSON_MASK)
@@ -14,7 +14,7 @@ typedef struct {
 	double coulomb_min;
 	double coulomb_max;
 	double charger_cmin; //充电计算的最小容量
-	double energy; //当前的能量(wh)
+	double current_real_coulomb; //当前的能量(wh)
 	double charger_coulomb; //本次充电的AH
 	double dischrger_coulomb; //本次放电的AH
 

+ 1 - 1
Application/app/sox/state.c

@@ -283,7 +283,7 @@ static s32 _process_unheath(void){
 		}
 		unhealth |= (Health_Discharger_Failt | Health_Fault_Can_Sleep);		
 	}
-	if (io_state()->aux_lock_detect || bms_health()->small_current_short) {
+	if (bms_health()->small_current_real_short) {
 		unhealth |= Health_aux_Fault;
 		if (bms_health()->small_current_real_short) {
 			unhealth |= Health_Discharger_Failt;