diff --git a/application/chassis/chassis.c b/application/chassis/chassis.c index 1e0a1a2..0d70798 100644 --- a/application/chassis/chassis.c +++ b/application/chassis/chassis.c @@ -43,7 +43,7 @@ static Chassis_Ctrl_Cmd_s chassis_cmd_recv; // 底盘接收到的控制 static Chassis_Upload_Data_s chassis_feedback_data; // 底盘回传的反馈数据 static referee_info_t* referee_data; // 用于获取裁判系统的数据 -static Referee_Interactive_info_t ui_data; // UI数据 +static Referee_Interactive_info_t ui_data; // UI数据,将底盘中的数据传入此结构体的对应变量中,UI会自动检测是否变化,对应显示UI static SuperCapInstance *cap; // 超级电容 static DJIMotorInstance *motor_lf, *motor_rf, *motor_lb, *motor_rb; // left right forward back @@ -105,9 +105,6 @@ void ChassisInit() referee_data = Referee_Interactive_init(&huart6,&ui_data); // 裁判系统初始化 - // while (referee_data->GameRobotState.robot_id ==0); - // Referee_Interactive_init(referee_data); - SuperCap_Init_Config_s cap_conf = { .can_config = { .can_handle = &hcan2, diff --git a/modules/referee/referee.md b/modules/referee/referee.md index 0bc3115..8417705 100644 --- a/modules/referee/referee.md +++ b/modules/referee/referee.md @@ -6,24 +6,22 @@ UI的绘制包含初始化和TASK两个部分,初始化部分在`My_UI_init` 初始化部分的UI主要有两个目的:静态UI的绘制、为动态UI的绘制做准备。 分析超级电容能量条功能可知,此UI包含如下: -voltage:xxx voltage为静态不变的,冒号后的xxx为变化的量。 +Power:xxx Power为静态不变的,冒号后的xxx为变化的量。 方框以及方框内的能量条:方框为静态不变的,能量条为变化的量。(参考游戏血条) 因而,静态UI的绘制包含如下: -绘制字符“voltage:”、绘制矩形方框。 +绘制字符“Power:”、绘制矩形方框。 为动态UI的准备如下: -绘制矩形方框内的初始能量条、绘制voltage的初始值。 +绘制矩形方框内的初始能量条、绘制Power的初始值。 -### 绘制字符“voltage:”: -设置绘制用结构体,此处使用数组是因为需要绘制多个字符。本次绘制的字符为“voltage:”,只是用到了第6个,即xxx[5]: +### 绘制字符“Power:”: +设置绘制用结构体,此处使用数组是因为需要绘制多个字符。本次绘制的字符为“Power:”,只是用到了第6个,即xxx[5]: ```c static String_Data_t UI_State_sta[6]; // 静态 -static String_Data_t UI_State_dyn[6]; // 动态 ``` 字符格式以及内容设置: ```c -// 底盘功率显示,静态 -Char_Draw(&UI_State_sta[5], "ss5", UI_Graph_ADD, 8, UI_Color_Green, 18, 2, 720, 210, "Voltage:"); +Char_Draw(&UI_State_sta[5], "ss5", UI_Graph_ADD, 7, UI_Color_Green, 18, 2, 620, 230, "Power:"); ``` 各参数意义如下,函数定义中有详细注释: @@ -38,18 +36,112 @@ Char_Draw(&UI_State_sta[5], "ss5", UI_Graph_ADD, 8, UI_Color_Green, 18, 2, 720, *stringdata 字符串数据 设置完毕后,使用“Char_ReFresh”发送即可: ```c -// 底盘功率显示,静态 -Char_ReFresh(&_referee_info->referee_id, UI_State_sta[5]); +Char_ReFresh(&referee_recv_info->referee_id, UI_State_sta[5]); ``` ### 绘制能量框: 定义一个图形类结构体,用于绘制能量框: ```c -static Graph_Data_t UI_energy_line[1]; // 电容能量条 +static Graph_Data_t UI_energy_line[3]; // 电容能量条 +``` +能量框参数设置以及发送函数: +```c +Rectangle_Draw(&UI_energy_line[0],"ss6", UI_Graph_ADD, 7, UI_Color_Green,20, 720, 220, 820, 240) +UI_ReFresh(&referee_recv_info->referee_id, 1,UI_energy_line[0]); +``` + +### 绘制power的初始值: +```c +Float_Draw(&UI_Energy[1], "sd5", UI_Graph_ADD, 8, UI_Color_Green, 18, 2, 2, 750, 230, 24000); +``` +### 绘制能量条的初始值: +```c +Line_Draw(&UI_Energy[2], "sd6", UI_Graph_ADD, 8, UI_Color_Pink, 30, 720, 160, 1020, 160); +``` +将两个图形打包发送 +``` +UI_ReFresh(&referee_recv_info->referee_id, 2, UI_Energy[1], UI_Energy[2]); +``` + +## TASK部分 +task中UI处于动态变化,此时需要检测所画的UI是否发生变化,若发生变化,则刷新对应UI。 +### 添加变化检测: +绘制功率部分UI,我们需要的是`Chassis_Power_Data_s`中的数据,我们定义`Chassis_Power_Data_s Chassis_Power_Data;`和`Chassis_Power_Data_s Chassis_last_Power_Data;`分别存储此次和上次的对应数据,本次和上次对应检测变化的需求。 +```c +typedef struct +{ + Referee_Interactive_Flag_t Referee_Interactive_Flag; + // 为UI绘制以及交互数据所用 + chassis_mode_e chassis_mode; // 底盘模式 + gimbal_mode_e gimbal_mode; // 云台模式 + shoot_mode_e shoot_mode; // 发射模式设置 + friction_mode_e friction_mode; // 摩擦轮关闭 + lid_mode_e lid_mode; // 弹舱盖打开 + Chassis_Power_Data_s Chassis_Power_Data; // 功率控制 + + // 上一次的模式,用于flag判断 + chassis_mode_e chassis_last_mode; + gimbal_mode_e gimbal_last_mode; + shoot_mode_e shoot_last_mode; + friction_mode_e friction_last_mode; + lid_mode_e lid_last_mode; + Chassis_Power_Data_s Chassis_last_Power_Data; + +} Referee_Interactive_info_t; +``` +添加功率变化标志位,`uint32_t Power_flag : 1;`,1为检测到变化,0为未检测到变换 +``` +typedef struct +{ + uint32_t chassis_flag : 1; + uint32_t gimbal_flag : 1; + uint32_t shoot_flag : 1; + uint32_t lid_flag : 1; + uint32_t friction_flag : 1; + uint32_t Power_flag : 1; +} Referee_Interactive_Flag_t; +``` +在变化检测函数中增加对应判断,由于voltage和能量条的变化对应同一个参数`Chassis_last_Power_Data.chassis_power_mx`的变化,所以只需要一个参数即可: +``` +static void Mode_Change_Check(Referee_Interactive_info_t *_Interactive_data) +{ + if (_Interactive_data->chassis_mode != _Interactive_data->chassis_last_mode) + ...... + ...... + if (_Interactive_data->lid_mode != _Interactive_data->lid_last_mode) + { + _Interactive_data->Referee_Interactive_Flag.lid_flag = 1; + _Interactive_data->lid_last_mode = _Interactive_data->lid_mode; + } + + if (_Interactive_data->Chassis_Power_Data.chassis_power_mx != _Interactive_data->Chassis_last_Power_Data.chassis_power_mx) + { + _Interactive_data->Referee_Interactive_Flag.Power_flag = 1; + _Interactive_data->Chassis_last_Power_Data.chassis_power_mx = _Interactive_data->Chassis_Power_Data.chassis_power_mx; + } +} +``` +### 根据功率的变化绘制UI: +在绘制变化的UI时,由于初始化时已经使用`UI_Graph_ADD`操作添加了UI,所以在绘制时,需要使用`UI_Graph_Change`操作,以便于刷新UI。 + +同时,完成UI刷新后,需要将对应的flag置0,以便于下次检测变化 +``` +if (_Interactive_data->Referee_Interactive_Flag.Power_flag == 1) +{ + Float_Draw(&UI_Energy[1], "sd5", UI_Graph_Change, 8, UI_Color_Green, 18, 2, 2, 750, 230, _Interactive_data->Chassis_Power_Data.chassis_power_mx * 1000); + Line_Draw(&UI_Energy[2], "sd6", UI_Graph_Change, 8, UI_Color_Pink, 30, 720, 160, (uint32_t)750 + _Interactive_data->Chassis_Power_Data.chassis_power_mx * 30, 160); + UI_ReFresh(&referee_recv_info->referee_id, 2, UI_Energy[1], UI_Energy[2]); + _Interactive_data->Referee_Interactive_Flag.Power_flag = 0; +} ``` + + +# +# +# 若需要进行多机交互,可增加此函数: ```c void CommBetweenRobotSend(referee_id_t *_id, robot_interactive_data_t *_data) diff --git a/modules/referee/referee_task.c b/modules/referee/referee_task.c index 8ff4694..8a1a077 100644 --- a/modules/referee/referee_task.c +++ b/modules/referee/referee_task.c @@ -12,7 +12,7 @@ #include "robot_def.h" #include "rm_referee.h" #include "referee_UI.h" - +#include "string.h" static Referee_Interactive_info_t *Interactive_data; // UI绘制需要的机器人状态数据 static referee_info_t *referee_recv_info; // 接收到的裁判系统数据 @@ -51,23 +51,24 @@ void Referee_Interactive_task() } static Graph_Data_t UI_shoot_line[10]; // 射击准线 -static Graph_Data_t UI_energy_line[1]; // 电容能量条 +static Graph_Data_t UI_Energy[3]; // 电容能量条 static String_Data_t UI_State_sta[6]; // 机器人状态,静态只需画一次 static String_Data_t UI_State_dyn[6]; // 机器人状态,动态先add才能change static uint32_t shoot_line_location[10] = {540, 960, 490, 515, 565}; void My_UI_init() { + while (referee_recv_info->GameRobotState.robot_id == 0) + ; DeterminRobotID(); UIDelete(&referee_recv_info->referee_id, UI_Data_Del_ALL, 0); // 清空UI - // // 绘制发射基准线 + // 绘制发射基准线 Line_Draw(&UI_shoot_line[0], "sl0", UI_Graph_ADD, 7, UI_Color_White, 3, 710, shoot_line_location[0], 1210, shoot_line_location[0]); Line_Draw(&UI_shoot_line[1], "sl1", UI_Graph_ADD, 7, UI_Color_White, 3, shoot_line_location[1], 340, shoot_line_location[1], 740); Line_Draw(&UI_shoot_line[2], "sl2", UI_Graph_ADD, 7, UI_Color_Yellow, 2, 810, shoot_line_location[2], 1110, shoot_line_location[2]); Line_Draw(&UI_shoot_line[3], "sl3", UI_Graph_ADD, 7, UI_Color_Yellow, 2, 810, shoot_line_location[3], 1110, shoot_line_location[3]); Line_Draw(&UI_shoot_line[4], "sl4", UI_Graph_ADD, 7, UI_Color_Yellow, 2, 810, shoot_line_location[4], 1110, shoot_line_location[4]); - UI_ReFresh(&referee_recv_info->referee_id, 5, UI_shoot_line[0], UI_shoot_line[1], UI_shoot_line[2], UI_shoot_line[3], UI_shoot_line[4]); // 绘制车辆状态标志指示 @@ -82,10 +83,6 @@ void My_UI_init() Char_Draw(&UI_State_sta[4], "ss4", UI_Graph_ADD, 8, UI_Color_Pink, 15, 2, 150, 550, "lid:"); Char_ReFresh(&referee_recv_info->referee_id, UI_State_sta[4]); - // 底盘功率显示,静态 - Char_Draw(&UI_State_sta[5], "ss5", UI_Graph_ADD, 8, UI_Color_Green, 18, 2, 720, 210, "Power:"); - Char_ReFresh(&referee_recv_info->referee_id, UI_State_sta[5]); - // 绘制车辆状态标志,动态 // 由于初始化时xxx_last_mode默认为0,所以此处对应UI也应该设为0时对应的UI,防止模式不变的情况下无法置位flag,导致UI无法刷新 Char_Draw(&UI_State_dyn[0], "sd0", UI_Graph_ADD, 8, UI_Color_Main, 15, 2, 270, 750, "zeroforce"); @@ -99,9 +96,18 @@ void My_UI_init() Char_Draw(&UI_State_dyn[4], "sd4", UI_Graph_ADD, 8, UI_Color_Pink, 15, 2, 270, 550, "open "); Char_ReFresh(&referee_recv_info->referee_id, UI_State_dyn[4]); + // 底盘功率显示,静态 + Char_Draw(&UI_State_sta[5], "ss5", UI_Graph_ADD, 7, UI_Color_Green, 18, 2, 620, 230, "Power:"); + Char_ReFresh(&referee_recv_info->referee_id, UI_State_sta[5]); + // 能量条框 + Rectangle_Draw(&UI_Energy[0], "ss6", UI_Graph_ADD, 7, UI_Color_Green, 2, 720, 140, 1220, 180); + UI_ReFresh(&referee_recv_info->referee_id, 1, UI_Energy[0]); + // 底盘功率显示,动态 - Char_Draw(&UI_State_dyn[5], "sd5", UI_Graph_ADD, 8, UI_Color_Green, 18, 2, 840, 210, "0000"); - Char_ReFresh(&referee_recv_info->referee_id, UI_State_dyn[5]); + Float_Draw(&UI_Energy[1], "sd5", UI_Graph_ADD, 8, UI_Color_Green, 18, 2, 2, 750, 230, 24000); + // 能量条初始状态 + Line_Draw(&UI_Energy[2], "sd6", UI_Graph_ADD, 8, UI_Color_Pink, 30, 720, 160, 1020, 160); + UI_ReFresh(&referee_recv_info->referee_id, 2, UI_Energy[1], UI_Energy[2]); } static uint8_t count = 0; @@ -123,6 +129,9 @@ static void robot_mode_change(Referee_Interactive_info_t *_Interactive_data) // _Interactive_data->shoot_mode = SHOOT_ON; _Interactive_data->friction_mode = FRICTION_ON; _Interactive_data->lid_mode = LID_OPEN; + _Interactive_data->Chassis_Power_Data.chassis_power_mx += 3.5; + if (_Interactive_data->Chassis_Power_Data.chassis_power_mx >= 18) + _Interactive_data->Chassis_Power_Data.chassis_power_mx = 0; break; } case 1: @@ -225,7 +234,7 @@ static void My_UI_Refresh(referee_info_t *referee_recv_info, Referee_Interactive Char_ReFresh(&referee_recv_info->referee_id, UI_State_dyn[2]); _Interactive_data->Referee_Interactive_Flag.shoot_flag = 0; } - + // friction if (_Interactive_data->Referee_Interactive_Flag.friction_flag == 1) { switch (_Interactive_data->friction_mode) @@ -244,7 +253,7 @@ static void My_UI_Refresh(referee_info_t *referee_recv_info, Referee_Interactive Char_ReFresh(&referee_recv_info->referee_id, UI_State_dyn[3]); _Interactive_data->Referee_Interactive_Flag.friction_flag = 0; } - + // lid if (_Interactive_data->Referee_Interactive_Flag.lid_flag == 1) { switch (_Interactive_data->lid_mode) @@ -263,6 +272,14 @@ static void My_UI_Refresh(referee_info_t *referee_recv_info, Referee_Interactive Char_ReFresh(&referee_recv_info->referee_id, UI_State_dyn[4]); _Interactive_data->Referee_Interactive_Flag.lid_flag = 0; } + // power + if (_Interactive_data->Referee_Interactive_Flag.Power_flag == 1) + { + Float_Draw(&UI_Energy[1], "sd5", UI_Graph_Change, 8, UI_Color_Green, 18, 2, 2, 750, 230, _Interactive_data->Chassis_Power_Data.chassis_power_mx * 1000); + Line_Draw(&UI_Energy[2], "sd6", UI_Graph_Change, 8, UI_Color_Pink, 30, 720, 160, (uint32_t)750 + _Interactive_data->Chassis_Power_Data.chassis_power_mx * 30, 160); + UI_ReFresh(&referee_recv_info->referee_id, 2, UI_Energy[1], UI_Energy[2]); + _Interactive_data->Referee_Interactive_Flag.Power_flag = 0; + } } /** @@ -302,4 +319,10 @@ static void Mode_Change_Check(Referee_Interactive_info_t *_Interactive_data) _Interactive_data->Referee_Interactive_Flag.lid_flag = 1; _Interactive_data->lid_last_mode = _Interactive_data->lid_mode; } + + if (_Interactive_data->Chassis_Power_Data.chassis_power_mx != _Interactive_data->Chassis_last_Power_Data.chassis_power_mx) + { + _Interactive_data->Referee_Interactive_Flag.Power_flag = 1; + _Interactive_data->Chassis_last_Power_Data.chassis_power_mx = _Interactive_data->Chassis_Power_Data.chassis_power_mx; + } } diff --git a/modules/referee/rm_referee.h b/modules/referee/rm_referee.h index 9db1748..1cf83b2 100644 --- a/modules/referee/rm_referee.h +++ b/modules/referee/rm_referee.h @@ -59,22 +59,20 @@ typedef struct { Referee_Interactive_Flag_t Referee_Interactive_Flag; // 为UI绘制以及交互数据所用 - Robot_Status_e Robot_Status; // 机器人状态 - App_Status_e App_Status; // 应用状态 chassis_mode_e chassis_mode; // 底盘模式 gimbal_mode_e gimbal_mode; // 云台模式 shoot_mode_e shoot_mode; // 发射模式设置 friction_mode_e friction_mode; // 摩擦轮关闭 lid_mode_e lid_mode; // 弹舱盖打开 - loader_mode_e loader_mode; // 单发...连发 Chassis_Power_Data_s Chassis_Power_Data; // 功率控制 // 上一次的模式,用于flag判断 - chassis_mode_e chassis_last_mode; // 底盘模式 - gimbal_mode_e gimbal_last_mode; // 云台模式 - shoot_mode_e shoot_last_mode; // 发射模式设置 - friction_mode_e friction_last_mode; // 摩擦轮关闭 - lid_mode_e lid_last_mode; // 弹舱盖打开 + chassis_mode_e chassis_last_mode; + gimbal_mode_e gimbal_last_mode; + shoot_mode_e shoot_last_mode; + friction_mode_e friction_last_mode; + lid_mode_e lid_last_mode; + Chassis_Power_Data_s Chassis_last_Power_Data; } Referee_Interactive_info_t;