通过CAN从0驱动GM6020电机
初始化:使用的是RM的A板的话,由官方A板手册可知芯片是STM32F427IIH6,在CubeMX中配置对应的时钟,enable CAN即可。
首先需要知道的是CAN线先从“主设备”连接到“电调”,然后由“电调”再连接到“电机”。(一个电调对应且只对应一个电机)
然后需要知道“电调”接受CAN报文的格式,它是这样接收的:


“帧格式:DATA”意思就是说上表的DATA[8]是数据帧所蕴含的8Byte,详见下图CAN通讯帧的组成:

CAN的“标识符”不表示目的地址而是 表示发送优先级。
接收节点根据标识符的值,来决定是否接收对应消息。
这里以大疆的CAN信号传输函数为例:
/*** @brief send control current of motor (0x205, 0x206, 0x207, 0x208)* @param[in] yaw: (0x205) 6020 motor control current, range [-30000,30000] * @param[in] pitch: (0x206) 6020 motor control current, range [-30000,30000]* @param[in] shoot: (0x207) 2006 motor control current, range [-10000,10000]* @param[in] rev: (0x208) reserve motor control current* @retval none*/
/*** @brief 发送电机控制电流(0x205,0x206,0x207,0x208)* @param[in] yaw: (0x205) 6020电机控制电流, 范围 [-30000,30000]* @param[in] pitch: (0x206) 6020电机控制电流, 范围 [-30000,30000]* @param[in] shoot: (0x207) 2006电机控制电流, 范围 [-10000,10000]* @param[in] rev: (0x208) 保留,电机控制电流* @retval none*/
void CAN_cmd_gimbal(int16_t yaw, int16_t pitch, int16_t shoot, int16_t rev)
{uint32_t send_mail_box;gimbal_tx_message.StdId = CAN_GIMBAL_ALL_ID;gimbal_tx_message.IDE = CAN_ID_STD;gimbal_tx_message.RTR = CAN_RTR_DATA;gimbal_tx_message.DLC = 0x08;gimbal_can_send_data[0] = (yaw >> 8);gimbal_can_send_data[1] = yaw;gimbal_can_send_data[2] = (pitch >> 8);gimbal_can_send_data[3] = pitch;gimbal_can_send_data[4] = (shoot >> 8);gimbal_can_send_data[5] = shoot;gimbal_can_send_data[6] = (rev >> 8);gimbal_can_send_data[7] = rev;HAL_CAN_AddTxMessage(&GIMBAL_CAN, &gimbal_tx_message, gimbal_can_send_data, &send_mail_box);
}
由于一次数据帧只能传8Byte,而根据电调的接受格式,每次需要2Byte(1Byte高8位,1Byte低8位)来进行电流的控制,因此一个数据帧只能同时控制4个电机。
因此,如果需要控制5~8个电机,需要两帧,每帧对应的标识符也会不同,这里分别是0x200和0x1FF。
官方对于此函数的定义:

————————————————————————————————————————分割线分割线————————————————————————————————————————
至此,大部分理论工作完成了,接下来看RM官方的流程图:

主函数如下:
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_CAN1_Init();MX_CAN2_Init();can_filter_init(); //初始化can接受报文,关闭屏蔽报文的功能,所有报文都接收/* USER CODE BEGIN 2 *//* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){CAN_cmd_chassis(4000, 4000, 4000, 4000);HAL_Delay(2);CAN_cmd_gimbal(10000, 10000, 10000, 10000);HAL_Delay(2);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}
如果想要控制GM6020的转速,调整CAN_cmd_gimbal中第1、2个参数即可。
————————————————————————————————————————分割线分割线————————————————————————————————————————
而电调还有个作用就是:
形成闭环系统
将电机的各项参数反传输给MCU,由MCU进行解析,从而进行反馈调节,接下来是电调反馈报文格式:

同样的,大疆也提供了相应的接受函数:
typedef struct
{uint16_t ecd;int16_t speed_rpm;int16_t given_current;uint8_t temperate;int16_t last_ecd;
} motor_measure_t;/*
motor data, 0:chassis motor1 3508;1:chassis motor3 3508;2:chassis motor3 3508;3:chassis motor4 3508;
4:yaw gimbal motor 6020;5:pitch gimbal motor 6020;6:trigger motor 2006;
电机数据, 0:底盘电机1 3508电机, 1:底盘电机2 3508电机,2:底盘电机3 3508电机,3:底盘电机4 3508电机;
4:yaw云台电机 6020电机; 5:pitch云台电机 6020电机; 6:拨弹电机 2006电机*/static motor_measure_t motor_chassis[7];
GM6020对应的函数:
/*** @brief return the yaw 6020 motor data point* @param[in] none* @retval motor data point*/
/*** @brief 返回yaw 6020电机数据指针* @param[in] none* @retval 电机数据指针*/
const motor_measure_t *get_yaw_gimbal_motor_measure_point(void)
{return &motor_chassis[4];
}/*** @brief return the pitch 6020 motor data point* @param[in] none* @retval motor data point*/
/*** @brief 返回pitch 6020电机数据指针* @param[in] none* @retval 电机数据指针*/
const motor_measure_t *get_pitch_gimbal_motor_measure_point(void)
{return &motor_chassis[5];
}
此数组成员是结构体类型,通过调用结构体的成员,就可以知道相应的数据了。
Fin.
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
