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

add uart timeout && charger remain time

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

+ 2 - 1
Application/app/bms_message.c

@@ -59,6 +59,7 @@ void process_bms_message(can_frame_t *frame, int len){
 					bresp.max_temp = measure_value()->pack_temp[i];
 				}
 			}
+			bresp.cycle = soc_get_cycle();
 			data = (uint8_t *)&bresp;
 			data_len = sizeof(bresp);			
 			break;
@@ -66,7 +67,7 @@ void process_bms_message(can_frame_t *frame, int len){
 		case CAN_KEY_BMS_CHARG_INFO:{
 			cinfo_cmd_resp_t cresp;
 			cresp.charge_current = measure_value()->load_current;
-			cresp.charge_remain_time = 0;
+			cresp.charge_remain_time = soc_get_charger_remain_time();
 			data = (uint8_t *)&cresp;
 			data_len = sizeof(cresp);			
 			break;

+ 1 - 0
Application/app/protocol.h

@@ -75,6 +75,7 @@ typedef struct {
 	uint8_t  capacity;
 	uint32_t energy;   //能量,给PS100/200/310/360计算续航里程用
 	int8_t  max_temp;//最高的那个温度
+	uint32_t cycle; //充放电循环次数
 }binfo_cmd_resp_t;
 #pragma pack(pop)
 

+ 92 - 8
Application/app/sox/soc.c

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

+ 12 - 0
Application/app/sox/soc.h

@@ -1,7 +1,11 @@
 #pragma once
 #include "libs/shark_libs.h"
 
+#define MAX_HA (30.0f)
+
+#define SOC_FLAG_CALIBRATED 1 //已经校准
 typedef struct {
+	uint8_t flags; //比如是否校准等
 	float coulomb_now; /*AH, 若导线中载有1安培的稳定电流,则在1秒内通过导线横截面积的电量为1库仑 */
 	uint8_t capacity;  /* 电池的容量百分比 */
 	float coulomb_min;
@@ -10,8 +14,16 @@ typedef struct {
 	float energy; //当前的能量(wh)
 	float charger_coulomb; //本次充电的AH
 	float dischrger_coulomb; //本次放电的AH
+
+	float pre_charger_coulomb;
+	float pre_discharger_coulomb;
+
+	uint32_t total_coulomb;
 }soc_t;
 
 void soc_init(void);
 void soc_update(void);
+void soc_update_by_ocv(void);
+uint32_t soc_get_cycle(void);
+uint32_t soc_get_charger_remain_time(void);
 soc_t *get_soc(void);

+ 4 - 2
Application/app/sox/state.c

@@ -154,6 +154,8 @@ static void _process_power_down(void){
 	if (bms_health()->powerdown_lower_voltage){
 		state_debug("BMS System PowerDown!!\n");
 
+		soc_update_by_ocv();
+		
 		nv_save_soc();
 		
 		ml5238_enable_charger_detect(AUX_VOL_IS_OPEN(), 1);
@@ -206,9 +208,9 @@ static void _process_deepsleep(s32 health){
 		return;
 	}
 
-	/*if (ºìÍâ»òÕß485ͨÐÅûÓг¬Ê±){
+	if (!shark_uart_timeout()){
 		return;
-	}*/
+	}
 
 	if (io_state()->aux_lock_detect){
 		return;

+ 10 - 0
Application/bsp/uart.c

@@ -46,6 +46,7 @@ static shark_uart_t _shark_uart[SHARK_UART_COUNT];
 static shark_task_t _uart_task;
 static bool new_prococol = false;
 static u64 _rx_time;
+static bool uart_no_data = false;
 #define update_dma_w_pos(uart) circle_update_write_position(&uart->rx_queue, SHARK_UART_RX_MEM_SIZE - DMA_CHCNT(uart->rx_dma_ch))
 extern void protocol_recv_frame(uart_enum_t uart_no, char *data, int len);
 extern void protocol_notify_old_frame(uart_enum_t uart_no);
@@ -76,6 +77,11 @@ static void shark_uart_rx(shark_uart_t *uart){
 					_rx_time = 0xFFFFFFFFFFFFL;
 					protocol_notify_old_frame(_uart_index(uart->uart_com));
 				}
+			}else if (shark_get_mseconds() >= (2000 + _rx_time)){
+				uart_no_data = true;
+
+			}else {
+				uart_no_data = false;
 			}
 			break;
 		}
@@ -324,9 +330,13 @@ void shark_uart_deinit(uart_enum_t uart_no){
 		UART1_IR_EN(0);
 	}
 	new_prococol = false;
+	uart_no_data = true;
 }
 
 
+bool shark_uart_timeout(void){
+	return uart_no_data;
+}
 void shark_uart_init(uart_enum_t uart_no)
 {
 	shark_uart_t *uart = _shark_uart + uart_no;

+ 1 - 0
Application/bsp/uart.h

@@ -45,6 +45,7 @@ void shark_uart_frame_continue(uart_enum_t uart_no, uint8_t *bytes, int len);
 void shark_uart_frame_end(uart_enum_t uart_no);
 void shark_uart_write_bytes(uart_enum_t uart_no, u8 *buff, u16 size);
 void shark_uart_flush(void);
+bool shark_uart_timeout(void);