mirror of
https://gitee.com/dlmu-cone/half-steering-basic-framework
synced 2026-10-23 17:42:20 +08:00
Compare commits
17 Commits
v1.0
...
dev-vision
| Author | SHA1 | Date | |
|---|---|---|---|
| a6d9bfc2b0 | |||
|
|
3ebb57d86b | ||
|
|
4ac9cba1d7 | ||
|
|
3afa755680 | ||
|
|
fbc83771a8 | ||
|
|
52e8018b2c | ||
|
|
fa85ac8e2a | ||
|
|
4d20b137da | ||
|
|
8a96476007 | ||
|
|
91588795c2 | ||
|
|
0e711f1fe8 | ||
|
|
09802b3daa | ||
| 69e97cbefa | |||
| 5d32411da6 | |||
| 6d1de50957 | |||
| 93d26b601d | |||
| d6872ad1e8 |
@@ -113,14 +113,14 @@ void ChassisInit()
|
|||||||
.can_init_config.can_handle = &hcan1,
|
.can_init_config.can_handle = &hcan1,
|
||||||
.controller_param_init_config = {
|
.controller_param_init_config = {
|
||||||
.angle_PID = {
|
.angle_PID = {
|
||||||
.Kp = 12,
|
.Kp = 35,
|
||||||
.Ki = 0.2,
|
.Ki = 0.25,
|
||||||
.Kd = 0,
|
.Kd = 0,
|
||||||
.CoefA = 3,
|
.CoefA = 3,
|
||||||
.CoefB = 0.1,
|
.CoefB = 0.1,
|
||||||
.Improve = PID_Trapezoid_Intergral | PID_Integral_Limit | PID_Derivative_On_Measurement | PID_DerivativeFilter | PID_ChangingIntegrationRate,
|
.Improve = PID_Trapezoid_Intergral | PID_Integral_Limit | PID_Derivative_On_Measurement | PID_DerivativeFilter | PID_ChangingIntegrationRate,
|
||||||
.IntegralLimit = 1000,
|
.IntegralLimit = 1500,
|
||||||
.MaxOut = 5000,
|
.MaxOut = 6000,
|
||||||
.Derivative_LPF_RC = 0.001,
|
.Derivative_LPF_RC = 0.001,
|
||||||
.DeadBand = 0.5,
|
.DeadBand = 0.5,
|
||||||
},
|
},
|
||||||
@@ -151,7 +151,7 @@ void ChassisInit()
|
|||||||
motor_steering_lb = DJIMotorInit(&chassis_motor_steering_config);
|
motor_steering_lb = DJIMotorInit(&chassis_motor_steering_config);
|
||||||
|
|
||||||
PID_Init_Config_s chassis_follow_pid_conf = {
|
PID_Init_Config_s chassis_follow_pid_conf = {
|
||||||
.Kp = 1.05, // 6
|
.Kp = 0.95, // 6
|
||||||
.Ki = 0,
|
.Ki = 0,
|
||||||
.Kd = 0.1, // 0.495
|
.Kd = 0.1, // 0.495
|
||||||
.DeadBand = 0.5f,// 启用死区,值为0.5度
|
.DeadBand = 0.5f,// 启用死区,值为0.5度
|
||||||
@@ -170,11 +170,14 @@ void ChassisInit()
|
|||||||
|
|
||||||
SuperCap_Init_Config_s cap_conf = {
|
SuperCap_Init_Config_s cap_conf = {
|
||||||
.can_config = {
|
.can_config = {
|
||||||
.can_handle = &hcan2,
|
.can_handle = &hcan1, // 保持你原有的硬件CAN接口不变
|
||||||
.tx_id = 0x302, // 超级电容默认接收id
|
.tx_id = 0x001, // C板发给超级电容的ID
|
||||||
.rx_id = 0x301, // 超级电容默认发送id,注意tx和rx在其他人看来是反的
|
.rx_id = 0x100, // 超级电容发给C板的ID
|
||||||
}};
|
}};
|
||||||
cap = SuperCapInit(&cap_conf); // 超级电容初始化
|
cap = SuperCapInit(&cap_conf); // 超级电容初始化 todo 控制
|
||||||
|
|
||||||
|
// (新增)设置超级电容功率补偿,例如补偿5W,可根据实际需求调整 todo 控制
|
||||||
|
SuperCapSetPowerOffset(cap, 5);
|
||||||
|
|
||||||
// 发布订阅初始化,如果为双板,则需要can comm来传递消息
|
// 发布订阅初始化,如果为双板,则需要can comm来传递消息
|
||||||
#ifdef CHASSIS_BOARD
|
#ifdef CHASSIS_BOARD
|
||||||
|
|||||||
@@ -203,14 +203,13 @@ static void RemoteControlSet()
|
|||||||
// 左侧开关状态为[下],或视觉未识别到目标,纯遥控器拨杆控制
|
// 左侧开关状态为[下],或视觉未识别到目标,纯遥控器拨杆控制
|
||||||
if (switch_is_down(rc_data[TEMP].rc.switch_left) )
|
if (switch_is_down(rc_data[TEMP].rc.switch_left) )
|
||||||
{ // 按照摇杆的输出大小进行角度增量,增益系数需调整
|
{ // 按照摇杆的输出大小进行角度增量,增益系数需调整
|
||||||
gimbal_cmd_send.yaw += 0.005f * (float)rc_data[TEMP].rc.rocker_l_;
|
gimbal_cmd_send.yaw += 0.005f * (float)rc_data[TEMP].rc.rocker_r_;
|
||||||
gimbal_cmd_send.pitch += 0.001f * (float)rc_data[TEMP].rc.rocker_l1;
|
gimbal_cmd_send.pitch += 0.001f * (float)rc_data[TEMP].rc.rocker_r1;
|
||||||
}
|
}
|
||||||
// 云台软件限位
|
// 云台软件限位
|
||||||
|
|
||||||
// 底盘参数,目前没有加入小陀螺(调试似乎暂时没有必要),系数需要调整
|
// 底盘参数,目前没有加入小陀螺(调试似乎暂时没有必要),系数需要调整
|
||||||
chassis_cmd_send.vx = 0.15f * (float)rc_data[TEMP].rc.rocker_r_; // _水平方向
|
chassis_cmd_send.vx = 0.15f * (float)rc_data[TEMP].rc.rocker_l_; // _水平方向
|
||||||
chassis_cmd_send.vy = 0.15f * (float)rc_data[TEMP].rc.rocker_r1; // 1数值方向
|
chassis_cmd_send.vy = 0.15f * (float)rc_data[TEMP].rc.rocker_l1; // 1数值方向
|
||||||
|
|
||||||
// // 发射参数
|
// // 发射参数
|
||||||
// if (switch_is_up(rc_data[TEMP].rc.switch_right)) // 右侧开关状态[上],弹舱打开
|
// if (switch_is_up(rc_data[TEMP].rc.switch_right)) // 右侧开关状态[上],弹舱打开
|
||||||
|
|||||||
@@ -26,12 +26,12 @@ void GimbalInit()
|
|||||||
},
|
},
|
||||||
.controller_param_init_config = {
|
.controller_param_init_config = {
|
||||||
.angle_PID = {
|
.angle_PID = {
|
||||||
//.Kp = 0.685, // 8
|
//.Kp = 0.785, // 8
|
||||||
.Kp = 0.685, // 8
|
.Kp = 3, // 8
|
||||||
//.Ki = 0.315,
|
//.Ki = 0.315,
|
||||||
.Ki = 0.25,
|
.Ki = 0.45,
|
||||||
.Kd = 0.022,
|
.Kd = 0.03,
|
||||||
//.DeadBand = 0.1,
|
//.DeadBand = 0.1
|
||||||
.Improve = PID_Trapezoid_Intergral | PID_Integral_Limit | PID_Derivative_On_Measurement | PID_DerivativeFilter | PID_ChangingIntegrationRate,
|
.Improve = PID_Trapezoid_Intergral | PID_Integral_Limit | PID_Derivative_On_Measurement | PID_DerivativeFilter | PID_ChangingIntegrationRate,
|
||||||
.IntegralLimit = 1060,
|
.IntegralLimit = 1060,
|
||||||
.CoefA = 20,
|
.CoefA = 20,
|
||||||
@@ -40,9 +40,9 @@ void GimbalInit()
|
|||||||
.Derivative_LPF_RC = 0.001
|
.Derivative_LPF_RC = 0.001
|
||||||
},
|
},
|
||||||
.speed_PID = {
|
.speed_PID = {
|
||||||
.Kp = 8000, // 50
|
.Kp = 500, // 50
|
||||||
//.Kp = 5000, // 50
|
//.Kp = 5000, // 50
|
||||||
.Ki = 5000, // 200
|
.Ki = 2000, // 200
|
||||||
.Kd = 0,
|
.Kd = 0,
|
||||||
.CoefB = 1,
|
.CoefB = 1,
|
||||||
.CoefA = 10,
|
.CoefA = 10,
|
||||||
@@ -66,7 +66,7 @@ void GimbalInit()
|
|||||||
Motor_Init_Config_s pitch_config = {
|
Motor_Init_Config_s pitch_config = {
|
||||||
.can_init_config = {
|
.can_init_config = {
|
||||||
.can_handle = &hcan2,
|
.can_handle = &hcan2,
|
||||||
.tx_id = 4,
|
.tx_id = 4,//2
|
||||||
},
|
},
|
||||||
.controller_param_init_config = {
|
.controller_param_init_config = {
|
||||||
.angle_PID = {
|
.angle_PID = {
|
||||||
@@ -83,7 +83,7 @@ void GimbalInit()
|
|||||||
.Kd = 0, // 0
|
.Kd = 0, // 0
|
||||||
.Improve = PID_Trapezoid_Intergral | PID_Integral_Limit | PID_Derivative_On_Measurement,
|
.Improve = PID_Trapezoid_Intergral | PID_Integral_Limit | PID_Derivative_On_Measurement,
|
||||||
.IntegralLimit = 2500,
|
.IntegralLimit = 2500,
|
||||||
.MaxOut = 20000,
|
.MaxOut = 8000,//20000
|
||||||
},
|
},
|
||||||
.other_angle_feedback_ptr = &gimba_IMU_data->Pitch,
|
.other_angle_feedback_ptr = &gimba_IMU_data->Pitch,
|
||||||
// 还需要增加角速度额外反馈指针,注意方向,ins_task.md中有c板的bodyframe坐标系说明
|
// 还需要增加角速度额外反馈指针,注意方向,ins_task.md中有c板的bodyframe坐标系说明
|
||||||
@@ -96,7 +96,7 @@ void GimbalInit()
|
|||||||
.close_loop_type = SPEED_LOOP | ANGLE_LOOP,
|
.close_loop_type = SPEED_LOOP | ANGLE_LOOP,
|
||||||
.motor_reverse_flag = MOTOR_DIRECTION_NORMAL,
|
.motor_reverse_flag = MOTOR_DIRECTION_NORMAL,
|
||||||
},
|
},
|
||||||
.motor_type = M3508,
|
.motor_type = DM4310,
|
||||||
};
|
};
|
||||||
// 电机对total_angle闭环,上电时为零,会保持静止,收到遥控器数据再动
|
// 电机对total_angle闭环,上电时为零,会保持静止,收到遥控器数据再动
|
||||||
yaw_motor = DJIMotorInit(&yaw_config);
|
yaw_motor = DJIMotorInit(&yaw_config);
|
||||||
@@ -132,7 +132,18 @@ void GimbalTask()
|
|||||||
DJIMotorChangeFeed(pitch_motor, SPEED_LOOP, OTHER_FEED);
|
DJIMotorChangeFeed(pitch_motor, SPEED_LOOP, OTHER_FEED);
|
||||||
DJIMotorSetRef(yaw_motor, gimbal_cmd_recv.yaw); // yaw和pitch会在robot_cmd中处理好多圈和单圈
|
DJIMotorSetRef(yaw_motor, gimbal_cmd_recv.yaw); // yaw和pitch会在robot_cmd中处理好多圈和单圈
|
||||||
DJIMotorSetRef(pitch_motor, gimbal_cmd_recv.pitch);
|
DJIMotorSetRef(pitch_motor, gimbal_cmd_recv.pitch);
|
||||||
break;
|
// // 根据底盘速度进行补偿,保持云台稳定
|
||||||
|
// // 这里简化处理,实际应用中可能需要更复杂的补偿算法
|
||||||
|
// float yaw_ref = gimbal_cmd_recv.yaw;
|
||||||
|
// float pitch_ref = gimbal_cmd_recv.pitch;
|
||||||
|
//
|
||||||
|
// // 当底盘移动时,云台需要保持相对稳定
|
||||||
|
// // 这里可以根据底盘速度调整云台的控制参考值
|
||||||
|
// // 例如,当底盘向前移动时,云台可能需要稍微向后调整以保持稳定
|
||||||
|
//
|
||||||
|
// DJIMotorSetRef(yaw_motor, yaw_ref); // yaw和pitch会在robot_cmd中处理好多圈和单圈
|
||||||
|
// DJIMotorSetRef(pitch_motor, pitch_ref);
|
||||||
|
break;
|
||||||
// 云台自由模式,使用编码器反馈,底盘和云台分离,仅云台旋转,一般用于调整云台姿态(英雄吊射等)/能量机关
|
// 云台自由模式,使用编码器反馈,底盘和云台分离,仅云台旋转,一般用于调整云台姿态(英雄吊射等)/能量机关
|
||||||
case GIMBAL_FREE_MODE: // 后续删除,或加入云台追地盘的跟随模式(响应速度更快)
|
case GIMBAL_FREE_MODE: // 后续删除,或加入云台追地盘的跟随模式(响应速度更快)
|
||||||
DJIMotorEnable(yaw_motor);
|
DJIMotorEnable(yaw_motor);
|
||||||
@@ -159,4 +170,13 @@ void GimbalTask()
|
|||||||
// gimbal_feedback_data.yaw_motor_total_angle = gimba_IMU_data->YawTotalAngle;
|
// gimbal_feedback_data.yaw_motor_total_angle = gimba_IMU_data->YawTotalAngle;
|
||||||
// 推送消息
|
// 推送消息
|
||||||
PubPushMessage(gimbal_pub, (void *)&gimbal_feedback_data);
|
PubPushMessage(gimbal_pub, (void *)&gimbal_feedback_data);
|
||||||
}
|
}
|
||||||
|
// /**
|
||||||
|
// * @brief 获取云台IMU数据指针
|
||||||
|
// *
|
||||||
|
// * @return attitude_t* 云台IMU数据指针
|
||||||
|
// */
|
||||||
|
// attitude_t *GetGimbalIMUData()
|
||||||
|
// {
|
||||||
|
// return gimba_IMU_data;
|
||||||
|
// }
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#ifndef GIMBAL_H
|
#ifndef GIMBAL_H
|
||||||
#define GIMBAL_H
|
#define GIMBAL_H
|
||||||
|
#include "../modules/imu/ins_task.h"
|
||||||
/**
|
/**
|
||||||
* @brief 初始化云台,会被RobotInit()调用
|
* @brief 初始化云台,会被RobotInit()调用
|
||||||
*
|
*
|
||||||
@@ -9,8 +9,8 @@ void GimbalInit();
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 云台任务
|
* @brief 云台任务
|
||||||
*
|
* @return attitude_t* 云台IMU数据指针
|
||||||
*/
|
*/
|
||||||
void GimbalTask();
|
void GimbalTask();
|
||||||
|
//attitude_t *GetGimbalIMUData();
|
||||||
#endif // GIMBAL_H
|
#endif // GIMBAL_H
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
/* 机器人重要参数定义,注意根据不同机器人进行修改,浮点数需要以.0或f结尾,无符号以u结尾 */
|
/* 机器人重要参数定义,注意根据不同机器人进行修改,浮点数需要以.0或f结尾,无符号以u结尾 */
|
||||||
// 云台参数
|
// 云台参数
|
||||||
#define YAW_CHASSIS_ALIGN_ECD 3938 // 云台和底盘对齐指向相同方向时的电机编码器值,若对云台有机械改动需要修改
|
#define YAW_CHASSIS_ALIGN_ECD 1190 // 云台和底盘对齐指向相同方向时的电机编码器值,若对云台有机械改动需要修改
|
||||||
#define YAW_ECD_GREATER_THAN_4096 0 // ALIGN_ECD值是否大于4096,是为1,否为0;用于计算云台偏转角度
|
#define YAW_ECD_GREATER_THAN_4096 0 // ALIGN_ECD值是否大于4096,是为1,否为0;用于计算云台偏转角度
|
||||||
#define PITCH_HORIZON_ECD 3412 // 云台处于水平位置时编码器值,若对云台有机械改动需要修改
|
#define PITCH_HORIZON_ECD 3412 // 云台处于水平位置时编码器值,若对云台有机械改动需要修改
|
||||||
#define PITCH_MAX_ANGLE 0 // 云台竖直方向最大角度 (注意反馈如果是陀螺仪,则填写陀螺仪的角度)
|
#define PITCH_MAX_ANGLE 0 // 云台竖直方向最大角度 (注意反馈如果是陀螺仪,则填写陀螺仪的角度)
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ void ShootInit()
|
|||||||
.close_loop_type = CURRENT_LOOP | SPEED_LOOP,
|
.close_loop_type = CURRENT_LOOP | SPEED_LOOP,
|
||||||
.motor_reverse_flag = MOTOR_DIRECTION_NORMAL, // 注意方向设置为拨盘的拨出的击发方向
|
.motor_reverse_flag = MOTOR_DIRECTION_NORMAL, // 注意方向设置为拨盘的拨出的击发方向
|
||||||
},
|
},
|
||||||
.motor_type = M3508 // 英雄使用m3508
|
.motor_type = M2006 // 英雄使用m3508
|
||||||
};
|
};
|
||||||
loader = DJIMotorInit(&loader_config);
|
loader = DJIMotorInit(&loader_config);
|
||||||
|
|
||||||
|
|||||||
@@ -63,8 +63,8 @@ static void f_Integral_Limit(PIDInstance *pid)
|
|||||||
// 微分先行(仅使用反馈值而不计参考输入的微分)
|
// 微分先行(仅使用反馈值而不计参考输入的微分)
|
||||||
static void f_Derivative_On_Measurement(PIDInstance *pid)
|
static void f_Derivative_On_Measurement(PIDInstance *pid)
|
||||||
{
|
{
|
||||||
pid->Dout = pid->Kd * (pid->Last_Measure - pid->Measure) / pid->dt;
|
pid->Dout = pid->Kd * (pid->Last_Measure - pid->Measure) / pid->dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 微分滤波(采集微分时,滤除高频噪声)
|
// 微分滤波(采集微分时,滤除高频噪声)
|
||||||
static void f_Derivative_Filter(PIDInstance *pid)
|
static void f_Derivative_Filter(PIDInstance *pid)
|
||||||
@@ -172,8 +172,8 @@ float PIDCalculate(PIDInstance *pid, float measure, float ref)
|
|||||||
if (pid->Improve & PID_ChangingIntegrationRate)
|
if (pid->Improve & PID_ChangingIntegrationRate)
|
||||||
f_Changing_Integration_Rate(pid);
|
f_Changing_Integration_Rate(pid);
|
||||||
// 微分先行
|
// 微分先行
|
||||||
if (pid->Improve & PID_Derivative_On_Measurement)
|
if (pid->Improve & PID_Derivative_On_Measurement)
|
||||||
f_Derivative_On_Measurement(pid);
|
f_Derivative_On_Measurement(pid);
|
||||||
// 微分滤波器
|
// 微分滤波器
|
||||||
if (pid->Improve & PID_DerivativeFilter)
|
if (pid->Improve & PID_DerivativeFilter)
|
||||||
f_Derivative_Filter(pid);
|
f_Derivative_Filter(pid);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* @version beta
|
* @version beta
|
||||||
* @date 2022-11-03
|
* @date 2022-11-03
|
||||||
* @todo 增加对串口调试助手协议的支持,包括vofa和serial debug
|
* @todo 增加对串口调试助手协议的支持,包括vofa和serial debug
|
||||||
* @copyright Copyright (c) 2022
|
* @copyright Copyright (c) 2023
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include "master_process.h"
|
#include "master_process.h"
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ static CANInstance sender_assignment[6] = {
|
|||||||
[1] = {.can_handle = &hcan1, .txconf.StdId = 0x200, .txconf.IDE = CAN_ID_STD, .txconf.RTR = CAN_RTR_DATA, .txconf.DLC = 0x08, .tx_buff = {0}},
|
[1] = {.can_handle = &hcan1, .txconf.StdId = 0x200, .txconf.IDE = CAN_ID_STD, .txconf.RTR = CAN_RTR_DATA, .txconf.DLC = 0x08, .tx_buff = {0}},
|
||||||
[2] = {.can_handle = &hcan1, .txconf.StdId = 0x2ff, .txconf.IDE = CAN_ID_STD, .txconf.RTR = CAN_RTR_DATA, .txconf.DLC = 0x08, .tx_buff = {0}},
|
[2] = {.can_handle = &hcan1, .txconf.StdId = 0x2ff, .txconf.IDE = CAN_ID_STD, .txconf.RTR = CAN_RTR_DATA, .txconf.DLC = 0x08, .tx_buff = {0}},
|
||||||
[3] = {.can_handle = &hcan2, .txconf.StdId = 0x1ff, .txconf.IDE = CAN_ID_STD, .txconf.RTR = CAN_RTR_DATA, .txconf.DLC = 0x08, .tx_buff = {0}},
|
[3] = {.can_handle = &hcan2, .txconf.StdId = 0x1ff, .txconf.IDE = CAN_ID_STD, .txconf.RTR = CAN_RTR_DATA, .txconf.DLC = 0x08, .tx_buff = {0}},
|
||||||
[4] = {.can_handle = &hcan2, .txconf.StdId = 0x200, .txconf.IDE = CAN_ID_STD, .txconf.RTR = CAN_RTR_DATA, .txconf.DLC = 0x08, .tx_buff = {0}},
|
[4] = {.can_handle = &hcan2, .txconf.StdId = 0x3FE, .txconf.IDE = CAN_ID_STD, .txconf.RTR = CAN_RTR_DATA, .txconf.DLC = 0x08, .tx_buff = {0}},
|
||||||
[5] = {.can_handle = &hcan2, .txconf.StdId = 0x2ff, .txconf.IDE = CAN_ID_STD, .txconf.RTR = CAN_RTR_DATA, .txconf.DLC = 0x08, .tx_buff = {0}},
|
[5] = {.can_handle = &hcan2, .txconf.StdId = 0x2ff, .txconf.IDE = CAN_ID_STD, .txconf.RTR = CAN_RTR_DATA, .txconf.DLC = 0x08, .tx_buff = {0}},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -106,7 +106,36 @@ static void MotorSenderGrouping(DJIMotorInstance *motor, CAN_Init_Config_s *conf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case DM4310:
|
||||||
|
if (motor_id < 4) // 根据ID分组
|
||||||
|
{
|
||||||
|
motor_send_num = motor_id;
|
||||||
|
motor_grouping = config->can_handle == &hcan2 ? 1 : 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
motor_send_num = motor_id - 4;
|
||||||
|
motor_grouping = config->can_handle == &hcan2 ? 0 : 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算接收id并设置分组发送id
|
||||||
|
config->rx_id = 0x300 + motor_id + 1; // 把ID+1,进行分组设置
|
||||||
|
sender_enable_flag[motor_grouping] = 1; // 设置发送标志位,防止发送空帧
|
||||||
|
motor->message_num = motor_send_num;
|
||||||
|
motor->sender_group = motor_grouping;
|
||||||
|
|
||||||
|
// 检查是否发生id冲突
|
||||||
|
for (size_t i = 0; i < idx; ++i)
|
||||||
|
{
|
||||||
|
if (dji_motor_instance[i]->motor_can_instance->can_handle == config->can_handle && dji_motor_instance[i]->motor_can_instance->rx_id == config->rx_id)
|
||||||
|
{
|
||||||
|
LOGERROR("[dji_motor] ID crash. Check in debug mode, add dji_motor_instance to watch to get more information.");
|
||||||
|
uint16_t can_bus = config->can_handle == &hcan2 ? 1 : 2;
|
||||||
|
while (1) // 6020的id 1-4和2006/3508的id 5-8会发生冲突(若有注册,即1!5,2!6,3!7,4!8) (1!5!,LTC! (((不是)
|
||||||
|
LOGERROR("[dji_motor] id [%d], can_bus [%d]", config->rx_id, can_bus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
default: // other motors should not be registered here
|
default: // other motors should not be registered here
|
||||||
while (1)
|
while (1)
|
||||||
LOGERROR("[dji_motor]You must not register other motors using the API of DJI motor."); // 其他电机不应该在这里注册
|
LOGERROR("[dji_motor]You must not register other motors using the API of DJI motor."); // 其他电机不应该在这里注册
|
||||||
@@ -296,8 +325,17 @@ void DJIMotorControl()
|
|||||||
// 分组填入发送数据
|
// 分组填入发送数据
|
||||||
group = motor->sender_group;
|
group = motor->sender_group;
|
||||||
num = motor->message_num;
|
num = motor->message_num;
|
||||||
sender_assignment[group].tx_buff[2 * num] = (uint8_t)(set >> 8); // 低八位
|
|
||||||
sender_assignment[group].tx_buff[2 * num + 1] = (uint8_t)(set & 0x00ff); // 高八位
|
if (i == 1)
|
||||||
|
{
|
||||||
|
sender_assignment[4].tx_buff[6] = (uint8_t)(set & 0x00ff); // 高八位
|
||||||
|
sender_assignment[4].tx_buff[7] = (uint8_t)(set >> 8); // 低八位
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sender_assignment[group].tx_buff[2 * num] = (uint8_t)(set >> 8); // 低八位
|
||||||
|
sender_assignment[group].tx_buff[2 * num + 1] = (uint8_t)(set & 0x00ff); // 高八位
|
||||||
|
}
|
||||||
|
|
||||||
// 若该电机处于停止状态,直接将buff置零
|
// 若该电机处于停止状态,直接将buff置零
|
||||||
if (motor->stop_flag == MOTOR_STOP)
|
if (motor->stop_flag == MOTOR_STOP)
|
||||||
|
|||||||
@@ -105,7 +105,6 @@ void DJIMotorChangeFeed(DJIMotorInstance *motor, Closeloop_Type_e loop, Feedback
|
|||||||
* @brief 该函数被motor_task调用运行在rtos上,motor_stask内通过osDelay()确定控制频率
|
* @brief 该函数被motor_task调用运行在rtos上,motor_stask内通过osDelay()确定控制频率
|
||||||
*/
|
*/
|
||||||
void DJIMotorControl();
|
void DJIMotorControl();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 停止电机,注意不是将设定值设为零,而是直接给电机发送的电流值置零
|
* @brief 停止电机,注意不是将设定值设为零,而是直接给电机发送的电流值置零
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -20,13 +20,32 @@ static DaemonInstance *rc_daemon_instance;
|
|||||||
* @brief 矫正遥控器摇杆的值,超过660或者小于-660的值都认为是无效值,置0
|
* @brief 矫正遥控器摇杆的值,超过660或者小于-660的值都认为是无效值,置0
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void RectifyRCjoystick()
|
// static void RectifyRCjoystick()
|
||||||
|
// {
|
||||||
|
// for (uint8_t i = 0; i < 5; ++i)
|
||||||
|
// if (abs(*(&rc_ctrl[TEMP].rc.rocker_l_ + i)) > 660)
|
||||||
|
// *(&rc_ctrl[TEMP].rc.rocker_l_ + i) = 0;
|
||||||
|
// }
|
||||||
|
static void RectifyRCjoystick()//左遥杆水平向右限幅不够,因为下面的+3,将+3删除就用上面的
|
||||||
{
|
{
|
||||||
|
int16_t *rocker_ptr = &rc_ctrl[TEMP].rc.rocker_l_;
|
||||||
for (uint8_t i = 0; i < 5; ++i)
|
for (uint8_t i = 0; i < 5; ++i)
|
||||||
if (abs(*(&rc_ctrl[TEMP].rc.rocker_l_ + i)) > 660)
|
{
|
||||||
*(&rc_ctrl[TEMP].rc.rocker_l_ + i) = 0;
|
if (i == 0) // 左遥杆水平方向
|
||||||
|
{
|
||||||
|
// 增加右向最大值到700,左向保持660不变
|
||||||
|
if (rocker_ptr[i] > 700)
|
||||||
|
rocker_ptr[i] = 700;
|
||||||
|
else if (rocker_ptr[i] < -660)
|
||||||
|
rocker_ptr[i] = -660;
|
||||||
|
}
|
||||||
|
else // 其他通道保持原限制
|
||||||
|
{
|
||||||
|
if (abs(rocker_ptr[i]) > 660)
|
||||||
|
rocker_ptr[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 遥控器数据解析
|
* @brief 遥控器数据解析
|
||||||
*
|
*
|
||||||
@@ -40,7 +59,7 @@ static void sbus_to_rc(const uint8_t *sbus_buf)
|
|||||||
rc_ctrl[TEMP].rc.rocker_l_ = (((sbus_buf[2] >> 6) | (sbus_buf[3] << 2) | (sbus_buf[4] << 10)) & 0x07ff) - RC_CH_VALUE_OFFSET; //!< Channel 2
|
rc_ctrl[TEMP].rc.rocker_l_ = (((sbus_buf[2] >> 6) | (sbus_buf[3] << 2) | (sbus_buf[4] << 10)) & 0x07ff) - RC_CH_VALUE_OFFSET; //!< Channel 2
|
||||||
rc_ctrl[TEMP].rc.rocker_l1 = (((sbus_buf[4] >> 1) | (sbus_buf[5] << 7)) & 0x07ff) - RC_CH_VALUE_OFFSET; //!< Channel 3
|
rc_ctrl[TEMP].rc.rocker_l1 = (((sbus_buf[4] >> 1) | (sbus_buf[5] << 7)) & 0x07ff) - RC_CH_VALUE_OFFSET; //!< Channel 3
|
||||||
rc_ctrl[TEMP].rc.dial = ((sbus_buf[16] | (sbus_buf[17] << 8)) & 0x07FF) - RC_CH_VALUE_OFFSET;
|
rc_ctrl[TEMP].rc.dial = ((sbus_buf[16] | (sbus_buf[17] << 8)) & 0x07FF) - RC_CH_VALUE_OFFSET;
|
||||||
rc_ctrl[TEMP].rc.rocker_l_= rc_ctrl[TEMP].rc.rocker_l_;
|
rc_ctrl[TEMP].rc.rocker_l_= rc_ctrl[TEMP].rc.rocker_l_+3;
|
||||||
// 左侧拨轮
|
// 左侧拨轮
|
||||||
RectifyRCjoystick();
|
RectifyRCjoystick();
|
||||||
// 开关,0左1右
|
// 开关,0左1右
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* @Descripttion:
|
* @Descripttion: 适配群星战队协议的超级电容模块
|
||||||
* @version:
|
* @version: V2.0
|
||||||
* @Author: Chenfu
|
|
||||||
* @Date: 2022-12-02 21:32:47
|
|
||||||
* @LastEditTime: 2022-12-05 15:29:49
|
|
||||||
*/
|
*/
|
||||||
#include "super_cap.h"
|
#include "super_cap.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "stdlib.h"
|
#include "stdlib.h"
|
||||||
|
|
||||||
static SuperCapInstance *super_cap_instance = NULL; // 可以由app保存此指针
|
static SuperCapInstance *super_cap_instance = NULL;
|
||||||
|
|
||||||
static void SuperCapRxCallback(CANInstance *_instance)
|
static void SuperCapRxCallback(CANInstance *_instance)
|
||||||
{
|
{
|
||||||
@@ -17,25 +14,44 @@ static void SuperCapRxCallback(CANInstance *_instance)
|
|||||||
SuperCap_Msg_s *Msg;
|
SuperCap_Msg_s *Msg;
|
||||||
rxbuff = _instance->rx_buff;
|
rxbuff = _instance->rx_buff;
|
||||||
Msg = &super_cap_instance->cap_msg;
|
Msg = &super_cap_instance->cap_msg;
|
||||||
Msg->vol = (uint16_t)(rxbuff[0] << 8 | rxbuff[1]);
|
|
||||||
Msg->current = (uint16_t)(rxbuff[2] << 8 | rxbuff[3]);
|
// 按照新协议解析接收数据
|
||||||
Msg->power = (uint16_t)(rxbuff[4] << 8 | rxbuff[5]);
|
Msg->ready = (SuperCapReadyEnum)rxbuff[0];
|
||||||
|
Msg->state = (SuperCapStateEnum)rxbuff[1];
|
||||||
|
Msg->energy = rxbuff[2];
|
||||||
|
Msg->chassis_power = (uint16_t)(rxbuff[3] << 1); // 左移一位还原量程
|
||||||
|
Msg->bat_voltage = rxbuff[4];
|
||||||
|
Msg->bat_power = rxbuff[5];
|
||||||
}
|
}
|
||||||
|
|
||||||
SuperCapInstance *SuperCapInit(SuperCap_Init_Config_s *supercap_config)
|
SuperCapInstance *SuperCapInit(SuperCap_Init_Config_s *supercap_config)
|
||||||
{
|
{
|
||||||
super_cap_instance = (SuperCapInstance *)malloc(sizeof(SuperCapInstance));
|
super_cap_instance = (SuperCapInstance *)malloc(sizeof(SuperCapInstance));
|
||||||
memset(super_cap_instance, 0, sizeof(SuperCapInstance));
|
memset(super_cap_instance, 0, sizeof(SuperCapInstance));
|
||||||
|
|
||||||
supercap_config->can_config.can_module_callback = SuperCapRxCallback;
|
supercap_config->can_config.can_module_callback = SuperCapRxCallback;
|
||||||
super_cap_instance->can_ins = CANRegister(&supercap_config->can_config);
|
super_cap_instance->can_ins = CANRegister(&supercap_config->can_config);
|
||||||
return super_cap_instance;
|
return super_cap_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SuperCapSend(SuperCapInstance *instance, uint8_t *data)
|
void SuperCapSend(SuperCapInstance *instance, SuperCap_TxMsg_s *tx_data)
|
||||||
{
|
{
|
||||||
memcpy(instance->can_ins->tx_buff, data, 8);
|
uint8_t *txbuff = instance->can_ins->tx_buff;
|
||||||
CANTransmit(instance->can_ins,1);
|
|
||||||
|
// 按照新协议装载发送数据
|
||||||
|
txbuff[0] = tx_data->Enable;
|
||||||
|
txbuff[1] = tx_data->Charge;
|
||||||
|
txbuff[2] = tx_data->Powerlimit - instance->power_offset; // 计算功率补偿
|
||||||
|
txbuff[3] = tx_data->ChargePower;
|
||||||
|
|
||||||
|
CANTransmit(instance->can_ins, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuperCapSetPowerOffset(SuperCapInstance *instance, uint8_t offset)
|
||||||
|
{
|
||||||
|
if (instance != NULL) {
|
||||||
|
instance->power_offset = offset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SuperCap_Msg_s SuperCapGet(SuperCapInstance *instance)
|
SuperCap_Msg_s SuperCapGet(SuperCapInstance *instance)
|
||||||
|
|||||||
@@ -1,29 +1,61 @@
|
|||||||
/*
|
/*
|
||||||
* @Descripttion:
|
* @Descripttion: 适配群星战队协议的超级电容模块
|
||||||
* @version:
|
* @version: V2.0
|
||||||
* @Author: Chenfu
|
|
||||||
* @Date: 2022-12-02 21:32:47
|
|
||||||
* @LastEditTime: 2022-12-05 15:25:46
|
|
||||||
*/
|
*/
|
||||||
#ifndef SUPER_CAP_H
|
#ifndef SUPER_CAP_H
|
||||||
#define SUPER_CAP_H
|
#define SUPER_CAP_H
|
||||||
|
|
||||||
#include "bsp_can.h"
|
#include "bsp_can.h"
|
||||||
|
|
||||||
|
// 超级电容状态枚举(从群星战队协议移植)
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DISCHARGE = 0, // 放电状态
|
||||||
|
CHARGE = 1, // 充电状态
|
||||||
|
WAIT = 2, // 待机状态
|
||||||
|
SOFTSTART_PROTECTION = 3, // 处于软起动状态
|
||||||
|
OVER_LOAD_PROTECTION = 4, // 超电过载保护状态
|
||||||
|
BAT_OVER_VOLTAGE_PROTECTION = 5, // 过压保护状态
|
||||||
|
BAT_UNDER_VOLTAGE_PROTECTION = 6, // 电池欠压保护
|
||||||
|
CAP_UNDER_VOLTAGE_PROTECTION = 7, // 超级电容欠压保护
|
||||||
|
OVER_TEMPERATURE_PROTECTION = 8, // 过温保护
|
||||||
|
BOOM = 9, // 超电爆炸了
|
||||||
|
} SuperCapStateEnum;
|
||||||
|
|
||||||
|
// 超级电容准备状态
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
UNREADY = 0,
|
||||||
|
READY = 1,
|
||||||
|
} SuperCapReadyEnum;
|
||||||
|
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
|
/* 接收到的超级电容信息结构体 */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint16_t vol; // 电压
|
SuperCapReadyEnum ready; // 可用标志:1为可用,0为不可用
|
||||||
uint16_t current; // 电流
|
SuperCapStateEnum state; // 状态标志
|
||||||
uint16_t power; // 功率
|
uint8_t energy; // 超级电容可用能量:0-100%
|
||||||
|
uint16_t chassis_power; // 底盘功率
|
||||||
|
uint8_t bat_voltage; // 电池电压*10
|
||||||
|
uint8_t bat_power; // 电池功率
|
||||||
} SuperCap_Msg_s;
|
} SuperCap_Msg_s;
|
||||||
|
|
||||||
|
/* 需要发送给超级电容的控制信息结构体 */
|
||||||
|
typedef struct {
|
||||||
|
uint8_t Enable; // 超级电容使能。1使能,0失能
|
||||||
|
uint8_t Charge; // 超级电容充电。1充电,0放电
|
||||||
|
uint8_t Powerlimit; // 裁判系统功率限制
|
||||||
|
uint8_t ChargePower; // 超级电容充电功率
|
||||||
|
} SuperCap_TxMsg_s;
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
/* 超级电容实例 */
|
/* 超级电容实例 */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
CANInstance *can_ins; // CAN实例
|
CANInstance *can_ins; // CAN实例
|
||||||
SuperCap_Msg_s cap_msg; // 超级电容信息
|
SuperCap_Msg_s cap_msg; // 超级电容接收信息
|
||||||
|
uint8_t power_offset; // 功率补偿值
|
||||||
} SuperCapInstance;
|
} SuperCapInstance;
|
||||||
|
|
||||||
/* 超级电容初始化配置 */
|
/* 超级电容初始化配置 */
|
||||||
@@ -34,18 +66,22 @@ typedef struct
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 初始化超级电容
|
* @brief 初始化超级电容
|
||||||
*
|
|
||||||
* @param supercap_config 超级电容初始化配置
|
|
||||||
* @return SuperCapInstance* 超级电容实例指针
|
|
||||||
*/
|
*/
|
||||||
SuperCapInstance *SuperCapInit(SuperCap_Init_Config_s *supercap_config);
|
SuperCapInstance *SuperCapInit(SuperCap_Init_Config_s *supercap_config);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 发送超级电容控制信息
|
* @brief 发送超级电容控制信息
|
||||||
*
|
|
||||||
* @param instance 超级电容实例
|
|
||||||
* @param data 超级电容控制信息
|
|
||||||
*/
|
*/
|
||||||
void SuperCapSend(SuperCapInstance *instance, uint8_t *data);
|
void SuperCapSend(SuperCapInstance *instance, SuperCap_TxMsg_s *tx_data);
|
||||||
|
|
||||||
#endif // !SUPER_CAP_Hd
|
/**
|
||||||
|
* @brief 设置超级电容功率补偿
|
||||||
|
*/
|
||||||
|
void SuperCapSetPowerOffset(SuperCapInstance *instance, uint8_t offset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取超级电容数据
|
||||||
|
*/
|
||||||
|
SuperCap_Msg_s SuperCapGet(SuperCapInstance *instance);
|
||||||
|
|
||||||
|
#endif // !SUPER_CAP_H
|
||||||
@@ -1,21 +1,16 @@
|
|||||||
<!--
|
# super_cap (适配版)
|
||||||
* @Descripttion:
|
|
||||||
* @version:
|
|
||||||
* @Author: Chenfu
|
|
||||||
* @Date: 2022-12-02 21:32:47
|
|
||||||
* @LastEditTime: 2022-12-05 15:27:57
|
|
||||||
-->
|
|
||||||
# super_can
|
|
||||||
|
|
||||||
## 代码结构
|
## 代码结构
|
||||||
|
|
||||||
.h中放置的是数据定义和外部接口,以及协议的定义和宏,.c中包含一些私有函数。
|
.h中放置的是数据和协议枚举定义、控制接口,.c中包含CAN接收中断的回调解析以及发送打包逻辑。当前版本已完全适配群星战队的超级电容协议。
|
||||||
|
|
||||||
## 外部接口
|
## 外部接口
|
||||||
|
|
||||||
```c
|
```c
|
||||||
SuperCapInstance *SuperCapInit(SuperCap_Init_Config_s* supercap_config);
|
SuperCapInstance *SuperCapInit(SuperCap_Init_Config_s* supercap_config);
|
||||||
void SuperCapSend(SuperCapInstance *instance, uint8_t *data);
|
void SuperCapSend(SuperCapInstance *instance, SuperCap_TxMsg_s *tx_data);
|
||||||
|
void SuperCapSetPowerOffset(SuperCapInstance *instance, uint8_t offset);
|
||||||
|
SuperCap_Msg_s SuperCapGet(SuperCapInstance *instance);
|
||||||
```
|
```
|
||||||
## 私有函数和变量
|
## 私有函数和变量
|
||||||
|
|
||||||
@@ -25,7 +20,7 @@ static uint8_t *rxbuff;
|
|||||||
static void SuperCapRxCallback(can_instance *_instance)
|
static void SuperCapRxCallback(can_instance *_instance)
|
||||||
```
|
```
|
||||||
|
|
||||||
`SuperCapRxCallback()`是super cap初始化can实例时的回调函数,用于can接收中断,进行协议解析。
|
SuperCapRxCallback()是super cap初始化can实例时的回调函数,用于CAN接收中断,进行协议解析(包含底盘功率右移量程的还原等处理)。
|
||||||
|
|
||||||
## 使用范例
|
## 使用范例
|
||||||
|
|
||||||
@@ -33,22 +28,28 @@ static void SuperCapRxCallback(can_instance *_instance)
|
|||||||
|
|
||||||
```c
|
```c
|
||||||
SuperCap_Init_Config_s capconfig = {
|
SuperCap_Init_Config_s capconfig = {
|
||||||
.can_config = {
|
.can_config = {
|
||||||
.can_handle = &hcan1,
|
.can_handle = &hcan1,
|
||||||
.rx_id = 0x301,
|
.rx_id = 0x100, // 超级电容发给C板的ID
|
||||||
.tx_id = 0x302
|
.tx_id = 0x001 // C板发给超级电容的ID
|
||||||
},
|
}
|
||||||
.recv_data_len = 4*sizeof(uint16_t),
|
};
|
||||||
.send_data_len = sizeof(uint8_t)
|
SuperCapInstance *ins = SuperCapInit(&capconfig);
|
||||||
};
|
|
||||||
SuperCapInstance *ins =SuperCapInit(&capconfig);
|
// 如果需要设置功率补偿
|
||||||
|
SuperCapSetPowerOffset(ins, 5);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
发送通过`SuperCapSend()`,建议使用强制类型转换:
|
发送通过`SuperCapSend()`,建议使用强制类型转换:
|
||||||
|
发送控制指令时,使用 SuperCap_TxMsg_s 结构体:
|
||||||
```c
|
```c
|
||||||
uint16_t tx = 0x321;
|
SuperCap_TxMsg_s tx_cmd = {
|
||||||
SuperCapSend(ins, (uint8_t*)&tx);
|
.Enable = 1,
|
||||||
|
.Charge = 1,
|
||||||
|
.Powerlimit = 60,
|
||||||
|
.ChargePower = 40
|
||||||
|
};
|
||||||
|
SuperCapSend(ins, &tx_cmd);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user