STM32 CubeMX CAN通信配置&闭环控制Robomaster 6020电机

此次使用的是6020电机,即选择STM32F105R8T6芯片。

一、实现电机的双向通信

1、发送电机控制命令(见STM32 CubeMX CAN通信配置&开环控制Robomaster 2006电机);

2、接收电机反馈数据(电机速度);

(1)配置过滤器

因为之前的CSDN中有启动can通信和激活can通信的函数,所以可以删除重复的部分。

void can_filter_init(void)//过滤器(can总线上理论可以挂载无数多的设备,为把一些不必要的设备过滤掉)用过滤器
{

    CAN_FilterTypeDef can_filter_st;//因为此项目没有多余的设备,所以都配置为0
    can_filter_st.FilterActivation = ENABLE;
    can_filter_st.FilterMode = CAN_FILTERMODE_IDMASK;
    can_filter_st.FilterScale = CAN_FILTERSCALE_32BIT;
    can_filter_st.FilterIdHigh = 0x0000;
    can_filter_st.FilterIdLow = 0x0000;
    can_filter_st.FilterMaskIdHigh = 0x0000;
    can_filter_st.FilterMaskIdLow = 0x0000;
    can_filter_st.FilterBank = 0;
    can_filter_st.FilterFIFOAssignment = CAN_RX_FIFO0;
    HAL_CAN_ConfigFilter(&hcan1, &can_filter_st);//配置过滤器
    HAL_CAN_Start(&hcan1);//启动can通信
    HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);//激活CAN中断通知功能
}

(2)调用过滤器相关的函数

can_filter_init();//can通信过滤器, 如果不配置过滤器,会接收不到函数

(3)启动中断接收

只需要打开RX0中断,然后重新运行keil软件。

(4)、 在中断中插入回调函数

uint16_t GetSpeed,SetSpeed;
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)//回调函数
{
    CAN_RxHeaderTypeDef rx_header;
    uint8_t rx_data[8];

    HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header, rx_data);//将数据存放于rx_data数组中

    switch (rx_header.StdId)
    {

        case 0x205://根据电机具体id号设置 0x204+id(6020手册上找)
        {

						GetSpeed = (uint16_t)((rx_data)[2] << 8 | (rx_data)[3]); // 根据手册 2、3 位分别为电机转速的高八位、低八位
            break;																										// 此处是将两个数据合并为一个数据
        }

    }
}

二、配置pid

首先对要用到的函数进行定义。

typedef struct
{
	float Kp, Ki, Kd,taxget,e,I_Band,i_out,d_out,last_e,totalout,p_out,current;
}pid;

pid Motor_pid;
extern uint16_t GetSpeed,SetSpeed;

因为已经定义了GetSpeed,SetSpeed变量,这里用extern表示在别的地方已经定义过了。然后开始用pid进行计算

void pid_calc(pid* pid)//该函数为PID计算
{
	pid->e = pid->taxget - pid->current;//计算偏差值
	
	pid->p_out = (int32_t )(pid->Kp *pid->e);//计算p的输出值(比例)

	pid->i_out += (int32_t )(pid->Ki * pid->e);//计算i的输出值(积分)

	pid->d_out = (int32_t )(pid->Kd * (pid->e - pid->last_e));//计算d的输出值(微分)
	
	pid->totalout = pid->p_out + pid->i_out + pid->d_out;//总输出

	pid->last_e = pid->e;//记录当前偏差值
}

然后就可以在while函数里进行调用了

    SetSpeed = 60;//
    Motor_pid.Kp=60;//
    Motor_pid.Ki=5;//
      while (1)
      {
        Motor_pid.current=(float)GetSpeed;
		Motor_pid.taxget=SetSpeed;

		pid_calc(&Motor_pid);//调用计算pid的函数

		CAN_cmd_motor(Motor_pid.totalout,0, 0, 0);//向id1的电机发送电流值为200
      }

这里要注意的是can发送时一定要加delay函数,否则接收不到数据。

HAL_Delay(10);//用delay才能接收到数据

之后编译运行,就可以实现电机的闭环控制了。

  • 9
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值