Parcourir la source

1. cs1180 workaround
2. for charger single cell over charger
3. add nv erase soc data
4. add get soc internal measure data
5. calc every sleep times, may be used for power comsumer

Signed-off-by: huhui <huhui@sharkgulf.com>

huhui il y a 5 ans
Parent
commit
581a8cf39a

+ 13 - 0
Application/app/bms_message.c

@@ -138,6 +138,19 @@ void process_bms_message(can_frame_t *frame, int len){
 			protocol_send_bms_info(frame->head.can_addr, frame->key, data, data_len);
 			break;
 		}
+		case CAN_KEY_GET_SOC_INFO: {
+			soc_info_t soc;
+			soc.c_min = get_soc()->coulomb_min/36.0f;
+			soc.c_max = get_soc()->coulomb_max/36.0f;
+			soc.c_now = get_soc()->coulomb_now/36.0f;
+			soc.c_discharger = get_soc()->dischrger_coulomb/36.0f;
+			soc.c_charger = get_soc()->charger_coulomb/36.0f;
+			soc.c_totol = get_soc()->total_coulomb;
+			data = (uint8_t *)&soc;
+			data_len = sizeof(soc);
+			protocol_send_bms_info(frame->head.can_addr, frame->key, data, data_len);
+			break;
+		}
 		case CAN_KEY_BMS_GET_HEALTH_STAT:
 			data = (uint8_t *)bms_health();
 			data_len = sizeof(*bms_health());

+ 9 - 0
Application/app/iap.c

@@ -1,5 +1,6 @@
 #include <string.h>
 #include "app/iap.h"
+#include "app/nv_storage.h"
 #include "bsp/fmc_flash.h"
 
 static int iap_write_image(uint8_t *data, int len);
