350 lines
11 KiB
C
350 lines
11 KiB
C
/**
|
||
****************************(C) COPYRIGHT ZhouCc****************************
|
||
* @file djiMotor.c/h
|
||
* @brief 大疆电机接收发送程序
|
||
* @note
|
||
* @history
|
||
* Version Date Author Modification
|
||
* V1.0.0 2023.12.11 ZhouCc 完成
|
||
*
|
||
@verbatim
|
||
==============================================================================
|
||
|
||
==============================================================================
|
||
@endverbatim
|
||
****************************(C) COPYRIGHT ZhouCc****************************
|
||
*/
|
||
|
||
#include "djiMotor.h"
|
||
#include "can_it.h"
|
||
#include "can_init.h"
|
||
#if FREERTOS_DJI == 1
|
||
#include "TopDefine.h"
|
||
#include<cmsis_os2.h>
|
||
#include "FreeRTOS.h"
|
||
|
||
#include "odrive_can.h"
|
||
|
||
|
||
static CAN_TxHeaderTypeDef vesc_tx_message;
|
||
static uint8_t vesc_send_data[4];
|
||
|
||
#endif
|
||
|
||
//motor data read
|
||
#define get_motor_measure(ptr, data) \
|
||
{ \
|
||
(ptr)->last_ecd = (ptr)->ecd; \
|
||
(ptr)->ecd = (uint16_t)((data)[0] << 8 | (data)[1]); \
|
||
(ptr)->speed_rpm = (uint16_t)((data)[2] << 8 | (data)[3]); \
|
||
(ptr)->given_current = (uint16_t)((data)[4] << 8 | (data)[5]); \
|
||
(ptr)->temperate = (data)[6]; \
|
||
(ptr)->ecd - (ptr)->last_ecd > 4096 ? ((ptr)->round_cnt--) : ((ptr)->round_cnt=(ptr)->round_cnt); \
|
||
(ptr)->ecd - (ptr)->last_ecd < -4096 ? ((ptr)->round_cnt++) : ((ptr)->round_cnt=(ptr)->round_cnt); \
|
||
(ptr)->total_angle = (fp64)((ptr)->round_cnt * 8192 + (ptr)->ecd - (ptr)->offset_ecd ) * MOTOR_ECD_TO_ANGLE_3508; \
|
||
}//ptr指向电机测量数据结构体的指针,data包含电机测量数据的数组.
|
||
/*(ptr)->real_angle = (ptr)->real_angle % 360; */
|
||
#define get_motor_offset(ptr, data) \
|
||
{ \
|
||
(ptr)->ecd = (uint16_t)((data)[0] << 8 | (data)[1]); \
|
||
(ptr)->offset_ecd = (ptr)->ecd; \
|
||
}
|
||
#define get_6020_motor_measure(ptr, data) \
|
||
{ \
|
||
(ptr)->last_ecd = (ptr)->ecd; \
|
||
(ptr)->ecd = (uint16_t)((data)[0] << 8 | (data)[1]); \
|
||
(ptr)->speed_rpm = (uint16_t)((data)[2] << 8 | (data)[3]); \
|
||
(ptr)->given_current = (uint16_t)((data)[4] << 8 | (data)[5]); \
|
||
(ptr)->temperate = (data)[6]; \
|
||
(ptr)->ecd - (ptr)->last_ecd > 4096 ? ((ptr)->round_cnt--) : ((ptr)->round_cnt=(ptr)->round_cnt); \
|
||
(ptr)->ecd - (ptr)->last_ecd < -4096 ? ((ptr)->round_cnt++) : ((ptr)->round_cnt=(ptr)->round_cnt); \
|
||
(ptr)->total_angle = (fp64)((ptr)->round_cnt * 8192 + (ptr)->ecd - (ptr)->offset_ecd ) * MOTOR_ECD_TO_ANGLE_6020; \
|
||
}
|
||
#define get_2006_motor_measure(ptr, data) \
|
||
{ \
|
||
(ptr)->last_ecd = (ptr)->ecd; \
|
||
(ptr)->ecd = (uint16_t)((data)[0] << 8 | (data)[1]); \
|
||
(ptr)->speed_rpm = (uint16_t)((data)[2] << 8 | (data)[3]); \
|
||
(ptr)->given_current = (uint16_t)((data)[4] << 8 | (data)[5]); \
|
||
(ptr)->temperate = (data)[6]; \
|
||
(ptr)->ecd - (ptr)->last_ecd > 4096 ? ((ptr)->round_cnt--) : ((ptr)->round_cnt=(ptr)->round_cnt); \
|
||
(ptr)->ecd - (ptr)->last_ecd < -4096 ? ((ptr)->round_cnt++) : ((ptr)->round_cnt=(ptr)->round_cnt); \
|
||
(ptr)->total_angle = (fp64)((ptr)->round_cnt * 8192 + (ptr)->ecd - (ptr)->offset_ecd ) * MOTOR_ECD_TO_ANGLE_2006; \
|
||
}
|
||
// 解析出初始编码器值
|
||
// #define get_5065motor_measure(ptr, data) \
|
||
// { \
|
||
// (ptr)->last_ecd = (ptr)->ecd; \
|
||
// (ptr)->ecd = (float)((data)[0] << 4 | (data)[1] <<3 |(data)[2] < 2 |(data)[3]); \
|
||
// (ptr)->speed_rpm = (float)((data)[4] << 4 | (data)[5] <<3 |(data)[6] < 2 |(data)[7]);; \
|
||
// }
|
||
/*(ptr)->real_angle = (ptr)->real_angle % 360; */
|
||
|
||
static void CAN_VescMotor_Decode_1(CAN_MotorFeedback_t *feedback,
|
||
const uint8_t *raw)
|
||
{
|
||
if (feedback == NULL || raw == NULL) return;
|
||
union
|
||
{
|
||
int x;
|
||
uint8_t data[4];
|
||
}speed;
|
||
|
||
speed.data[0]= raw[3];
|
||
speed.data[1]= raw[2];
|
||
speed.data[2]= raw[1];
|
||
speed.data[3]= raw[0];
|
||
feedback->rotor_speed = speed.x;
|
||
union
|
||
{
|
||
int16_t y;
|
||
uint8_t dat[2];
|
||
}current;
|
||
current.dat[0]= raw[5];
|
||
current.dat[1]= raw[4];
|
||
feedback->torque_current =(fp32)current.y/10;
|
||
}
|
||
|
||
|
||
#if DEBUG == 1
|
||
motor_measure_t motor_chassis[5];
|
||
CAN_MotorFeedback_t motor_6384;
|
||
|
||
#else
|
||
static motor_measure_t motor_chassis[5];
|
||
#endif
|
||
static CAN_TxHeaderTypeDef tx_meessage_1ff;
|
||
static uint8_t can_send_data_1ff[8];
|
||
static CAN_TxHeaderTypeDef tx_meessage_2ff;
|
||
static uint8_t can_send_data_2ff[8];
|
||
static CAN_TxHeaderTypeDef tx_message_200;
|
||
static uint8_t can_send_data_200[8];
|
||
|
||
CAN_RxHeaderTypeDef dji_rx_header;
|
||
uint8_t dji_rx_data[8];
|
||
|
||
/**
|
||
* @brief 数据处理函数
|
||
* @param[in] none
|
||
* @retval none
|
||
*/
|
||
void djiMotorEncode()
|
||
{
|
||
switch (dji_rx_header.StdId)
|
||
{
|
||
case 0x201:
|
||
case 0x202:
|
||
case 0x203:
|
||
case 0x204:
|
||
case 0x205:
|
||
case 0x206:
|
||
case 0x207:
|
||
{
|
||
static uint8_t i = 0;
|
||
//get motor id
|
||
i = dji_rx_header.StdId - 0x201;
|
||
if(motor_chassis[i].msg_cnt<=50)
|
||
{
|
||
motor_chassis[i].msg_cnt++;
|
||
get_motor_offset(&motor_chassis[i], dji_rx_data);
|
||
}else{
|
||
get_motor_measure(&motor_chassis[i], dji_rx_data);
|
||
}
|
||
break;
|
||
}
|
||
|
||
|
||
default:
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
void vescMotorEncode()
|
||
{
|
||
switch (dji_rx_header.ExtId) {
|
||
|
||
case CAN_VESC5065_M1_MSG1:
|
||
// 存储消息到对应的电机结构体中
|
||
CAN_VescMotor_Decode_1(&motor_6384, dji_rx_data);
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
}
|
||
|
||
#if FREERTOS_DJI == 0
|
||
/**
|
||
* @brief hal库CAN回调函数,接收电机数据
|
||
* @param[in] hcan:CAN句柄指针
|
||
* @retval none
|
||
*/
|
||
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
|
||
{
|
||
HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &dji_rx_header, dji_rx_data);
|
||
|
||
djiMotorEncode();
|
||
|
||
}
|
||
#else
|
||
static osEventFlagsId_t eventReceive;//事件标志
|
||
/**
|
||
* @brief 自定义大疆电机回调函数
|
||
* @param[in] none
|
||
* @retval none
|
||
*/
|
||
void Dji_Motor_CB()
|
||
{
|
||
HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &dji_rx_header, dji_rx_data);
|
||
|
||
osEventFlagsSet(eventReceive, EVENT_CAN);
|
||
}
|
||
|
||
/**
|
||
* @brief 大疆电机初始化
|
||
* @param none
|
||
* @retval none
|
||
*/
|
||
void djiInit(void)
|
||
{
|
||
BSP_CAN_RegisterCallback(BSP_CAN_1, HAL_CAN_RX_FIFO0_MSG_PENDING_CB,
|
||
Dji_Motor_CB);
|
||
can_filter_init();
|
||
}
|
||
|
||
/**
|
||
* @brief 等待新数据
|
||
*/
|
||
uint32_t waitNewDji()
|
||
{
|
||
return osEventFlagsWait(
|
||
eventReceive, EVENT_CAN,osFlagsWaitAny, osWaitForever);
|
||
}
|
||
#endif
|
||
|
||
/**
|
||
* @brief 发送电机控制电流(0x205,0x206,0x207,0x208)
|
||
* @param[in] motor1: (0x205) 电机控制电流
|
||
* @param[in] motor2: (0x206) 电机控制电流
|
||
* @param[in] motor3: (0x207) 电机控制电流
|
||
* @param[in] motor4: (0x208) 电机控制电流
|
||
* @retval none
|
||
*/
|
||
extern void CAN_cmd_1FF(int16_t motor1, int16_t motor2, int16_t motor3, int16_t motor4,CAN_HandleTypeDef*hcan)
|
||
{
|
||
uint32_t send_mail_box;
|
||
tx_meessage_1ff.StdId = 0x1FF;
|
||
tx_meessage_1ff.IDE = CAN_ID_STD;
|
||
tx_meessage_1ff.RTR = CAN_RTR_DATA;
|
||
tx_meessage_1ff.DLC = 0x08;
|
||
can_send_data_1ff[0] = (motor1 >> 8);
|
||
can_send_data_1ff[1] = motor1;
|
||
can_send_data_1ff[2] = (motor2 >> 8);
|
||
can_send_data_1ff[3] = motor2;
|
||
can_send_data_1ff[4] = (motor3 >> 8);
|
||
can_send_data_1ff[5] = motor3;
|
||
can_send_data_1ff[6] = (motor4 >> 8);
|
||
can_send_data_1ff[7] = motor4;
|
||
HAL_CAN_AddTxMessage(hcan, &tx_meessage_1ff, can_send_data_1ff, &send_mail_box);
|
||
}
|
||
|
||
/**
|
||
* @brief 发送电机控制电流(0x201,0x202,0x203,0x204)
|
||
* @param[in] motor1: (0x201) 电机控制电流
|
||
* @param[in] motor2: (0x202) 电机控制电流
|
||
* @param[in] motor3: (0x203) 电机控制电流
|
||
* @param[in] motor4: (0x204) 电机控制电流
|
||
* @retval none
|
||
*/
|
||
void CAN_cmd_200(int16_t motor1, int16_t motor2, int16_t motor3, int16_t motor4,CAN_HandleTypeDef*hcan)
|
||
{
|
||
uint32_t send_mail_box;
|
||
tx_message_200.StdId = 0x200;
|
||
tx_message_200.IDE = CAN_ID_STD;
|
||
tx_message_200.RTR = CAN_RTR_DATA;
|
||
tx_message_200.DLC = 0x08;
|
||
can_send_data_200[0] = motor1 >> 8;
|
||
can_send_data_200[1] = motor1;
|
||
can_send_data_200[2] = motor2 >> 8;
|
||
can_send_data_200[3] = motor2;
|
||
can_send_data_200[4] = motor3 >> 8;
|
||
can_send_data_200[5] = motor3;
|
||
can_send_data_200[6] = motor4 >> 8;
|
||
can_send_data_200[7] = motor4;
|
||
|
||
HAL_CAN_AddTxMessage(hcan, &tx_message_200, can_send_data_200, &send_mail_box);
|
||
}
|
||
|
||
/**
|
||
* @brief 发送电机控制电流(0x205,0x206,0x207,0x208)
|
||
* @param[in] motor1: (0x209) 电机控制电流
|
||
* @param[in] motor2: (0x20A) 电机控制电流
|
||
* @param[in] motor3: (0x20B) 电机控制电流
|
||
* @retval none
|
||
*/
|
||
void CAN_cmd_2FF(int16_t motor1, int16_t motor2, int16_t motor3, CAN_HandleTypeDef*hcan)
|
||
{
|
||
uint32_t send_mail_box;
|
||
tx_meessage_2ff.StdId = 0x1FF;
|
||
tx_meessage_2ff.IDE = CAN_ID_STD;
|
||
tx_meessage_2ff.RTR = CAN_RTR_DATA;
|
||
tx_meessage_2ff.DLC = 0x08;
|
||
can_send_data_2ff[0] = (motor1 >> 8);
|
||
can_send_data_2ff[1] = motor1;
|
||
can_send_data_2ff[2] = (motor2 >> 8);
|
||
can_send_data_2ff[3] = motor2;
|
||
can_send_data_2ff[4] = (motor3 >> 8);
|
||
can_send_data_2ff[5] = motor3;
|
||
can_send_data_2ff[6] = (0 >> 8);
|
||
can_send_data_2ff[7] = 0;
|
||
HAL_CAN_AddTxMessage(hcan, &tx_meessage_2ff, can_send_data_2ff, &send_mail_box);
|
||
}
|
||
|
||
/**************************************
|
||
* 限幅函数
|
||
**************************************/
|
||
void assert_param_rpm(float *rpm){
|
||
if( fabsf(*rpm) > wtrcfg_VESC_COMMAND_ERPM_MAX )
|
||
*rpm = *rpm > 0 ? wtrcfg_VESC_COMMAND_ERPM_MAX : - wtrcfg_VESC_COMMAND_ERPM_MAX ;
|
||
}
|
||
|
||
/**
|
||
* @brief 返回电机数据指针
|
||
* @param[in] i: 电机编号
|
||
* @retval 电机数据指针
|
||
*/
|
||
motor_measure_t *get_motor_point(uint8_t i)
|
||
{
|
||
return &motor_chassis[i];
|
||
}
|
||
|
||
/*
|
||
用转速模式控制电机
|
||
输入参数是controller_id(我用的是65,这个可以在上位机找到)和RPM(1000-50000之间的数)
|
||
*/
|
||
void CAN_VESC_RPM(uint8_t controller_id, float RPM)
|
||
{
|
||
uint32_t id;
|
||
int32_t data;
|
||
uint32_t send_mail_box;
|
||
|
||
id = controller_id | ((uint32_t)CAN_PACKET_SET_RPM << 8);
|
||
assert_param_rpm(&RPM);
|
||
data = (int32_t)(RPM);
|
||
|
||
vesc_tx_message.ExtId = id;
|
||
vesc_tx_message.IDE = CAN_ID_EXT;
|
||
vesc_tx_message.RTR = CAN_RTR_DATA;
|
||
vesc_tx_message.DLC = 0x04;
|
||
vesc_send_data[0] = data >> 24 ;
|
||
vesc_send_data[1] = data >> 16 ;
|
||
vesc_send_data[2] = data >> 8 ;
|
||
vesc_send_data[3] = data ;
|
||
|
||
HAL_CAN_AddTxMessage(&hcan1, &vesc_tx_message, vesc_send_data, &send_mail_box);
|
||
}
|
||
|