diff --git a/HAL_N_Middlewares/Src/main.c b/HAL_N_Middlewares/Src/main.c
index fd640c3..a072fef 100644
--- a/HAL_N_Middlewares/Src/main.c
+++ b/HAL_N_Middlewares/Src/main.c
@@ -116,31 +116,31 @@ int main(void)
MX_USART6_UART_Init();
/* USER CODE BEGIN 2 */
RC_init(&huart3);
- can_instance_config can_config = {.can_handle = &hcan1,
- .tx_id = 1};
- Motor_Control_Setting_s motor_config = {.angle_feedback_source = MOTOR_FEED,
- .close_loop_type = SPEED_LOOP | CURRENT_LOOP,
- .speed_feedback_source = MOTOR_FEED,
- .reverse_flag = MOTOR_DIRECTION_NORMAL};
- Motor_Controller_Init_s controller_init = {.current_PID = {
- .Improve = 0,
- .Kp = 1,
- .Ki = 0,
- .Kd = 0,
- .DeadBand = 0,
- .MaxOut = 4000,
- },
- .speed_PID = {
- .Improve = 0,
- .Kp = 1,
- .Ki = 0,
- .Kd = 0,
- .DeadBand = 0,
- .MaxOut = 4000,
- }};
- Motor_Type_e type = M3508;
DWT_Init(168);
- dji_motor_instance *djimotor = DJIMotorInit(can_config, motor_config, controller_init, type);
+ Motor_Init_Config_s config = {
+ .motor_type = M3508,
+ .can_init_config = {
+ .can_handle = &hcan1,
+ .tx_id = 1},
+ .controller_setting_init_config = {.angle_feedback_source = MOTOR_FEED,
+ .close_loop_type = SPEED_LOOP | CURRENT_LOOP,
+ .speed_feedback_source = MOTOR_FEED,
+ .reverse_flag = MOTOR_DIRECTION_NORMAL},
+ .controller_param_init_config = {.current_PID = {
+ .Improve = 0,
+ .Kp = 1,
+ .Ki = 0,
+ .Kd = 0,
+ .DeadBand = 0,
+ .MaxOut = 4000},
+ .speed_PID = {
+ .Improve = 0,
+ .Kp = 1,
+ .Ki = 0,
+ .Kd = 0,
+ .DeadBand = 0,
+ .MaxOut = 4000}}};
+ dji_motor_instance *djimotor = DJIMotorInit(config);
/* USER CODE END 2 */
/* Call init function for freertos objects (in freertos.c) */
diff --git a/bsp/bsp_can.c b/bsp/bsp_can.c
index e1cbfee..104c075 100644
--- a/bsp/bsp_can.c
+++ b/bsp/bsp_can.c
@@ -57,7 +57,7 @@ static void CANServiceInit()
/* -----------------------two extern callable function -----------------------*/
-void CANRegister(can_instance *ins, can_instance_config config)
+void CANRegister(can_instance *ins, can_instance_config_s config)
{
static uint8_t idx;
if (!idx)
diff --git a/bsp/bsp_can.h b/bsp/bsp_can.h
index 35f1457..e6faf21 100644
--- a/bsp/bsp_can.h
+++ b/bsp/bsp_can.h
@@ -9,50 +9,44 @@
#define MX_CAN_FILTER_CNT (2 * 14) // temporarily useless
#define DEVICE_CAN_CNT 2 // CAN1,CAN2
-
-
/* can instance typedef, every module registered to CAN should have this variable */
typedef struct _
{
- CAN_HandleTypeDef* can_handle;
+ CAN_HandleTypeDef *can_handle;
CAN_TxHeaderTypeDef txconf;
uint32_t tx_id;
uint32_t tx_mailbox;
- uint8_t tx_buff[8];
+ uint8_t tx_buff[8];
uint8_t rx_buff[8];
uint32_t rx_id;
- void (*can_module_callback)(struct _*); // callback needs an instance to tell among registered ones
+ void (*can_module_callback)(struct _ *); // callback needs an instance to tell among registered ones
} can_instance;
-
/* this structure is used as initialization*/
-typedef struct
+typedef struct
{
- CAN_HandleTypeDef* can_handle;
+ CAN_HandleTypeDef *can_handle;
uint32_t tx_id;
uint32_t rx_id;
- void (*can_module_callback)(can_instance*);
-} can_instance_config;
+ void (*can_module_callback)(can_instance *);
+} can_instance_config_s;
/* module callback,which resolve protocol when new mesg arrives*/
-typedef void (*can_callback)(can_instance*);
-
+typedef void (*can_callback)(can_instance *);
/**
* @brief transmit mesg through CAN device
- *
+ *
* @param _instance can instance owned by module
*/
-void CANTransmit(can_instance* _instance);
-
+void CANTransmit(can_instance *_instance);
/**
* @brief Register a module to CAN service,remember to call this before using a CAN device
- *
+ *
* @param config init config
* @return can_instance* can instance owned by module
*/
-void CANRegister(can_instance* instance, can_instance_config config);
-
+void CANRegister(can_instance *instance, can_instance_config_s config);
#endif
diff --git a/modules/master_machine/湖南大学RoboMaster电控组通信协议.md b/modules/master_machine/湖南大学RoboMaster电控组通信协议.md
index 149a6d9..5becc33 100644
--- a/modules/master_machine/湖南大学RoboMaster电控组通信协议.md
+++ b/modules/master_machine/湖南大学RoboMaster电控组通信协议.md
@@ -1,7 +1,16 @@
# 湖南大学RoboMaster电控组通信协议
+
Seasky LIUWei
+
+modified by neozng1@hnu.edu.cn
+
可用于视觉,以及其他自研模块(仅限串口通信)
+> TODO:
+>
+> 1. 利用F4自带的硬件CRC模块计算校验码,提高速度
+> 2. 增加更多的数据类型支持,使得数据类型也为可配置的
+
## 一、串口配置
通信方式是串口,配置为波特率 115200,8 位数据位,1 位停止位,无硬件流控,无校验位。
diff --git a/modules/motor/HT04.c b/modules/motor/HT04.c
index 38aa69d..db4a7e8 100644
--- a/modules/motor/HT04.c
+++ b/modules/motor/HT04.c
@@ -1,63 +1,63 @@
#include "HT04.h"
#include "memory.h"
-joint_instance* joint_motor_info[HT_MOTOR_CNT];
+joint_instance *joint_motor_info[HT_MOTOR_CNT];
static uint16_t float_to_uint(float x, float x_min, float x_max, uint8_t bits)
{
float span = x_max - x_min;
float offset = x_min;
- return (uint16_t) ((x-offset)*((float)((1<motor_can_instace==motor_instance)
+ if (joint_motor_info[i]->motor_can_instace == motor_instance)
{
tmp = (motor_instance->rx_buff[1] << 8) | motor_instance->rx_buff[2];
- joint_motor_info[i]->last_ecd=joint_motor_info[i]->ecd;
- joint_motor_info[i]->ecd=uint_to_float(tmp,P_MAX,P_MIN,16);
+ joint_motor_info[i]->last_ecd = joint_motor_info[i]->ecd;
+ joint_motor_info[i]->ecd = uint_to_float(tmp, P_MAX, P_MIN, 16);
tmp = (motor_instance->rx_buff[3] << 4) | (motor_instance->rx_buff[4] >> 4);
- joint_motor_info[i]->speed_rpm= uint_to_float(tmp,V_MAX,V_MIN,12);
- tmp=((motor_instance->rx_buff[4]&0xf)<<8) | motor_instance->rx_buff[5];
- joint_motor_info[i]->given_current=uint_to_float(tmp,T_MAX,T_MIN,12);
+ joint_motor_info[i]->speed_rpm = uint_to_float(tmp, V_MAX, V_MIN, 12);
+ tmp = ((motor_instance->rx_buff[4] & 0xf) << 8) | motor_instance->rx_buff[5];
+ joint_motor_info[i]->given_current = uint_to_float(tmp, T_MAX, T_MIN, 12);
break;
}
}
}
-joint_instance* HTMotorInit(can_instance_config config)
+joint_instance *HTMotorInit(can_instance_config_s config)
{
static uint8_t idx;
- joint_motor_info[idx]=(joint_instance*)malloc(sizeof(joint_instance));
- CANRegister(joint_motor_info[idx++]->motor_can_instace,config);
+ joint_motor_info[idx] = (joint_instance *)malloc(sizeof(joint_instance));
+ CANRegister(joint_motor_info[idx++]->motor_can_instace, config);
return joint_motor_info[idx++];
}
-void JointControl(joint_instance* _instance,float current)
+void JointControl(joint_instance *_instance, float current)
{
uint16_t tmp;
- LIMIT_MIN_MAX(current, T_MIN, T_MAX);
+ LIMIT_MIN_MAX(current, T_MIN, T_MAX);
tmp = float_to_uint(current, T_MIN, T_MAX, 12);
- _instance->motor_can_instace->rx_buff[6] = tmp>>8;
- _instance->motor_can_instace->rx_buff[7] = tmp&0xff;
+ _instance->motor_can_instace->rx_buff[6] = tmp >> 8;
+ _instance->motor_can_instace->rx_buff[7] = tmp & 0xff;
CANTransmit(_instance->motor_can_instace);
}
-void SetJointMode(joint_mode cmd,joint_instance* _instance)
+void SetJointMode(joint_mode cmd, joint_instance *_instance)
{
static uint8_t buf[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
- buf[7]=(uint8_t)cmd;
- memcpy(_instance->motor_can_instace->rx_buff,buf,8*sizeof(uint8_t));
+ buf[7] = (uint8_t)cmd;
+ memcpy(_instance->motor_can_instace->rx_buff, buf, 8 * sizeof(uint8_t));
CANTransmit(_instance->motor_can_instace);
}
diff --git a/modules/motor/HT04.h b/modules/motor/HT04.h
index 09965a8..5da5f1f 100644
--- a/modules/motor/HT04.h
+++ b/modules/motor/HT04.h
@@ -7,14 +7,14 @@
#define HT_MOTOR_CNT 4
-#define P_MIN -95.5f // Radians
+#define P_MIN -95.5f // Radians
#define P_MAX 95.5f
-#define V_MIN -45.0f // Rad/s
+#define V_MIN -45.0f // Rad/s
#define V_MAX 45.0f
#define T_MIN -18.0f
#define T_MAX 18.0f
-typedef struct //HT04
+typedef struct // HT04
{
float last_ecd;
float ecd;
@@ -22,20 +22,20 @@ typedef struct //HT04
float given_current;
PID_t pid;
- can_instance* motor_can_instace;
+ can_instance *motor_can_instace;
} joint_instance;
typedef enum
{
- CMD_MOTOR_MODE = 0xfc,
- CMD_RESET_MODE = 0xfd,
+ CMD_MOTOR_MODE = 0xfc,
+ CMD_RESET_MODE = 0xfd,
CMD_ZERO_POSITION = 0xfe
} joint_mode;
-joint_instance* HTMotorInit(can_instance_config config);
+joint_instance *HTMotorInit(can_instance_config_s config);
-void JointControl(joint_instance* _instance,float current);
+void JointControl(joint_instance *_instance, float current);
-void SetJointMode(joint_mode cmd,joint_instance* _instance);
+void SetJointMode(joint_mode cmd, joint_instance *_instance);
#endif // !HT04_H#define HT04_H
\ No newline at end of file
diff --git a/modules/motor/LK9025.c b/modules/motor/LK9025.c
index dc24273..7baa307 100644
--- a/modules/motor/LK9025.c
+++ b/modules/motor/LK9025.c
@@ -18,7 +18,7 @@ static void DecodeDriven(can_instance *_instance)
}
}
-driven_instance *LKMotroInit(can_instance_config config)
+driven_instance *LKMotroInit(can_instance_config_s config)
{
static uint8_t idx;
driven_motor_info[idx] = (driven_instance *)malloc(sizeof(driven_instance));
diff --git a/modules/motor/LK9025.h b/modules/motor/LK9025.h
index 57e0a59..e3092fc 100644
--- a/modules/motor/LK9025.h
+++ b/modules/motor/LK9025.h
@@ -9,10 +9,9 @@
#define I_MIN -2000
#define I_MAX 2000
-#define LIMIT_MIN_MAX(x,min,max) (x) = (((x)<=(min))?(min):(((x)>=(max))?(max):(x)))
+#define LIMIT_MIN_MAX(x, min, max) (x) = (((x) <= (min)) ? (min) : (((x) >= (max)) ? (max) : (x)))
-
-typedef struct //9025
+typedef struct // 9025
{
uint16_t last_ecd;
uint16_t ecd;
@@ -20,8 +19,8 @@ typedef struct //9025
int16_t given_current;
uint8_t temperate;
- PID_t* pid;
- can_instance* motor_can_instance;
+ PID_t *pid;
+ can_instance *motor_can_instance;
} driven_instance;
@@ -30,10 +29,10 @@ typedef enum
unused = 0,
} driven_mode;
-driven_instance* LKMotroInit(can_instance_config config);
+driven_instance *LKMotroInit(can_instance_config_s config);
-void DrivenControl(int16_t motor1_current,int16_t motor2_current);
+void DrivenControl(int16_t motor1_current, int16_t motor2_current);
-void SetDrivenMode(driven_mode cmd,uint16_t motor_id);
+void SetDrivenMode(driven_mode cmd, uint16_t motor_id);
#endif // LK9025_H
diff --git a/modules/motor/dji_motor.c b/modules/motor/dji_motor.c
index 4ef9146..a17ca4b 100644
--- a/modules/motor/dji_motor.c
+++ b/modules/motor/dji_motor.c
@@ -48,7 +48,7 @@ static void IDcrash_Handler(uint8_t conflict_motor_idx, uint8_t temp_motor_idx)
*
* @param config
*/
-static void MotorSenderGrouping(can_instance_config *config)
+static void MotorSenderGrouping(can_instance_config_s *config)
{
uint8_t motor_id = config->tx_id - 1; // 下标从零开始,先减一方便赋值
uint8_t motor_send_num;
@@ -146,29 +146,26 @@ static void DecodeDJIMotor(can_instance *_instance)
}
// 电机初始化,返回一个电机实例
-dji_motor_instance *DJIMotorInit(can_instance_config can_config,
- Motor_Control_Setting_s motor_setting,
- Motor_Controller_Init_s controller_init,
- Motor_Type_e type)
+dji_motor_instance *DJIMotorInit(Motor_Init_Config_s config)
{
dji_motor_info[idx] = (dji_motor_instance *)malloc(sizeof(dji_motor_instance));
memset(dji_motor_info[idx], 0, sizeof(dji_motor_instance));
// motor basic setting
- dji_motor_info[idx]->motor_type = type;
- dji_motor_info[idx]->motor_settings = motor_setting;
+ dji_motor_info[idx]->motor_type = config.motor_type;
+ dji_motor_info[idx]->motor_settings = config.controller_setting_init_config;
// motor controller init
- PID_Init(&dji_motor_info[idx]->motor_controller.current_PID, &controller_init.current_PID);
- PID_Init(&dji_motor_info[idx]->motor_controller.speed_PID, &controller_init.speed_PID);
- PID_Init(&dji_motor_info[idx]->motor_controller.angle_PID, &controller_init.angle_PID);
- dji_motor_info[idx]->motor_controller.other_angle_feedback_ptr = controller_init.other_angle_feedback_ptr;
- dji_motor_info[idx]->motor_controller.other_speed_feedback_ptr = controller_init.other_speed_feedback_ptr;
+ PID_Init(&dji_motor_info[idx]->motor_controller.current_PID, &config.controller_param_init_config.current_PID);
+ PID_Init(&dji_motor_info[idx]->motor_controller.speed_PID, &config.controller_param_init_config.speed_PID);
+ PID_Init(&dji_motor_info[idx]->motor_controller.angle_PID, &config.controller_param_init_config.angle_PID);
+ dji_motor_info[idx]->motor_controller.other_angle_feedback_ptr = config.controller_param_init_config.other_angle_feedback_ptr;
+ dji_motor_info[idx]->motor_controller.other_speed_feedback_ptr = config.controller_param_init_config.other_speed_feedback_ptr;
// group motors, because 4 motors share the same CAN control message
- MotorSenderGrouping(&can_config);
+ MotorSenderGrouping(&config.can_init_config);
// register motor to CAN bus
- can_config.can_module_callback = DecodeDJIMotor; // set callback
- CANRegister(&dji_motor_info[idx]->motor_can_instance, can_config);
+ config.can_init_config.can_module_callback = DecodeDJIMotor; // set callback
+ CANRegister(&dji_motor_info[idx]->motor_can_instance, config.can_init_config);
return dji_motor_info[idx++];
}
diff --git a/modules/motor/dji_motor.h b/modules/motor/dji_motor.h
index bc65703..cf4b3e8 100644
--- a/modules/motor/dji_motor.h
+++ b/modules/motor/dji_motor.h
@@ -75,23 +75,12 @@ typedef struct
*
* @attention M3508和M2006的反馈报文都是0x200+id,而GM6020的反馈是0x204+id,请注意前两者和后者的id不要冲突.
* 如果产生冲突,在初始化电机的时候会进入IDcrash_Handler(),可以通过debug来判断是否出现冲突.
- *
- * @param config 电机can设置,对于DJI电机仅需要将tx_id设置为电调闪动次数(c620,615,610)或拨码开关的值(GM6020)
- * 你不需要自己查表计算发送和接收id,我们会帮你处理好!
- *
- * @param motor_setting 电机的控制设置,包括是否反转,闭环类型和是否使用编码器之外的反馈值
- *
- * @param controller_init 电机控制器的参数设置,包括其他的反馈来源数据指针和三环PID的参数.
- * 如果不需要其他数据来源或不需要三个环,将不需要指针置为NULL即可
- *
- * @param type 电机的类型枚举,包括m2006,m3508和gm6020
- *
- * @return dji_motor_instance* 返回一个电机实例指针给应用,方便其对电机的参考值进行设置,即调用DJIMotorSetRef()
+ *
+ * @param config 电机初始化结构体,包含了电机控制设置,电机PID参数设置,电机类型以及电机挂载的CAN设置
+ *
+ * @return dji_motor_instance*
*/
-dji_motor_instance *DJIMotorInit(can_instance_config config,
- Motor_Control_Setting_s motor_setting,
- Motor_Controller_Init_s controller_init,
- Motor_Type_e type);
+dji_motor_instance *DJIMotorInit(Motor_Init_Config_s config);
/**
* @brief 被application层的应用调用,给电机设定参考值.
diff --git a/modules/motor/dji_motor.md b/modules/motor/dji_motor.md
index 77924b4..a931ce8 100644
--- a/modules/motor/dji_motor.md
+++ b/modules/motor/dji_motor.md
@@ -20,9 +20,14 @@ dji_motor模块对DJI智能电机,包括M2006,M3508以及GM6020进行了详
初始化电机时,你需要传入的参数包括:
-- 电机挂载的总线设置:CAN1 or CAN2,以及电机的id
+- **电机挂载的CAN总线设置**,CAN1 or CAN2,以及电机的id,使用`can_instance_config_s`封装,只需要设置这两个参数:
-- 电机类型:
+ ```c
+ CAN_HandleTypeDef *can_handle;
+ uint32_t tx_id; // tx_id设置为电机id,不需要查说明书计算,直接为电调的闪动次数或拨码开关值,为1-8
+ ```
+
+- **电机类型**,使用`Motor_Type_e`:
```c
GM6020 = 0
@@ -30,74 +35,122 @@ dji_motor模块对DJI智能电机,包括M2006,M3508以及GM6020进行了详
M2006 = 2
```
-- 闭环类型
+- **电机控制设置**
- ```c
- OPEN_LOOP
- CURRENT_LOOP
- SPEED_LOOP
- ANGLE_LOOP
- CURRENT_LOOP| SPEED_LOOP // 同时对电流和速度闭环
- SPEED_LOOP | ANGLE_LOOP // 同时对速度和位置闭环
- CURRENT_LOOP| SPEED_LOOP |ANGLE_LOOP // 三环全开
- ```
+ - 闭环类型
-- 是否反转
+ ```c
+ OPEN_LOOP
+ CURRENT_LOOP
+ SPEED_LOOP
+ ANGLE_LOOP
+ CURRENT_LOOP| SPEED_LOOP // 同时对电流和速度闭环
+ SPEED_LOOP | ANGLE_LOOP // 同时对速度和位置闭环
+ CURRENT_LOOP| SPEED_LOOP |ANGLE_LOOP // 三环全开
+ ```
- ```c
- MOTOR_DIRECTION_NORMAL
- MOTOR_DIRECTION_REVERSE
- ```
+ - 是否反转
-- 是否其他反馈来源,以及他们对应的数据指针(如果有的话)
+ ```c
+ MOTOR_DIRECTION_NORMAL
+ MOTOR_DIRECTION_REVERSE
+ ```
- ```c
- MOTOR_FEED = 0
- OTHER_FEED = 1
- ---
- float *other_angle_feedback_ptr
- float *other_speed_feedback_ptr
- // 电流只能从电机传感器获得所以无法设置其他来源
- ```
+ - 是否其他反馈来源,以及他们对应的数据指针(如果有的话)
-- 每个环的PID参数以及是否使用改进功能
+ ```c
+ MOTOR_FEED = 0
+ OTHER_FEED = 1
+ ---
+
+ // 电流只能从电机传感器获得所以无法设置其他来源
+ ```
+
+ - 每个环的PID参数以及是否使用改进功能,以及其他反馈来源指针(如果在上一步启用了其他数据来源)
+
+ ```c
+ typedef struct // config parameter
+ {
+ float Kp;
+ float Ki;
+ float Kd;
+
+ float MaxOut; // 输出限幅
+ // 以下是优化参数
+ float IntegralLimit; // 积分限幅
+ float DeadBand; // 死区
+ float CoefA; // For Changing Integral
+ float CoefB; // ITerm = Err*((A-abs(err)+B)/A) when B<|err|motor_measure->speed_rpm;
+...
+```
+
+
+
***现在,忘记PID的计算和发送、接收以及协议解析,专注于模块之间的逻辑交互吧。***
diff --git a/modules/motor/motor_def.h b/modules/motor/motor_def.h
index bd68887..a46073d 100644
--- a/modules/motor/motor_def.h
+++ b/modules/motor/motor_def.h
@@ -94,4 +94,13 @@ typedef struct
} Motor_Controller_Init_s;
+/* 用于初始化CAN电机的结构体,各类电机通用 */
+typedef struct
+{
+ Motor_Controller_Init_s controller_param_init_config;
+ Motor_Control_Setting_s controller_setting_init_config;
+ Motor_Type_e motor_type;
+ can_instance_config_s can_init_config;
+} Motor_Init_Config_s;
+
#endif // !MOTOR_DEF_H