@@ -48,6 +49,14 @@ void process_iap_message(can_frame_t *frame, int len){
 		case CAN_EEY_IAP_READ_STRING:
 			iap_read_string(frame);
 			break;
+		case CAN_KEY_REBOOT:
+			shark_timer_post(&_reboot_timer, 100);
+			protocol_send_ack(frame->head.can_addr, frame->key, 1);
+		case CAN_KET_ERASE_NV:
+			nv_erase();
+			shark_timer_post(&_reboot_timer, 100);
+			protocol_send_ack(frame->head.can_addr, frame->key, 1);
+			break;
 	}
 	if (data != NULL && data_len > 0){
 		protocol_send_bms_info(frame->head.can_addr, frame->key, frame->data, data_len);

+ 7 - 0
Application/app/nv_storage.c

@@ -17,6 +17,13 @@ void nv_save_soc(void){
 	printf("write e2rom time %lld\n", (shark_get_mseconds() - start_time));
 }
 
+void nv_erase(void){
+	uint8_t data = 0xFF;
+	for (int i = 0; i < sizeof(soc_t) + sizeof(uint16_t); i++){
+		AT24CXX_Write(SOC_ADDR + i, &data, 1);
+	}
+}
+
 int nv_restore_soc(void){
 	soc_t soc;
 	AT24CXX_Read(SOC_ADDR , (uint8_t *)&soc, sizeof(soc_t));

+ 1 - 0
Application/app/nv_storage.h

@@ -2,3 +2,4 @@
 
 extern void nv_save_soc(void);
 extern int nv_restore_soc(void);
+extern void nv_erase(void);

+ 14 - 0
Application/app/protocol.h

@@ -104,6 +104,16 @@ typedef struct {
 }cell_cmd_resp_t;
 #pragma pack(pop)
 
+#define CAN_KEY_GET_SOC_INFO 0xa7
+typedef struct {
+	int c_min;
+	int c_max;
+	int c_now;
+	int c_charger;
+	int c_discharger;
+	int   c_totol;
+}soc_info_t;
+
 #define CAN_KEY_BMS_TEMPS 0x11 //return int[4]
 
 #define CAN_KEY_SET_LOGGER  0xa2 //byte 0:modle, byte1 level
@@ -111,6 +121,7 @@ typedef struct {
 #define CAN_KEY_BMS_GET_HEALTH_STAT 0xa4 //return bms_health_t
 #define CAN_KEY_BMS_GET_TIME      0xa5 //return bms running times(second) uint32_t
 #define CAN_KEY_BMS_SET_WORK_MODE     0xa6 //byte0=mode, byte1=start/stop
+
 #define CAN_KEY_GET_VERSION 0x0c //return string
 #define CAN_KEY_SET_SN      0x06 //string
 #define CAN_KEY_GET_SN      0x05 //return string
@@ -121,6 +132,9 @@ typedef struct {
 #define CAN_KEY_IAP_WRITE   0xF4
 #define CAN_KEY_IAP_BOOT    0xF5
 #define CAN_EEY_IAP_READ_STRING 0xF8
+#define CAN_KEY_REBOOT    0xFC
+#define CAN_KET_ERASE_NV  0xFE
+
 
 void protocol_send_bms_info(uint8_t dest, uint8_t key, uint8_t *data, int len);
 void protocol_send_debug_info(uint8_t dest, uint8_t *data, int size);

+ 7 - 2
Application/app/sox/health.c

@@ -7,14 +7,12 @@
 #include "measure_task.h"
 #include "health.h"
 
-#define MAX_CURRENT_FOR_CHARGER (20*1000) //最大充电电流20A
 #if 0
 #define MIN_VOLTAGE_FOR_DISCHARGER (2.2f * CELLS_NUM * 1000) //允许能放电的最小电压
 #define MIN_VOLTAGE_FOR_RECOVERY_DISCHARGER (2.3f * CELLS_NUM * 1000) //恢复放电的最小电压
 #define MIN_VOLTAGE_FOR_POWER_DOWN (2.1f * CELLS_NUM* 1000)
 #define SIGLE_CELL_LOWER_DISCHARGER_VOLTAGE (1820) //最小允许的电芯放电电压 1.8v, 考虑到采样的误差取 1.82
 #endif
-#define SIGLE_CELL_MAX_CHARGER_VOLTAGE (3800)//最大允许充电电压,3.9v,考虑到采样的误差取 3.88
 
 static int8_t charger_normal_low_temp[PACK_TEMPS_NUM] = {0,0,0,0}; //正常的充电最低温度
 static int8_t charger_normal_high_temp[PACK_TEMPS_NUM] = {50,50,50,55}; //正常的充电最高温度
@@ -186,6 +184,10 @@ static int _can_powerdown(void){
 
 void check_voltage_state(void) {
 	if (bms_state_get()->charging){ //check sigle cell's voltage for charger
+		_health.discharger_shutpower_voltage = 0;
+		_health.sigle_cell_lower_voltage = 0;
+		_health.discharger_lower_voltage = 0;
+		_health.discharger_cell_shutpower_voltage = 0;
 		if ((bms_state_get()->cell_max_vol>= SIGLE_CELL_MAX_CHARGER_VOLTAGE)){
 			if (judge_debounce(!_health.sigle_cell_over_voltage, &_sigle_cell_charger_max_vol)){
 				_health.sigle_cell_over_voltage = 1;
@@ -195,8 +197,11 @@ void check_voltage_state(void) {
 				_health.sigle_cell_over_voltage = 0;
 			}
 		}
+		_health.charger_over_voltage = _health.sigle_cell_over_voltage;
 	}else{ 
 		//check sigle cell's voltage for discharger
+		_health.charger_over_voltage = _health.sigle_cell_over_voltage = 0;
+		
 		if ((bms_state_get()->cell_min_vol <= min_discharger_cell_vol[_health.is_work_temp_lower])){
 			if (judge_debounce(!_health.sigle_cell_lower_voltage, &_sigle_cell_discharger_lower_vol)){
 				_health.sigle_cell_lower_voltage = 1;

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

@@ -2,6 +2,9 @@
 #define _HEALTH_H__
 #include <stdint.h>
 #include "bsp/shark_bsp.h"
+
+#define MAX_CURRENT_FOR_CHARGER (20*1000) //最大充电电流20A
+#define SIGLE_CELL_MAX_CHARGER_VOLTAGE (3800)//最大允许充电电压,3.9v,考虑到采样的误差取 3.88
 /* 
  * xxx_over_temp: 表示过高温(温度过高)
  * xxx_under_temp: 表示过低温(温度过低)

+ 7 - 4
Application/app/sox/measure.c

@@ -123,9 +123,8 @@ static float get_pack_current_by_gd(void){
 	return (int)((cali_adc / max_gd_adc) * v_gd_ref / r_sense * 1000);
 }
 
-static float get_pack_current_by_cs1180(void){
-	float adc = cs1180_adc_sample();
-
+static float get_pack_current_by_cs1180(int *valid){
+	float adc = cs1180_adc_sample(valid);
 	return (adc / max_cs1180_adc) * v_cs1180_ref / r_sense * 1000 - 5.0f;//°å×ӹ̶¨5MA£¬cs1180ÎÞ·¨²âÁ¿µ½
 }
 
@@ -133,7 +132,11 @@ static float get_pack_current_by_cs1180(void){
 float get_pack_current(void){
 	float current = get_pack_current_by_gd();
 	if (cs1180_change_gain(current) == 0) {
-		current = get_pack_current_by_cs1180();
+		int valid = 1;
+		float cs1180_current = get_pack_current_by_cs1180(&valid);
+		if (valid == 1) {
+			current = cs1180_current;
+		}
 	}
 	return current;
 }

+ 22 - 10
Application/app/sox/soc.c

@@ -10,6 +10,7 @@ static soc_t _soc;
 static uint8_t chargering = 0;
 static u64     time_ms = 0;
 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;
 uint32_t charger_remain_time = 0;
@@ -39,17 +40,19 @@ void soc_init(void){
 	soc_log();
 }
 
+#define TOHA(x) (float)(x/3600.0f)
+
 void soc_log(void){
-	soc_debug("C now: %f\n", _soc.coulomb_now);
-	soc_debug("C min: %f\n", _soc.coulomb_min);
-	soc_debug("C max: %f\n", _soc.coulomb_max);
-	soc_debug("C char: %f\n", _soc.charger_coulomb);
-	soc_debug("C dischar: %f\n", _soc.dischrger_coulomb);
-	soc_debug("C pre char: %f\n", _soc.pre_discharger_coulomb);
-	soc_debug("C pre dischar: %f\n", _soc.pre_charger_coulomb);
-	soc_debug("C tol: %d\n", _soc.total_coulomb);
+	soc_debug("C now: %.2f\n", TOHA(_soc.coulomb_now));
+	soc_debug("C min: %.2f\n", TOHA(_soc.coulomb_min));
+	soc_debug("C max: %.2f\n", TOHA(_soc.coulomb_max));
+	soc_debug("C char: %.2f\n", TOHA(_soc.charger_coulomb));
+	soc_debug("C dischar: %.2f\n", TOHA(_soc.dischrger_coulomb));
+	soc_debug("C pre char: %.2f\n", TOHA(_soc.pre_discharger_coulomb));
+	soc_debug("C pre dischar: %.2f\n", TOHA(_soc.pre_charger_coulomb));
+	soc_debug("C tol: %.2f\n", _soc.total_coulomb);
 	soc_debug("C energy: %f\n", _soc.energy);
-	soc_debug("C delta time %fs\n", soc_delta_time);
+	soc_debug("C delta time %f,%f\n", max_soc_delta_time, soc_delta_time);
 	if (chargering){
 		soc_debug("C remain %d\n", charger_remain_time);
 	}
@@ -84,6 +87,9 @@ static __inline__ float _delta_time(void){
 	u32 delta = shark_get_mseconds() - time_ms;
 	time_ms = shark_get_mseconds();
 	soc_delta_time = (float)delta / (1000.0f);
+	if (soc_delta_time > max_soc_delta_time){
+		max_soc_delta_time = soc_delta_time;
+	}
 	return soc_delta_time; //秒
 }
 
@@ -105,6 +111,7 @@ void soc_update_by_ocv(void){
 			if (measure_value()->load_current <= 300.0f){				
 				//判断总电压
 				if (bms_state_get()->pack_voltage >= 54000){
+					soc_debug("measure_value()->load_current %d\n", measure_value()->load_current);
 					_soc.capacity = 100;
 				}
 			}
@@ -143,11 +150,13 @@ void soc_update(void){
 		_soc.charger_coulomb = 0;//clear charing
 		_soc.total_coulomb += _soc.pre_charger_coulomb / 3600.0f;
 		chargering = 1;
+		soc_warning("changed to chargering, current = %d\n", measure_value()->load_current);
 	}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;
+		soc_warning("changed to dischargering, current = %d\n", measure_value()->load_current);
 	}
 	double current = measure_value()->load_current / 1000.0f; //A
 	double delta_q = current * _delta_time();
@@ -166,7 +175,10 @@ void soc_update(void){
 		_soc.coulomb_now = _soc.coulomb_min;
 	}
 	uint8_t old_cap = _soc.capacity;
-	_soc.capacity = (_soc.coulomb_now - _soc.coulomb_min)/(_soc.coulomb_max - _soc.coulomb_min) * 100;
+	_soc.capacity = ((_soc.coulomb_now - _soc.coulomb_min)/(_soc.coulomb_max - _soc.coulomb_min) + 0.5f) * 100;//四舍五入
+	if (_soc.capacity > 100){
+		_soc.capacity = 100;
+	}
 	if (chargering && (_soc.capacity == 100)){
 		_soc.capacity = 99;//充电的时候必须通过ovc才能把电量校准到100
 	}else if (!chargering && (_soc.capacity == 0)){

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

@@ -18,7 +18,7 @@ typedef struct {
 	double pre_charger_coulomb;
 	double pre_discharger_coulomb;
 
-	uint32_t total_coulomb;
+	float total_coulomb;
 }soc_t;
 
 void soc_init(void);

+ 24 - 16
Application/app/sox/state.c

@@ -15,7 +15,7 @@
 #define ALLOW_DEEP_SLEEP 0
 #define SLEEP_IGNORE_UNHEALTH 0
 #define ALLOW_POWER_DOWN 0 //disable power down for debug
-#define ALLOW_5238_BALANCE 1
+#define ALLOW_5238_BALANCE 0
 
 static void _current_notify(void);
 static void _voltage_notify(void);
@@ -147,9 +147,9 @@ static s32 _process_unheath(void){
 	}
 
 	if (bms_health()->charger_over_current || bms_health()->charger_over_temp || bms_health()->charger_lower_temp ||
-				bms_health()->over_temp_deny_charger|| bms_health()->lower_temp_deny_charger){
+				bms_health()->over_temp_deny_charger|| bms_health()->lower_temp_deny_charger ||
+				bms_health()->charger_over_voltage || bms_health()->sigle_cell_over_voltage){
 		charger_open(0); //disable charger mosfet
-		_bms_state.charging = 0;
 		unhealth |= Health_charger_Fault;
 	}
 
@@ -292,7 +292,7 @@ static void _process_iostate_changed(s32 unhealth){
 			AUX_VOL_OPEN(1);
 		}
 	}
-	if (io_state()->charger_detect && ((unhealth & Health_charger_Fault) == 0)) {
+	if (io_state()->charger_detect && ((unhealth & Health_charger_Fault) == 0) && (_bms_state.cell_max_vol < SIGLE_CELL_MAX_CHARGER_VOLTAGE)) {
 		if (!ml5238_is_charging()){
 			charger_open(1);
 		}
@@ -308,20 +308,28 @@ static u32 _bms_main_task_handler(void){
 	return 0;
 }
 
-static debounce_t _charging_detect = {.count = 10, .max_count = 20, .init_count = 10};
+static debounce_t _charging_detect = {.count = 0, .max_count = 10, .init_count = 0};
 static void check_charging(){
-	if ((measure_value()->load_current >= MIN_START_CHARGER_CURRENT) && !_bms_state.charging) {
-		debounce_inc(_charging_detect);
-		if (debounce_reach_max(_charging_detect)){
-			_bms_state.charging = 1;
+	if ((measure_value()->load_current >= MIN_START_CHARGER_CURRENT)) {
+		if (!_bms_state.charging) {
+			debounce_inc(_charging_detect);
+			if (debounce_reach_max(_charging_detect)){
+				_bms_state.charging = 1;
+				debounce_reset(_charging_detect);
+			}
+		}else {
 			debounce_reset(_charging_detect);
 		}
-	}else if ((measure_value()->load_current < MIN_START_LOADING_CURRENT) && _bms_state.charging){
-		debounce_dec(_charging_detect);
-		if (debounce_reach_zero(_charging_detect)){
-			_bms_state.charging = 0;
+	}else if ((measure_value()->load_current < MIN_START_LOADING_CURRENT)){
+		if (_bms_state.charging) {
+			debounce_inc(_charging_detect);
+			if (debounce_reach_max(_charging_detect)){
+				_bms_state.charging = 0;
+				debounce_reset(_charging_detect);
+			}
+		}else {
 			debounce_reset(_charging_detect);
-		}		
+		}
 	}	
 }
 
@@ -411,11 +419,11 @@ static uint8_t calc_cell_voltage(void){
 	uint8_t max_index = 0;
 	for (int i = 0; i < CELLS_NUM; i++){
 		voltage += measure_value()->cell_vol[i];
-		if (max_cell > measure_value()->cell_vol[i]){
+		if (max_cell < measure_value()->cell_vol[i]){
 			max_cell = measure_value()->cell_vol[i];
 			max_index = i;
 		}
-		if (min_cell < measure_value()->cell_vol[i]){
+		if (min_cell > measure_value()->cell_vol[i]){
 			min_cell = measure_value()->cell_vol[i];
 		}		
 	}

+ 27 - 14
Application/bsp/cs1180.c

@@ -254,9 +254,9 @@ int cs1180_change_gain(int current){
 		return cs1180_adc_set_gain_online(CS1180_GAIN_128X);
 	}else if (abs(current) < 12 * 1000){ //18
 		return cs1180_adc_set_gain_online(CS1180_GAIN_32X);
-	}else if (abs(current) < 48 * 1000){ //72
+	}/*else if (abs(current) < 48 * 1000){ //72
 		return cs1180_adc_set_gain_online(CS1180_GAIN_8X);
-	}/*else if (abs(current) < 160 * 1000){
+	}else if (abs(current) < 160 * 1000){
 		return cs1180_adc_set_gain_online(CS1180_GAIN_1X);
 	}*/
 	return -1;
@@ -268,23 +268,36 @@ void cs1180_adc_shutdown(void){
 	_cs1180_ready = 0;
 }
 
-float cs1180_adc_sample(void)
+float cs1180_adc_sample(int *valide)
 {
 	uint8_t data[3] = {0,0,0};
 	int a = 0;
-	
+	int retry = 5;
 	while (IS_CS1180_NOT_READY()); //当drdy 为高时,不读取数据
 
-	cs1180_cs(0);
-	cs1180_send_cmd(CS1180_RDATA);
-	delay_us(60);
-	data[0] = cs1180_read_data(0xFF);
-	data[1] = cs1180_read_data(0xFF);
-	data[2] = cs1180_read_data(0xFF);
-	cs1180_cs(1);
-	a = (data[0] << 16) | (data[1] << 8) | data[2];
-	a >>= 4;
-
+	while(retry-- >= 0) {
+		cs1180_cs(0);
+		cs1180_send_cmd(CS1180_RDATA);
+		delay_us(100);
+		data[0] = cs1180_read_data(0xFF);
+		data[1] = cs1180_read_data(0xFF);
+		data[2] = cs1180_read_data(0xFF);
+		cs1180_cs(1);
+		a = (data[0] << 16) | (data[1] << 8) | data[2];
+		a >>= 4;
+		if (a != 0xFFFFF){//spi 上拉,所以如果读到的数据全F,说明可能cs1180没有数据输出,通过判断ready来确定是否要重读
+			break;
+		}
+		delay_us(100);
+		if (IS_CS1180_NOT_READY()){
+			break;
+		}
+		sys_warning("cs1180 read adc retry!!!!\n");
+	}
+	if ((a == 0xFFFFF) && !IS_CS1180_NOT_READY() && (valide != NULL)){
+		sys_error("cs1180 adc is not valide\n");
+		*valide = 0;
+	}
 	if (a & 0x80000) {
 		a = ~a;
 		a = - (a&0x7FFFF);

+ 1 - 1
Application/bsp/cs1180.h

@@ -15,7 +15,7 @@ void cs1180_adc_shutdown(void);
 int cs1180_is_ready(void);
 int cs1180_adc_set_gain(int gain);
 void cs1180_sys_offset_calibrate(void);
-float cs1180_adc_sample(void);
+float cs1180_adc_sample(int *valide);
 int cs1180_change_gain(int current);
 
 #endif /* _CS1180_H__ */

+ 4 - 2
Application/bsp/mcu_power_sleep.c

@@ -18,6 +18,7 @@ extern void current_calibrate(void);
 extern void adc_init(void);
 extern void adc_deinit(void);
 static uint32_t _sleep_second_time = 0;
+static uint32_t _sleep_second_time_now = 0;
 static void post_deepsleep(void);
 
 #define WDOG_TIME_FOR_SLEEP 15
@@ -96,10 +97,11 @@ void mcu_enter_deepsleep(void){
 	pmu_to_deepsleepmode(PMU_LDO_LOWPOWER, WFI_CMD);
 	u32 end_time = shark_rtc_get_second();
 	if (end_time >= start_time) {
-		_sleep_second_time += (end_time - start_time);
+		_sleep_second_time_now = end_time - start_time;
 	}else { //rtc second wrap
-		_sleep_second_time += (60 - start_time + end_time);
+		_sleep_second_time_now = 60 - start_time + end_time;
 	}
+	_sleep_second_time += _sleep_second_time_now;
 	disable_wakeup_irq();
 	post_deepsleep();
 }

+ 3 - 3
Application/bsp/spi.c

@@ -42,9 +42,9 @@ void spi1_init(void){
 	rcu_periph_clock_enable(RCU_GPIOB);
 	rcu_periph_clock_enable(RCU_SPI1);
 
-	gpio_mode_af(GPIOB, GPIO_PUPD_NONE, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15);
+	gpio_mode_af(GPIOB, GPIO_PUPD_PULLUP, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15);
 	gpio_af_set(GPIOB, GPIO_AF_0, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15);
-	gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13|GPIO_PIN_15);
+	gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15);
 
 	spi_i2s_deinit(SPI1);
 	spi_parameter_struct spi_init_struct;
@@ -55,7 +55,7 @@ void spi1_init(void){
     spi_init_struct.frame_size           = SPI_FRAMESIZE_8BIT;
     spi_init_struct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_2EDGE;
     spi_init_struct.nss                  = SPI_NSS_SOFT;
-    spi_init_struct.prescale             = SPI_PSC_64 ;
+    spi_init_struct.prescale             = SPI_PSC_128 ;
     spi_init_struct.endian               = SPI_ENDIAN_MSB;
     spi_init(SPI1, &spi_init_struct);