可以控制,拔掉dji可以接收

This commit is contained in:
ws 2025-03-30 10:25:19 +08:00
parent 25bdadf878
commit 6909b34ccd
5 changed files with 391 additions and 4 deletions

View File

@ -123,12 +123,268 @@ static uint8_t can_send_data_200[8];
CAN_RxHeaderTypeDef dji_rx_header;
uint8_t dji_rx_data[8];
//小米电机
CAN_RxHeaderTypeDef rxMsg;//发送接收结构体
CAN_TxHeaderTypeDef txMsg;//发送配置结构体
uint32_t Motor_Can_ID; //接收数据电机ID
uint8_t byte[4]; //转换临时数据
uint32_t send_mail_box = {0};//NONE
#define can_txd() HAL_CAN_AddTxMessage(&hcan1, &txMsg, tx_data, &send_mail_box)//CAN发送宏定义
MI_Motor mi_motor[4];//预先定义四个小米电机
/**
* @brief 4
* @param[in] f:
* @retval 4
* @description : IEEE 754
*/
static uint8_t* Float_to_Byte(float f)
{
unsigned long longdata = 0;
longdata = *(unsigned long*)&f;
byte[0] = (longdata & 0xFF000000) >> 24;
byte[1] = (longdata & 0x00FF0000) >> 16;
byte[2] = (longdata & 0x0000FF00) >> 8;
byte[3] = (longdata & 0x000000FF);
return byte;
}
/**
* @brief 16
* @param[in] x:16
* @param[in] x_min:
* @param[in] x_max:
* @param[in] bits:
* @retval
*/
static float uint16_to_float(uint16_t x,float x_min,float x_max,int bits)
{
uint32_t span = (1 << bits) - 1;
float offset = x_max - x_min;
return offset * x / span + x_min;
}
/**
* @brief 16
* @param[in] x:
* @param[in] x_min:
* @param[in] x_max:
* @param[in] bits:
* @retval
*/
static int float_to_uint(float x, float x_min, float x_max, int bits)
{
float span = x_max - x_min;
float offset = x_min;
if(x > x_max) x=x_max;
else if(x < x_min) x= x_min;
return (int) ((x-offset)*((float)((1<<bits)-1))/span);
}
/**
* @brief
* @param[in] Motor:
* @param[in] Index:
* @param[in] Value:
* @param[in] Value_type:
* @retval none
*/
static void Set_Motor_Parameter(MI_Motor *Motor,uint16_t Index,float Value,char Value_type){
uint8_t tx_data[8];
txMsg.ExtId = Communication_Type_SetSingleParameter<<24|Master_CAN_ID<<8|Motor->CAN_ID;
tx_data[0]=Index;
tx_data[1]=Index>>8;
tx_data[2]=0x00;
tx_data[3]=0x00;
if(Value_type == 'f'){
Float_to_Byte(Value);
tx_data[4]=byte[3];
tx_data[5]=byte[2];
tx_data[6]=byte[1];
tx_data[7]=byte[0];
}
else if(Value_type == 's'){
tx_data[4]=(uint8_t)Value;
tx_data[5]=0x00;
tx_data[6]=0x00;
tx_data[7]=0x00;
}
can_txd();
}
/**
* @brief ID中的电机CANID
* @param[in] CAN_ID_Frame:CANID
* @retval CANID
*/
static uint32_t Get_Motor_ID(uint32_t CAN_ID_Frame)
{
return (CAN_ID_Frame&0xFFFF)>>8;
}
/**
* @brief
* @param[in] Motor:
* @param[in] DataFrame:
* @param[in] IDFrame:ID帧
* @retval None
*/
static void Motor_Data_Handler(MI_Motor *Motor,uint8_t DataFrame[8],uint32_t IDFrame)
{
Motor->Angle=uint16_to_float(DataFrame[0]<<8|DataFrame[1],MIN_P,MAX_P,16);
Motor->Speed=uint16_to_float(DataFrame[2]<<8|DataFrame[3],V_MIN,V_MAX,16);
Motor->Torque=uint16_to_float(DataFrame[4]<<8|DataFrame[5],T_MIN,T_MAX,16);
Motor->Temp=(DataFrame[6]<<8|DataFrame[7])*Temp_Gain;
Motor->error_code=(IDFrame&0x1F0000)>>16;
}
/**
* @brief ID检查
* @param[in] id: CAN_ID0x7F
* @retval none
*/
void chack_cybergear(uint8_t ID)
{
uint8_t tx_data[8] = {0};
txMsg.ExtId = Communication_Type_GetID<<24|Master_CAN_ID<<8|ID;
can_txd();
}
/**
* @brief 使
* @param[in] Motor:
* @retval none
*/
void start_cybergear(MI_Motor *Motor)
{
uint8_t tx_data[8] = {0};
txMsg.ExtId = Communication_Type_MotorEnable<<24|Master_CAN_ID<<8|Motor->CAN_ID;
can_txd();
}
/**
* @brief
* @param[in] Motor:
* @param[in] clear_error:0 1
* @retval None
*/
void stop_cybergear(MI_Motor *Motor,uint8_t clear_error)
{
uint8_t tx_data[8]={0};
tx_data[0]=clear_error;//清除错误位设置
txMsg.ExtId = Communication_Type_MotorStop<<24|Master_CAN_ID<<8|Motor->CAN_ID;
can_txd();
}
/**
* @brief ()
* @param[in] Motor:
* @param[in] Mode: 1.Motion_mode 2. Position_mode 3. Speed_mode 4. Current_mode
* @retval none
*/
void set_mode_cybergear(MI_Motor *Motor,uint8_t Mode)
{
Set_Motor_Parameter(Motor,Run_mode,Mode,'s');
}
/**
* @brief
* @param[in] Motor:
* @param[in] Current:
* @retval none
*/
void set_current_cybergear(MI_Motor *Motor,float Current)
{
Set_Motor_Parameter(Motor,Iq_Ref,Current,'f');
}
/**
* @brief
* @param[in] Motor:
* @retval none
*/
void set_zeropos_cybergear(MI_Motor *Motor)
{
uint8_t tx_data[8]={0};
tx_data[0] = 1;
txMsg.ExtId = Communication_Type_SetPosZero<<24|Master_CAN_ID<<8|Motor->CAN_ID;
can_txd();
}
/**
* @brief CANID
* @param[in] Motor:
* @param[in] Motor: ID
* @retval none
*/
void set_CANID_cybergear(MI_Motor *Motor,uint8_t CAN_ID)
{
uint8_t tx_data[8]={0};
txMsg.ExtId = Communication_Type_CanID<<24|CAN_ID<<16|Master_CAN_ID<<8|Motor->CAN_ID;
Motor->CAN_ID = CAN_ID;//将新的ID导入电机结构体
can_txd();
}
/**
* @brief
* @param[in] Motor:
* @param[in] Can_Id: ID(0x7F)
* @param[in] Motor_Num:
* @param[in] mode: 0.Motion_mode 1. Position_mode 2. Speed_mode 3. Current_mode
* @retval none
*/
void init_cybergear(MI_Motor *Motor,uint8_t Can_Id, uint8_t mode)
{
txMsg.StdId = 0; //配置CAN发送标准帧清零
txMsg.ExtId = 0; //配置CAN发送扩展帧清零
txMsg.IDE = CAN_ID_EXT; //配置CAN发送扩展帧
txMsg.RTR = CAN_RTR_DATA; //配置CAN发送数据帧
txMsg.DLC = 0x08; //配置CAN发送数据长度
Motor->CAN_ID=Can_Id; //ID设置
set_mode_cybergear(Motor,mode);//设置电机模式
start_cybergear(Motor); //使能电机
}
/**
* @brief
* @param[in] Motor:
* @param[in] torque: [-12,12] N*M
* @param[in] MechPosition: [-12.5,12.5] rad
* @param[in] speed: [-30,30] rpm
* @param[in] kp:
* @param[in] kd:
* @retval none
*/
void motor_controlmode(MI_Motor *Motor,float torque, float MechPosition, float speed, float kp, float kd)
{
uint8_t tx_data[8];//发送数据初始化
//装填发送数据
tx_data[0]=float_to_uint(MechPosition,P_MIN,P_MAX,16)>>8;
tx_data[1]=float_to_uint(MechPosition,P_MIN,P_MAX,16);
tx_data[2]=float_to_uint(speed,V_MIN,V_MAX,16)>>8;
tx_data[3]=float_to_uint(speed,V_MIN,V_MAX,16);
tx_data[4]=float_to_uint(kp,KP_MIN,KP_MAX,16)>>8;
tx_data[5]=float_to_uint(kp,KP_MIN,KP_MAX,16);
tx_data[6]=float_to_uint(kd,KD_MIN,KD_MAX,16)>>8;
tx_data[7]=float_to_uint(kd,KD_MIN,KD_MAX,16);
txMsg.ExtId = Communication_Type_MotionControl<<24|float_to_uint(torque,T_MIN,T_MAX,16)<<8|Motor->CAN_ID;//装填扩展帧数据
can_txd();
}
/**
* @brief
* @param[in] none
* @retval none
*/
void djiMotorEncode()
{
if(dji_rx_header.IDE == CAN_ID_STD)
{
switch (dji_rx_header.StdId)
{
@ -159,6 +415,28 @@ void djiMotorEncode()
break;
}
}
}
if(dji_rx_header.IDE == CAN_ID_EXT)
{
Motor_Can_ID=Get_Motor_ID(dji_rx_header.ExtId);//首先获取回传电机ID信息
switch(Motor_Can_ID)
{
case 0x01:
if(dji_rx_header.ExtId>>24 != 0) //检查是否为广播模式
Motor_Data_Handler(&mi_motor[0],dji_rx_data,dji_rx_header.ExtId);
else
mi_motor[0].MCU_ID = dji_rx_data[0];
break;
default:
break;
}
}
}
void vescMotorEncode()

