Przeglądaj źródła

实现bms基本指令

Signed-off-by: huhui <huhui@sharkgulf.com>
huhui 5 lat temu
rodzic
commit
517217d29c

+ 119 - 1
Application/app/bms_message.c

@@ -1,6 +1,124 @@
+#include "app/sox/soc.h"
+#include "app/sox/measure.h"
+#include "app/sox/measure_task.h"
+#include "app/sox/health.h"
+#include "app/sox/state.h"
+#include "bsp/gpio.h"
+#include "bsp/ml5238.h"
+#include "libs/logger.h"
+#include "protocol.h"
 #include "bms_message.h"
 
-void process_bms_message(uint8_t *data, int len){
+static uint8_t bms_insert = 0;
+static uint8_t bms_insert_ack = 0;
+void bms_message_update_insert(int is_hall_detect){
+	if (!is_hall_detect){
+		bms_insert = 0;
+		bms_insert_ack = 0;
+	}else {
+		if (!bms_insert_ack) {
+			bms_insert = 1;
+		}
+	}
+}
 
+void process_bms_message(can_frame_t *frame, int len){
+	int result = 0;
+	uint8_t *data = NULL;
+	int data_len = 0;
+	switch(frame->key) {
+		case CAN_KEY_BMS_SET_POWER:
+			if (len != sizeof(pwr_cmd_t)){
+				result = 1;
+			}else {
+				pwr_cmd_t *cmd = (pwr_cmd_t *)frame->data;
+				int user_request = (int)USER_REQUEST_PENDING;
+				if (cmd->charger_fet){
+					user_request |= USER_REQUEST_CHARGER;
+				}
+				if (cmd->discharger_fet){
+					user_request |= USER_REQUEST_DISCHARGER;
+				}
+				if (cmd->small_power){
+					user_request |= USER_REQUEST_SMALLCURRENT;
+				}
+				bms_state_get()->user_request = user_request;
+			}
+			protocol_send_ack(frame->head.can_addr, frame->key, result);
+			break;
+		case CAN_KEY_BMS_BASE_INFO:{
+			binfo_cmd_resp_t bresp;
+			bresp.capacity = get_soc()->capacity;
+			bresp.energy = get_soc()->energy;
+			bresp.pack_current = measure_value()->load_current;
+			bresp.pack_voltage = bms_state_get()->pack_voltage;
+			bresp.max_temp = 0;
+			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];
+				}
+			}
+			data = (uint8_t *)&bresp;
+			data_len = sizeof(bresp);			
+			break;
+		}
+		case CAN_KEY_BMS_CHARG_INFO:{
+			cinfo_cmd_resp_t cresp;
+			cresp.charge_current = measure_value()->load_current;
+			cresp.charge_remain_time = 0;
+			data = (uint8_t *)&cresp;
+			data_len = sizeof(cresp);			
+			break;
+		}
+		case CAN_KEY_BMS_CLEAR:
+			bms_insert_ack = 1;
+			bms_insert = 0;
+			protocol_send_ack(frame->head.can_addr, frame->key, result);
+			break;
+		case CAN_KEY_BMS_GET_STAT: {
+			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;
+			uint32_t *h = (uint32_t *)(bms_health());
+			sresp.health = (*h != 0);
+			data = (uint8_t *)&sresp;
+			data_len = sizeof(sresp);
+			break;
+		}
+		case CAN_KEY_BMS_TEMPS:
+			data = (uint8_t *)measure_value()->pack_temp;
+			data_len = sizeof(measure_value()->pack_temp);
+			break;
+		case CAN_KEY_BMS_GET_CELLS:
+			data = (uint8_t *)measure_value()->cell_vol;
+			data_len = sizeof(measure_value()->cell_vol);
+			break;
+		case CAN_KEY_BMS_GET_HEALTH_STAT:
+			data = (uint8_t *)bms_health();
+			data_len = sizeof(*bms_health());
+		case CAN_KEY_SET_SN:
+			protocol_send_ack(frame->head.can_addr, frame->key, result);
+			break;
+		case CAN_KEY_GET_SN:
+			break;
+		case CAN_KEY_GET_VERSION:
+			break;
+		case CAN_KEY_SET_LOGGER:
+			if (len != 2) {
+				result = 1;
+			}else {
+				set_log_level(frame->data[0], frame->data[1]);
+			}
+			protocol_send_ack(frame->head.can_addr, frame->key, result);
+			break;
+	}
+	if (data != NULL && data_len > 0){
+		protocol_send_bms_info(frame->head.can_addr, frame->key, data, data_len);
+	}
+	
 }
 

+ 2 - 2
Application/app/bms_message.h

@@ -1,5 +1,5 @@
 #pragma once
 #include <stdint.h>
