碳板步兵云台yaw轴调试完成

This commit is contained in:
宋家齐 2023-10-12 19:29:48 +08:00
parent fc6f91ac9a
commit e25cbdf2a3
5 changed files with 75 additions and 25 deletions

View File

@ -252,10 +252,10 @@ void ChassisTask()
// 根据裁判系统的反馈数据和电容数据对输出限幅并设定闭环参考值 // 根据裁判系统的反馈数据和电容数据对输出限幅并设定闭环参考值
LimitChassisOutput(); LimitChassisOutput();
float vofa_send_data[2]; // float vofa_send_data[2];
vofa_send_data[0]=motor_lb->motor_controller.speed_PID.Ref; // vofa_send_data[0]=motor_lb->motor_controller.speed_PID.Ref;
vofa_send_data[1]=motor_lb->motor_controller.speed_PID.Measure; // vofa_send_data[1]=motor_lb->motor_controller.speed_PID.Measure;
vofa_justfloat_output(vofa_send_data,8,&huart1); // vofa_justfloat_output(vofa_send_data,8,&huart1);
// 根据电机的反馈速度和IMU(如果有)计算真实速度 // 根据电机的反馈速度和IMU(如果有)计算真实速度
EstimateSpeed(); EstimateSpeed();

View File

@ -6,6 +6,7 @@
#include "general_def.h" #include "general_def.h"
#include "bmi088.h" #include "bmi088.h"
#include "vofa.h"
static attitude_t *gimba_IMU_data; // 云台IMU数据 static attitude_t *gimba_IMU_data; // 云台IMU数据
static DJIMotorInstance *yaw_motor, *pitch_motor; static DJIMotorInstance *yaw_motor, *pitch_motor;
@ -26,7 +27,7 @@ void GimbalInit()
}, },
.controller_param_init_config = { .controller_param_init_config = {
.angle_PID = { .angle_PID = {
.Kp = 8, // 8 .Kp = 0.5, // 8
.Ki = 0, .Ki = 0,
.Kd = 0, .Kd = 0,
.DeadBand = 0.1, .DeadBand = 0.1,
@ -36,8 +37,8 @@ void GimbalInit()
.MaxOut = 500, .MaxOut = 500,
}, },
.speed_PID = { .speed_PID = {
.Kp = 50, // 50 .Kp = 12000, // 50
.Ki = 200, // 200 .Ki = 3000, // 200
.Kd = 0, .Kd = 0,
.Improve = PID_Trapezoid_Intergral | PID_Integral_Limit | PID_Derivative_On_Measurement, .Improve = PID_Trapezoid_Intergral | PID_Integral_Limit | PID_Derivative_On_Measurement,
.IntegralLimit = 3000, .IntegralLimit = 3000,
@ -51,7 +52,7 @@ void GimbalInit()
.angle_feedback_source = OTHER_FEED, .angle_feedback_source = OTHER_FEED,
.speed_feedback_source = OTHER_FEED, .speed_feedback_source = OTHER_FEED,
.outer_loop_type = ANGLE_LOOP, .outer_loop_type = ANGLE_LOOP,
.close_loop_type = ANGLE_LOOP | SPEED_LOOP, .close_loop_type = SPEED_LOOP | ANGLE_LOOP,
.motor_reverse_flag = MOTOR_DIRECTION_NORMAL, .motor_reverse_flag = MOTOR_DIRECTION_NORMAL,
}, },
.motor_type = GM6020}; .motor_type = GM6020};
@ -59,7 +60,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 = 2, .tx_id = 4,
}, },
.controller_param_init_config = { .controller_param_init_config = {
.angle_PID = { .angle_PID = {
@ -93,7 +94,7 @@ void GimbalInit()
}; };
// 电机对total_angle闭环,上电时为零,会保持静止,收到遥控器数据再动 // 电机对total_angle闭环,上电时为零,会保持静止,收到遥控器数据再动
yaw_motor = DJIMotorInit(&yaw_config); yaw_motor = DJIMotorInit(&yaw_config);
pitch_motor = DJIMotorInit(&pitch_config); // pitch_motor = DJIMotorInit(&pitch_config);
gimbal_pub = PubRegister("gimbal_feed", sizeof(Gimbal_Upload_Data_s)); gimbal_pub = PubRegister("gimbal_feed", sizeof(Gimbal_Upload_Data_s));
gimbal_sub = SubRegister("gimbal_cmd", sizeof(Gimbal_Ctrl_Cmd_s)); gimbal_sub = SubRegister("gimbal_cmd", sizeof(Gimbal_Ctrl_Cmd_s));
@ -124,7 +125,7 @@ void GimbalTask()
DJIMotorChangeFeed(pitch_motor, ANGLE_LOOP, OTHER_FEED); DJIMotorChangeFeed(pitch_motor, ANGLE_LOOP, OTHER_FEED);
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; break;
// 云台自由模式,使用编码器反馈,底盘和云台分离,仅云台旋转,一般用于调整云台姿态(英雄吊射等)/能量机关 // 云台自由模式,使用编码器反馈,底盘和云台分离,仅云台旋转,一般用于调整云台姿态(英雄吊射等)/能量机关
case GIMBAL_FREE_MODE: // 后续删除,或加入云台追地盘的跟随模式(响应速度更快) case GIMBAL_FREE_MODE: // 后续删除,或加入云台追地盘的跟随模式(响应速度更快)
@ -135,7 +136,7 @@ void GimbalTask()
DJIMotorChangeFeed(pitch_motor, ANGLE_LOOP, OTHER_FEED); DJIMotorChangeFeed(pitch_motor, ANGLE_LOOP, OTHER_FEED);
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; break;
default: default:
break; break;
@ -145,6 +146,14 @@ void GimbalTask()
// 根据IMU姿态/pitch电机角度反馈计算出当前配重下的重力矩 // 根据IMU姿态/pitch电机角度反馈计算出当前配重下的重力矩
// ... // ...
float vofa_send_data[4];
vofa_send_data[0]=yaw_motor->motor_controller.speed_PID.Ref;
vofa_send_data[1]=yaw_motor->motor_controller.speed_PID.Measure;
vofa_send_data[2]=yaw_motor->motor_controller.angle_PID.Ref;
vofa_send_data[3]=yaw_motor->motor_controller.angle_PID.Measure;
vofa_justfloat_output(vofa_send_data,16,&huart1);
// 设置反馈数据,主要是imu和yaw的ecd // 设置反馈数据,主要是imu和yaw的ecd
gimbal_feedback_data.gimbal_imu_data = *gimba_IMU_data; gimbal_feedback_data.gimbal_imu_data = *gimba_IMU_data;
gimbal_feedback_data.yaw_motor_single_round_angle = yaw_motor->measure.angle_single_round; gimbal_feedback_data.yaw_motor_single_round_angle = yaw_motor->measure.angle_single_round;

View File

@ -32,7 +32,7 @@ void RobotInit()
#if defined(ONE_BOARD) || defined(GIMBAL_BOARD) #if defined(ONE_BOARD) || defined(GIMBAL_BOARD)
RobotCMDInit(); RobotCMDInit();
//暂时注释云台和发射任务 调试底盘 //暂时注释云台和发射任务 调试底盘
// GimbalInit(); GimbalInit();
// ShootInit(); // ShootInit();
#endif #endif
@ -51,7 +51,7 @@ void RobotTask()
#if defined(ONE_BOARD) || defined(GIMBAL_BOARD) #if defined(ONE_BOARD) || defined(GIMBAL_BOARD)
RobotCMDTask(); RobotCMDTask();
//暂时注释云台和发射任务 调试底盘 //暂时注释云台和发射任务 调试底盘
// GimbalTask(); GimbalTask();
// ShootTask(); // ShootTask();
#endif #endif

View File

@ -20,13 +20,19 @@
#include "general_def.h" #include "general_def.h"
#include "master_process.h" #include "master_process.h"
#include "vofa.h"
static INS_t INS; static INS_t INS;
static IMU_Param_t IMU_Param; static IMU_Param_t IMU_Param;
static PIDInstance TempCtrl = {0}; static PIDInstance TempCtrl = {0};
const float xb[3] = {1, 0, 0}; //const float xb[3] = {1, 0, 0};
//const float yb[3] = {0, 1, 0};
//const float zb[3] = {0, 0, 1};
const float xb[3] = {0, 0, 1};
const float yb[3] = {0, 1, 0}; const float yb[3] = {0, 1, 0};
const float zb[3] = {0, 0, 1}; const float zb[3] = {-1, 0, 0};
// 用于获取两次采样之间的时间间隔 // 用于获取两次采样之间的时间间隔
static uint32_t INS_DWT_Count = 0; static uint32_t INS_DWT_Count = 0;
@ -60,9 +66,9 @@ static void InitQuaternion(float *init_q4)
for (uint8_t i = 0; i < 100; ++i) for (uint8_t i = 0; i < 100; ++i)
{ {
BMI088_Read(&BMI088); BMI088_Read(&BMI088);
acc_init[X] += BMI088.Accel[X]; acc_init[X] += -BMI088.Accel[2];
acc_init[Y] += BMI088.Accel[Y]; acc_init[Y] += BMI088.Accel[Y];
acc_init[Z] += BMI088.Accel[Z]; acc_init[Z] += BMI088.Accel[0];
DWT_Delay(0.001); DWT_Delay(0.001);
} }
for (uint8_t i = 0; i < 3; ++i) for (uint8_t i = 0; i < 3; ++i)
@ -72,6 +78,9 @@ static void InitQuaternion(float *init_q4)
float angle = acosf(Dot3d(acc_init, gravity_norm)); float angle = acosf(Dot3d(acc_init, gravity_norm));
Cross3d(acc_init, gravity_norm, axis_rot); Cross3d(acc_init, gravity_norm, axis_rot);
Norm3d(axis_rot); Norm3d(axis_rot);
//q = cos (a/2) + i(x * sin(a/2)) + j(y * sin(a/2)) + k(z * sin(a/2))
//其中a表示旋转角度(x,y,z)表示旋转轴 计算由实际重力加速度方向(0,0,1)到当前加速度方向的旋转
init_q4[0] = cosf(angle / 2.0f); init_q4[0] = cosf(angle / 2.0f);
for (uint8_t i = 0; i < 2; ++i) for (uint8_t i = 0; i < 2; ++i)
init_q4[i + 1] = axis_rot[i] * sinf(angle / 2.0f); // 轴角公式,第三轴为0(没有z轴分量) init_q4[i + 1] = axis_rot[i] * sinf(angle / 2.0f); // 轴角公式,第三轴为0(没有z轴分量)
@ -97,7 +106,7 @@ attitude_t *INS_Init(void)
IMU_Param.flag = 1; IMU_Param.flag = 1;
float init_quaternion[4] = {0}; float init_quaternion[4] = {0};
InitQuaternion(init_quaternion); InitQuaternion(init_quaternion);//计算由实际重力加速度方向(0,0,1)到当前加速度方向的旋转
IMU_QuaternionEKF_Init(init_quaternion, 10, 0.001, 1000000, 1, 0); IMU_QuaternionEKF_Init(init_quaternion, 10, 0.001, 1000000, 1, 0);
// imu heat init // imu heat init
PID_Init_Config_s config = {.MaxOut = 2000, PID_Init_Config_s config = {.MaxOut = 2000,
@ -129,12 +138,12 @@ void INS_Task(void)
{ {
BMI088_Read(&BMI088); BMI088_Read(&BMI088);
INS.Accel[X] = BMI088.Accel[X]; INS.Accel[X] = -BMI088.Accel[2];
INS.Accel[Y] = BMI088.Accel[Y]; INS.Accel[Y] = BMI088.Accel[1];
INS.Accel[Z] = BMI088.Accel[Z]; INS.Accel[Z] = BMI088.Accel[0];
INS.Gyro[X] = BMI088.Gyro[X]; INS.Gyro[X] = -BMI088.Gyro[2];
INS.Gyro[Y] = BMI088.Gyro[Y]; INS.Gyro[Y] = BMI088.Gyro[1];
INS.Gyro[Z] = BMI088.Gyro[Z]; INS.Gyro[Z] = BMI088.Gyro[0];
// demo function,用于修正安装误差,可以不管,本demo暂时没用 // demo function,用于修正安装误差,可以不管,本demo暂时没用
IMU_Param_Correction(&IMU_Param, INS.Gyro, INS.Accel); IMU_Param_Correction(&IMU_Param, INS.Gyro, INS.Accel);
@ -162,11 +171,35 @@ void INS_Task(void)
} }
BodyFrameToEarthFrame(INS.MotionAccel_b, INS.MotionAccel_n, INS.q); // 转换回导航系n BodyFrameToEarthFrame(INS.MotionAccel_b, INS.MotionAccel_n, INS.q); // 转换回导航系n
INS.Yaw = QEKF_INS.Yaw; INS.Yaw = QEKF_INS.Yaw;
INS.Pitch = QEKF_INS.Pitch; INS.Pitch = QEKF_INS.Pitch;
INS.Roll = QEKF_INS.Roll; INS.Roll = QEKF_INS.Roll;
// // get Yaw total, yaw数据可能会超过360,处理一下方便其他功能使用(如小陀螺)
// if (INS.Yaw - INS.YawAngleLast > 180.0f)
// {
// INS.YawRoundCount--;
// }
// else if (INS.Yaw - INS.YawAngleLast < -180.0f)
// {
// INS.YawRoundCount++;
// }
// INS.YawTotalAngle = 360.0f * INS.YawRoundCount + INS.Yaw;
INS.YawTotalAngle = QEKF_INS.YawTotalAngle; INS.YawTotalAngle = QEKF_INS.YawTotalAngle;
// float vofa_send_data[9];
// vofa_send_data[0]=INS.Yaw;
// vofa_send_data[1]=INS.Pitch;
// vofa_send_data[2]=INS.Roll;
// vofa_send_data[3]=INS.Gyro[X];
// vofa_send_data[4]=INS.Gyro[Y];
// vofa_send_data[5]=INS.Gyro[Z];
// vofa_send_data[6]=BMI088.Accel[X];
// vofa_send_data[7]=BMI088.Accel[Y];
// vofa_send_data[8]=BMI088.Accel[Z];
// vofa_justfloat_output(vofa_send_data,36,&huart1);
VisionSetAltitude(INS.Yaw, INS.Pitch, INS.Roll); VisionSetAltitude(INS.Yaw, INS.Pitch, INS.Roll);
} }

View File

@ -23,6 +23,10 @@
#define Y 1 #define Y 1
#define Z 2 #define Z 2
//#define X 2
//#define Y 1
//#define Z 0
#define INS_TASK_PERIOD 1 #define INS_TASK_PERIOD 1
typedef struct typedef struct
@ -34,6 +38,7 @@ typedef struct
float Pitch; float Pitch;
float Yaw; float Yaw;
float YawTotalAngle; float YawTotalAngle;
} attitude_t; // 最终解算得到的角度,以及yaw转动的总角度(方便多圈控制) } attitude_t; // 最终解算得到的角度,以及yaw转动的总角度(方便多圈控制)
typedef struct typedef struct
@ -63,6 +68,9 @@ typedef struct
float Yaw; float Yaw;
float YawTotalAngle; float YawTotalAngle;
float YawAngleLast;
float YawRoundCount;
uint8_t init; uint8_t init;
} INS_t; } INS_t;