View File

@ -107,6 +107,96 @@ typedef enum {
#if FREERTOS_DJI == 1
/*小米电机部分参数和函数*/
//控制参数最值,谨慎更改
#define P_MIN -12.5f
#define P_MAX 12.5f
#define V_MIN -30.0f
#define V_MAX 30.0f
#define KP_MIN 0.0f
#define KP_MAX 500.0f
#define KD_MIN 0.0f
#define KD_MAX 5.0f
#define T_MIN -12.0f
#define T_MAX 12.0f
#define MAX_P 720
#define MIN_P -720
//主机CANID设置
#define Master_CAN_ID 0x00 //主机ID
//控制命令宏定义
#define Communication_Type_GetID 0x00 //获取设备的ID和64位MCU唯一标识符
#define Communication_Type_MotionControl 0x01 //用来向主机发送控制指令
#define Communication_Type_MotorRequest 0x02 //用来向主机反馈电机运行状态
#define Communication_Type_MotorEnable 0x03 //电机使能运行
#define Communication_Type_MotorStop 0x04 //电机停止运行
#define Communication_Type_SetPosZero 0x06 //设置电机机械零位
#define Communication_Type_CanID 0x07 //更改当前电机CAN_ID
#define Communication_Type_Control_Mode 0x12
#define Communication_Type_GetSingleParameter 0x11 //读取单个参数
#define Communication_Type_SetSingleParameter 0x12 //设定单个参数
#define Communication_Type_ErrorFeedback 0x15 //故障反馈帧
//参数读取宏定义
#define Run_mode 0x7005
#define Iq_Ref 0x7006
#define Spd_Ref 0x700A
#define Limit_Torque 0x700B
#define Cur_Kp 0x7010
#define Cur_Ki 0x7011
#define Cur_Filt_Gain 0x7014
#define Loc_Ref 0x7016
#define Limit_Spd 0x7017
#define Limit_Cur 0x7018
#define Gain_Angle 720/32767.0
#define Bias_Angle 0x8000
#define Gain_Speed 30/32767.0
#define Bias_Speed 0x8000
#define Gain_Torque 12/32767.0
#define Bias_Torque 0x8000
#define Temp_Gain 0.1
#define Motor_Error 0x00
#define Motor_OK 0X01
enum CONTROL_MODE //控制模式定义
{
Motion_mode = 0,//运控模式
Position_mode, //位置模式
Speed_mode, //速度模式
Current_mode //电流模式
};
enum ERROR_TAG //错误回传对照
{
OK = 0,//无故障
BAT_LOW_ERR = 1,//欠压故障
OVER_CURRENT_ERR = 2,//过流
OVER_TEMP_ERR = 3,//过温
MAGNETIC_ERR = 4,//磁编码故障
HALL_ERR_ERR = 5,//HALL编码故障
NO_CALIBRATION_ERR = 6//未标定
};
typedef struct{ //小米电机结构体
uint8_t CAN_ID; //CAN ID
uint8_t MCU_ID; //MCU唯一标识符[后8位共64位]
float Angle; //回传角度
float Speed; //回传速度
float Torque; //回传力矩
float Temp; //回传温度
uint16_t set_current;
uint16_t set_speed;
uint16_t set_position;
uint8_t error_code;
float Angle_Bias;
}MI_Motor;
extern MI_Motor mi_motor[4];//预先定义四个小米电机
/**
* @brief
* @param none
@ -156,6 +246,17 @@ extern void CAN_cmd_2FF(int16_t motor1, int16_t motor2, int16_t motor3, CAN_Hand
extern motor_measure_t *get_motor_point(uint8_t i);
//小米
extern void chack_cybergear(uint8_t ID);
extern void start_cybergear(MI_Motor *Motor);
extern void stop_cybergear(MI_Motor *Motor, uint8_t clear_error);
extern void set_mode_cybergear(MI_Motor *Motor, uint8_t Mode);
extern void set_current_cybergear(MI_Motor *Motor, float Current);
extern void set_zeropos_cybergear(MI_Motor *Motor);
extern void set_CANID_cybergear(MI_Motor *Motor, uint8_t CAN_ID);
extern void init_cybergear(MI_Motor *Motor, uint8_t Can_Id, uint8_t mode);
extern void motor_controlmode(MI_Motor *Motor,float torque, float MechPosition, float speed, float kp, float kd);
/**
* @brief
* @param[in] none

View File

@ -15,7 +15,7 @@ extern int16_t t_result;
extern motor_measure_t *trigger_motor_data;
float vofa[8];
int tangle=0;
/**
* \brief
@ -35,6 +35,7 @@ void Task_Motor(void *argument)
while(1)
{
trigger_pos(tangle);
CAN_cmd_200(t_result,0,0,0,&hcan1);
osDelay(2);

View File

@ -7,14 +7,18 @@
#include "main.h"
#include "remote_control.h"
#include "led.h"
#include "djiMotor.h"
#define GOUSE 1
extern RC_mess_t RC_mess;
int anglexiaomi = 0;
void Task_Go(void *argument)
{
#if GOUSE==1
HAL_Delay(500); //一定时间延时 等待电机初始化完成
init_cybergear(&mi_motor[0], 0x01, Motion_mode);//小米电机 启动!
//HAL_Delay(2000);
// gimbalInit();
//HAL_GPIO_WritePin(ledGreen_GPIO_Port,ledGreen_Pin,GPIO_PIN_RESET);
@ -23,6 +27,8 @@ void Task_Go(void *argument)
{
LED_green();
LED_bule();
motor_controlmode(&mi_motor[0], 0.5, anglexiaomi, 4, 0.5 , 0.5); //小米暂时锁住就行
// gimbalFlow();
osDelay(1);
}

View File

@ -32,6 +32,7 @@ void Task_Shoot(void *argument)
control_clutch_shoot();
tick += delay_tick; /* 计算下一个唤醒时刻 */
osDelayUntil(tick); /* 运行结束,等待下一个周期唤醒 */
}