STM32控制小米电机

背景:项目中需要用到可以低速转动的电机,并且力矩需要满足项目条件,因此这里选用小米电机(CyberGear 微电机)。

本实验硬件条件:单片机,STM32F103RET6、CAN通讯芯片。

注:PCB由自己设计绘制,在设计中单片机本身的时钟频率无法与高频率CAN同步,因此需要增加8M晶振。

原理图设计

下图为单片机主电路图
在这里插入图片描述

下图为CAN通讯电路图

在这里插入图片描述

控制程序设计

控制程序都封装在.c文件中了

小米电机ID检查,通信类型为0

/*—————————————————————————————————————————————————————————————————————————————————*/
/** @brief          小米电机ID检查,通信类型为0
  * @param[in]      id:  控制电机CAN_ID【出厂默认0x7F】
  **/
void check_cybergear(uint8_t ID)
{
    uint8_t tx_data[8] = {0};//没有数据
		//扩展ID的组合,依旧是3个部分
    txMsg.ExtId = Communication_Type_GetID<<24|Master_CAN_ID<<8|ID;
	MyCAN_Transmit(txMsg.ExtId,txMsg.DLC,tx_data);//写入指令	
}

小米运控模式指令,通信类型:1

/*——————————————————————————————————————————————————————————————————————————————————*/
/** @brief          小米运控模式指令,通信类型:1
  * @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]={0};//发送数据初始化
    //装填发送数据
	  //将目标角度转化为16位2进制数,对应字节0~1,假设是0x1234
    tx_data[0]=float_to_uint(MechPosition,P_MIN,P_MAX,16)>>8;  //取得是高位的结果,即0x12
    tx_data[1]=float_to_uint(MechPosition,P_MIN,P_MAX,16);  //取得是低位的结果,即0x34
	  //将目标速度转化为16位2进制数,对应字节2~3
    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);  
	  //目标KP
    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);  
	  //目标KD
    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;//装填扩展帧数据
    MyCAN_Transmit(txMsg.ExtId,txMsg.DLC,tx_data);//写入指令	
}

电机反馈数据,通信类型2

/*——————————————————————————————————————————————————————————————————————————————————————*/
/** @brief         电机反馈数据,通信类型2
  * @param[in]     信息存放的地址
  * @retval         none
  */
void Rx_Fifo0_Msg(MI_Motor *Motor)
{
		if (MyCAN_ReceiveFlag())//判断是否接收到报文信息
		{
			uint32_t RxID;
      uint8_t RxLength;
      uint8_t RxData[8];
			//接收信息放到对应的接收报文之中
			MyCAN_Receive(&RxID, &RxLength, RxData);
		  Motor->CAN_ID=(RxID&0xFFFF)>>8;//获取接收数据的ID:保留低16位,其余全变成零,再右移8位,则获得了bit8~bit15的canid
      Motor->Angle=uint16_to_float(RxData[0]<<8|RxData[1],MIN_P,MAX_P,16);//将字节0~1转化位浮点数,即为当前角度
		  Motor->Speed=uint16_to_float(RxData[2]<<8|RxData[3],V_MIN,V_MAX,16);//将字节2~3转化位浮点数,即为当前速度			
		  Motor->Torque=uint16_to_float(RxData[4]<<8|RxData[5],T_MIN,T_MAX,16);//将字节4~5转化位浮点数,即为当前角度				
		  Motor->Temp=(RxData[6]<<8|RxData[7])*Temp_Gain;//将字节4~5转化为当前温度	
		  Motor->error_code=(RxID&0x1F0000)>>16;	
		}
}

使能电机,通信类型为3

/*****************************使能电机,通信类型为3*******************************
  * @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;
    MyCAN_Transmit(txMsg.ExtId,txMsg.DLC,tx_data);//写入指令	
}

电机停止运行,通信类型为4

/************************电机停止运行,通信类型为4********************************
  * @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;
  MyCAN_Transmit(txMsg.ExtId,txMsg.DLC,tx_data);//写入指令	
}

小米电机初始化

/**
  * @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);        //使能电机
}

单个参数读取,通信类型17

/*************************单个参数读取,通信类型17******************
*@brief         电机参数读取
*@param[in]     ID,电机的ID号
*/
void check_param_cybergear(MI_Motor *Motor, uint8_t index)
{
  uint8_t tx_data[8]={0};
  txMsg.ExtId = Communication_Type_GetSingleParameter<<24|Master_CAN_ID<<8|Motor->CAN_ID;//装填扩展帧数据
  tx_data[0]=index>>8;//高8位
  tx_data[1]=index;//低8位
  MyCAN_Transmit(txMsg.ExtId,txMsg.DLC,tx_data);//写入指令	
}