-
-void process_bms_message(uint8_t *data, int len);
+#include "protocol.h"
+void process_bms_message(can_frame_t *frame, int len);
 

+ 1 - 1
Application/app/pc_message.c

@@ -1,6 +1,6 @@
 #include "pc_message.h"
 
-void process_pc_message(uint8_t *data, int len){
+void process_pc_message(can_frame_t *frame, int len){
 
 }
 

+ 2 - 1
Application/app/pc_message.h

@@ -1,4 +1,5 @@
 #pragma once
 #include <stdint.h>
-void process_pc_message(uint8_t *data, int len);
+#include "protocol.h"
+void process_pc_message(can_frame_t *frame, int len);
 

+ 28 - 14
Application/app/protocol.c

@@ -6,16 +6,29 @@
 static uint16_t _check_sum(uint8_t*data,uint16_t size);
 static uart_enum_t current_uart = SHARK_UART0;
 
-void protocol_send_bms_info(protocol_head_t *head){
-
+void protocol_send_bms_info(uint8_t dest, uint8_t key, uint8_t *data, int len){
+	can_frame_t can_frame;
+	CAN_OUT(&(can_frame.head), dest);
+	can_frame.key = key;
+	shark_uart_frame_start(current_uart, (uint8_t *)&can_frame, sizeof(can_frame));
+	shark_uart_frame_continue(current_uart, data, len);
+	shark_uart_frame_end(current_uart);	
 }
 
+void protocol_send_ack(uint8_t dest, uint8_t key, int result) {
+	uint8_t data[sizeof(can_frame_t) + 1];
+	can_frame_t *frame = (can_frame_t *)data;
+	CAN_OUT(&(frame->head), dest);
+	frame->key = key;
+	data[sizeof(can_frame_t)] = result;
+	shark_uart_write_frame(current_uart, data, sizeof(data));
+}
 
-void protocol_send_debug_info(uint8_t dest, uint8_t *data, int size){	
+void protocol_send_debug_info(uint8_t dest, uint8_t *data, int len){	
 	can_head_t can_head;
-	can_head.can_addr = dest;
+	CAN_OUT(&can_head, dest);
 	shark_uart_frame_start(current_uart, (uint8_t *)&can_head, sizeof(can_head));
-	shark_uart_frame_continue(current_uart, data, size);
+	shark_uart_frame_continue(current_uart, data, len);
 	shark_uart_frame_end(current_uart);
 }
 
@@ -38,18 +51,19 @@ void protocol_notify_old_frame(uart_enum_t uart_no){
 
 void protocol_recv_frame(uart_enum_t uart_no, uint8_t *data, int len){
 	current_uart = uart_no;
-	if (len < sizeof(can_head_t)){
+	if (len < sizeof(can_frame_t)){
 		return;
 	}
-	can_head_t *can_head = (can_head_t *)data;
-	if (can_head->can_addr == 0x45){ //pc sent
-		process_pc_message(data + sizeof(can_head_t), len - sizeof(can_head_t));
+	can_frame_t *can_frame = (can_frame_t *)data;
+	if (!CAN_IN(&(can_frame->head))) {//data is sent by myself, drop
+		return;
+	}
+
+	len -= sizeof(can_frame_t);
+	if (can_frame->head.can_addr == 0x45){ //pc sent
+		process_pc_message(can_frame, len);
 	}else {
-		len -= sizeof(can_head_t);
-		if (len <sizeof(protocol_head_t)){
-			return;
-		}
-		process_bms_message(data + sizeof(can_head_t), len - sizeof(can_head_t));
+		process_bms_message(can_frame, len);
 	}
 }
 

+ 57 - 81
Application/app/protocol.h

@@ -1,15 +1,6 @@
 #pragma once
 
 #include <stdint.h>
-
-#pragma  pack (push,1)  
-typedef struct
-{
-	uint8_t can_addr;
-}can_head_t;
-#pragma pack(pop)
-
-
 /* ================ 老协议 ================== */
 #pragma  pack (push,1)  
 typedef struct
@@ -33,94 +24,79 @@ typedef struct
 
 
 /* ================ 新协议 ================== */
-#define PROT_V00 0x00
-#define PROT_V01 0x01
+#define MY_CAN_ADDR 0x30
+#pragma  pack (push,1)  
+typedef struct
+{
+	uint8_t can_addr:7;
+	uint8_t can_dir:1; //0->out, 1 ->in,如果发现收到的是0,可能是红外那边自环过来的,需要丢弃
+}can_head_t;
+
+#define CAN_OUT(head, addr) {(head)->can_addr = addr; (head)->can_dir = 0;}
+#define CAN_IN(head) ((head)->can_dir == 1)
+
+typedef struct {
+	can_head_t head;
+	uint8_t key;
+	uint8_t data[0];
+}can_frame_t;
+#pragma pack(pop)
 
+/* can key define */
+#define CAN_KEY_BMS_SET_POWER 0x0B //开关各种mos和小电流
 #pragma  pack (push,1)
 typedef struct {
-	uint8_t dir 			:1;//1:bms out, 0: bms in
-	uint8_t insert 			:1;//是否新插入
-	uint8_t health 			:1;//电池是否有异常
 	uint8_t discharger_fet	:1;//dis/charger mos是否打开
 	uint8_t charger_fet		:1;
 	uint8_t small_power		:1;//小电是否打开
-	uint8_t is_charging 	:1;//是否在充电
-	uint8_t cmd_result		:1;//PSxxx 下发的cmd,是否成功
-}bms_stat_t;
+	uint8_t res				:5;
+}pwr_cmd_t;
+#pragma pack(pop)
 
+#define CAN_KEY_BMS_GET_STAT 0xa0 //bms_stat_t
+#pragma  pack (push,1)
 typedef struct {
-	uint8_t dir 			:1;//1:bms out, 0: bms in
-	uint8_t power_cmd		:1;//power命令是否有效,开关充放电mos,小电
-	uint8_t discharger_fet	:1;//打开dis/charger mos
+	uint8_t insert 			:1;//是否新插入,检测到霍尔马上置为1,等CAN_KEY_BMS_CLEAR
+	uint8_t health 			:1;//电池是否有异常
+	uint8_t discharger_fet	:1;//dis/charger mos是否打开
 	uint8_t charger_fet		:1;
-	uint8_t small_power		:1;//打开小电
-	uint8_t bms_info		:1; //读取bms基本信息,电压,电流
-	uint8_t bms_temps		:1; //读取pack的温度
-	uint8_t ext_cmd			:1; //扩展命令
-}bms_cmd_t;
-
-typedef struct
-{
-	//协议类型
-	uint8_t protocol;
-	union {
-		bms_stat_t status;
-		bms_cmd_t command;
-	}u_sc;
-}protocol_head_t;
+	uint8_t small_power		:1;//小电是否打开
+	uint8_t is_charging 	:1;//是否在充电
+	uint8_t is_charger_in   :1;
+	uint8_t is_balancing    :1; //是否在均衡
+}stat_cmd_resp_t;
 #pragma pack(pop)
 
+#define CAN_KEY_BMS_BASE_INFO 0x00 //电压,电流,能量, SOC,max temp
+#pragma  pack (push,1)
+typedef struct {
+	uint32_t pack_voltage;
+	int32_t  pack_current;
+	uint8_t  capacity;
+	uint32_t energy;   //能量,给PS100/200/310/360计算续航里程用
+	int8_t  max_temp;//最高的那个温度
+}binfo_cmd_resp_t;
+#pragma pack(pop)
 
-enum
-{
-	OP_NONE, //返回bms基本信息
-	OP_BIN_LIAN, // not used
-	OP_WRITE_SN,
-	OP_PAIR,
-	OP_UPDATE_PAIR,
-	OP_READ_INFO,
-	OP_ALARM_TIMES,
-	OP_CELL_VOL,//0x07
-	OP_TEMP_OTHER,//0x08
-	
-	OP_OPEN_FET = 0x0B,
-
-	OP_CLEAR_PAIR = OP_TEMP_OTHER + 1,
-	OP_UPDATE_SOFTWARE_REQ = 0x0E,
-	OP_UPDATE_SOFTWARE = 0x0F,
-	
-	OP_MAX
-};
+#define CAN_KEY_BMS_CHARG_INFO 0xa1
+typedef struct {
+	uint32_t charge_current;
+	uint32_t charge_remain_time; //s
+}cinfo_cmd_resp_t;
 
-#pragma  pack (push,1)  
-typedef struct
-{
-	uint8_t 	bike_speed;
-	uint32_t 	current_miles;//本次电门打开行驶的里程
-	uint8_t  	egate_open; //电门开关信号
-	uint8_t 	operate;
-	uint8_t 	res[8];//保留
-}command_t;
-#pragma pack(pop)
+#define CAN_KEY_BMS_TEMPS 0x11 //return int[4]
+#define CAN_KEY_BMS_GET_CELLS   0x07 //return uint16_t[15]
+#define CAN_KEY_SET_LOGGER  0xa2 //byte 0:modle, byte1 level
+#define CAN_KEY_BMS_CLEAR   0xa3 //clear some flags used by PSxxx, exp: stat_cmd_resp_t.insert
+#define CAN_KEY_BMS_GET_HEALTH_STAT 0xa4 //return bms_health_t
 
+#define CAN_KEY_GET_VERSION 0x0c //return string
+#define CAN_KEY_SET_SN      0x06 //string
+#define CAN_KEY_GET_SN      0x05 //return string
 
-#pragma  pack (push,1) 
-typedef struct {
-	uint8_t 	remain_mils; //预估可行驶里程
-	uint8_t 	soc_percent; //剩余电量
-	uint8_t 	charger_remain_time; //预计充电完成时间
-	uint8_t 	is_charging; //是否在充电
-	uint32_t 	current; //放电或者充电电流
-	uint32_t 	pack_voltage; //电池包总电压
-	uint8_t 	max_temp; //4个温感中的最高温度
-	uint16_t 	bms_status; //bms的状态,比如过高温放电等
-	uint32_t 	in_balance_cells; //正在均衡的电芯
-	uint8_t 	misc_flags; //0:bound, 1-2: mosfet, 3: aux short, 4: full 5-6:reserve
-	uint8_t 	result; //0-3:result, 4-7: operate
-}common_response_t;
-#pragma pack(pop)
 
-void protocol_send_bms_info(protocol_head_t *head);
+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);
+void protocol_send_ack(uint8_t dest, uint8_t key, int result);
 
 

+ 19 - 6
Application/app/sox/health.h

@@ -7,17 +7,30 @@
  * xxx_under_temp: 表示过低温(温度过低)
 */
 typedef struct {
+	uint32_t charger_over_voltage:1;
+	uint32_t discharger_lower_voltage:1;
+	uint32_t small_current_short:1;
+	uint32_t load_current_short:1; //大电短路保护
+
+	uint32_t charger_current:1; //不需要
+	uint32_t discharger_current:1;
 	uint32_t charger_over_current:1;
-	uint32_t charger_over_temp:1;
+	uint32_t discharger_over_current:1;
+
+	uint32_t res1 :1;//ST_TOTAL_CHRG
+	uint32_t charger_cells_vol_diff_over; //充电cell的电压差异超过阈值
+	uint32_t power_save;
+	uint32_t powerdown_lower_voltage:1;
+
 	uint32_t charger_lower_temp:1;
-	uint32_t discharger_over_temp:1;
 	uint32_t discharger_lower_temp:1;
-	uint32_t discharger_lower_voltage:1;
-	uint32_t powerdown_lower_voltage:1;
+	uint32_t charger_over_temp:1;
+	uint32_t discharger_over_temp:1;
+
 	uint32_t sigle_cell_lower_voltage:1;
 	uint32_t sigle_cell_over_voltage:1;
-	uint32_t load_current_short:1; //大电短路保护
-	uint32_t small_current_short:1;
+
+	uint32_t res2:14;
 	uint16_t internal_resistance;   //pack's internal resistance
 }bms_health_t;
 

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

@@ -14,25 +14,26 @@
 #define ALLOW_POWER_DOWN 1
 #define ALLOW_5238_BALANCE 1
 
-static bms_state_t _bms_state;
-static shark_task_t _bms_main_task;
-static shark_timer_t _balance_timer;
-
 static void _current_notify(void);
 static void _voltage_notify(void);
 static void _temperature_notify(void);
 static u32 _bms_main_task_handler(void);
 static void _balance_timer_handler(shark_timer_t *t);
 
+static bms_state_t _bms_state;
+static shark_task_t _bms_main_task = {.handler = _bms_main_task_handler};
+static shark_timer_t _balance_timer = {.handler = _balance_timer_handler};
+
+
 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();
 	soc_init();
 	shark_task_add(&_bms_main_task);
 	set_log_level(MOD_STATE, L_debug);
+	state_debug("BMS System Starting......\n");
 }
 
 bms_state_t *bms_state_get(void){
@@ -243,7 +244,6 @@ static void check_cell_balance(uint8_t current_max_index){
 	}
 	if (_bms_state.pack_balancing && (current_max_index != _bms_state.cell_index_of_max_vol)){
 		ml5238_cell_start_balance(BIT(current_max_index));
-		_balance_timer.handler = _balance_timer_handler;
 		shark_timer_post(&_balance_timer, 60 * 1000); //stop balance after 1 minute
 	}
 	_bms_state.cell_index_of_max_vol = current_max_index;	

+ 1 - 1
Application/bsp/ml5238.c

@@ -21,7 +21,7 @@ void ml5238_register_notify_handler(ml5238_notify_hander handler){
 }
 
 
-//used to detect charger over current
+//СµçÁ÷´ò¿ªµÈЧdischarger mos´ò¿ª
 int ml5238_charger_is_disconnect(int small_current_on){
 	uint8_t value = 0;
 	uint8_t fet = 0;