对应说明书的单个参数写入,通信类型为18

/******************对应说明书的单个参数写入,通信类型为18*************
  * @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]={0};//写入的数据
	//扩展ID,包括三个部分:通信类型、主ID、电机ID
	txMsg.ExtId = Communication_Type_SetSingleParameter<<24|Master_CAN_ID<<8|Motor->CAN_ID;
	//参见说明书的通信类型18里面,Index的相关应用方法,Index共
	tx_data[0]=Index;      //高8位
	tx_data[1]=Index>>8;   //低8位
	tx_data[2]=0x00;
	tx_data[3]=0x00;
	//如果参数类型为浮点型,则对应的数据所占字节数为4,对应的数据需要转化为8个字节
	if(Value_type == 'f'){
		Float_to_Byte(Value);//将数值转化为4个byte 作为返回值
		tx_data[4]=byte[3];//高8位
		tx_data[5]=byte[2];
		tx_data[6]=byte[1];
		tx_data[7]=byte[0];//低8位		
	}
	//如果参数类型为uint8,只有一个字节
	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();
  MyCAN_Transmit(txMsg.ExtId,txMsg.DLC,tx_data);//写入指令
}

小米速度模式指令

此代码根据电机说明书中给出的速度模式通讯顺序编写

/*——————————————————————————————————————————————————————————————————————————————————*/
/** @brief          小米速度模式指令,通信类型:2
  * @param[in]      Motor:  目标电机结构体
  * @param[in]      CurValue: 电流设置[0,23] A
  * @param[in]      SpeedValue: 速度设置[-30,30] rad
  * @retval         none
  **/
void motor_speedmode(MI_Motor *Motor, float CurValue, float SpeedValue)
{   
		//设置limit_cur参数(最大电流指令)
		Set_Motor_Parameter(Motor,Limit_Cur,CurValue,'f');
		DelayMs(10);
		//设置spd_ref参数(转速模式转速指令)
		Set_Motor_Parameter(Motor,Spd_Ref,SpeedValue,'f');
		DelayMs(10);
}

下图为说明书中速度模式指令顺序

STM32控制小米电机在这里插入图片描述

main函数中根据此顺序进行小米电机初始化,然后设置速度模式,使能电机,写入单个参数limit_cur(最大电流),然后写入单个参数spd_ref(最大速度)。即可让电机按照速度模式转动。

下面为main函数:

MI_Motor Cyber;
uint8_t Motor_ID=0x01; //电机ID,初始状态默认为0x7F,这里调整为0x01
uint8_t Mode = Speed_mode;//电机工作模式(0.运动模式Motion_mode 1. 位置模式Position_mode 2. 速度模式Speed_mode 3. 电流模式Current_mode)
uint32_t id;

/*
************************************************************
*	函数名称:	Hardware_Init
*
*	函数功能:	硬件初始化
************************************************************
*/
void Hardware_Init(void)
{
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//中断控制器分组设置

	Delay_Init();									//systick初始化
	
	uart1_init(115200);							//串口1
	uart2_init(115200);							//串口2
	
	LED_Init();
	MyCAN_Init();
	
}

/*
************************************************************
*	函数名称:	main
*
*	函数功能:	
************************************************************
*/
int main(void)
{
	Hardware_Init();				//初始化外围硬件
	DelayMs(1000);

	//以下用于调用程序验证相应的通信数据是否准确
	init_cybergear(&Cyber, 0X01, Mode);//初始化电机
	//*校验用的内容
  check_cybergear(Cyber.CAN_ID);//小米电机ID检查,通信类型为0
	//电机运控模式
//	motor_controlmode(&Cyber, 0, 0, 1, 0, 0.5);
	//电机速度模式
	motor_speedmode(&Cyber,23,1);
	
	while(1)
	{
		LED_STA();
//		MyCAN_Transmit(0X555, 8 ,AA);
		DelayMs(10);
	}
}

详情可通过下面两篇文章
Can2.0自由报文通讯~~基于小米微电机控制讲解之报文扩展
小米电机与STM32——CAN通信
文章源码
STM32控制小米电机

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大脑还没宕机

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值