|
背景:項(xiàng)目中需要用到可以低速轉(zhuǎn)動的電機(jī),并且力矩需要滿足項(xiàng)目條件,因此這里選用小米電機(jī)(CyberGear 微電機(jī))。
本實(shí)驗(yàn)硬件條件:單片機(jī),STM32F103RET6、CAN通訊芯片。
注:PCB由自己設(shè)計(jì)繪制,在設(shè)計(jì)中單片機(jī)本身的時鐘頻率無法與高頻率CAN同步,因此需要增加8M晶振。
## 原理圖設(shè)計(jì)
下圖為單片機(jī)主電路圖
下圖為CAN通訊電路圖
## 控制程序設(shè)計(jì)
控制程序都封裝在.c文件中了
## 小米電機(jī)ID檢查,通信類型為0
```c
/*—————————————————————————————————————————————————————————————————————————————————*/
/** @brief 小米電機(jī)ID檢查,通信類型為0
* @param[in] id: 控制電機(jī)CAN_ID【出廠默認(rèn)0x7F】
**/
void check_cybergear(uint8_t ID)
{
uint8_t tx_data[8] = {0};//沒有數(shù)據(jù)
//擴(kuò)展ID的組合,依舊是3個部分
txMsg.ExtId = Communication_Type_GetID<<24|Master_CAN_ID<<8|ID;
MyCAN_Transmit(txMsg.ExtId,txMsg.DLC,tx_data);//寫入指令
}
```
### 小米運(yùn)控模式指令,通信類型:1
```C
/*——————————————————————————————————————————————————————————————————————————————————*/
/** @brief 小米運(yùn)控模式指令,通信類型:1
* @param[in] Motor: 目標(biāo)電機(jī)結(jié)構(gòu)體
* @param[in] torque: 力矩設(shè)置[-12,12] N*M
* @param[in] MechPosition: 位置設(shè)置[-12.5,12.5] rad
* @param[in] speed: 速度設(shè)置[-30,30] rpm
* @param[in] kp: 比例參數(shù)設(shè)置
* @param[in] kd: 微分參數(shù)設(shè)置
* @retval none
**/
void motor_controlmode(MI_Motor *Motor,float torque, float MechPosition, float speed, float kp, float kd)
{
uint8_t tx_data[8]={0};//發(fā)送數(shù)據(jù)初始化
//裝填發(fā)送數(shù)據(jù)
//將目標(biāo)角度轉(zhuǎn)化為16位2進(jìn)制數(shù),對應(yīng)字節(jié)0~1,假設(shè)是0x1234
tx_data[0]=float_to_uint(MechPosition,P_MIN,P_MAX,16)>>8; //取得是高位的結(jié)果,即0x12
tx_data[1]=float_to_uint(MechPosition,P_MIN,P_MAX,16); //取得是低位的結(jié)果,即0x34
//將目標(biāo)速度轉(zhuǎn)化為16位2進(jìn)制數(shù),對應(yīng)字節(jié)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);
//目標(biāo)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);
//目標(biāo)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;//裝填擴(kuò)展幀數(shù)據(jù)
MyCAN_Transmit(txMsg.ExtId,txMsg.DLC,tx_data);//寫入指令
}
```
### 電機(jī)反饋數(shù)據(jù),通信類型2
```C
/*——————————————————————————————————————————————————————————————————————————————————————*/
/** @brief 電機(jī)反饋數(shù)據(jù),通信類型2
* @param[in] 信息存放的地址
* @retval none
*/
void Rx_Fifo0_Msg(MI_Motor *Motor)
{
if (MyCAN_ReceiveFlag())//判斷是否接收到報(bào)文信息
{
uint32_t RxID;
uint8_t RxLength;
uint8_t RxData[8];
//接收信息放到對應(yīng)的接收報(bào)文之中
MyCAN_Receive(&RxID, &RxLength, RxData);
Motor->CAN_ID=(RxID&0xFFFF)>>8;//獲取接收數(shù)據(jù)的ID:保留低16位,其余全變成零,再右移8位,則獲得了bit8~bit15的canid
Motor->Angle=uint16_to_float(RxData[0]<<8|RxData[1],MIN_P,MAX_P,16);//將字節(jié)0~1轉(zhuǎn)化位浮點(diǎn)數(shù),即為當(dāng)前角度
Motor->Speed=uint16_to_float(RxData[2]<<8|RxData[3],V_MIN,V_MAX,16);//將字節(jié)2~3轉(zhuǎn)化位浮點(diǎn)數(shù),即為當(dāng)前速度
Motor->Torque=uint16_to_float(RxData[4]<<8|RxData[5],T_MIN,T_MAX,16);//將字節(jié)4~5轉(zhuǎn)化位浮點(diǎn)數(shù),即為當(dāng)前角度
Motor->Temp=(RxData[6]<<8|RxData[7])*Temp_Gain;//將字節(jié)4~5轉(zhuǎn)化為當(dāng)前溫度
Motor->error_code=(RxID&0x1F0000)>>16;
}
}
```
### 使能電機(jī),通信類型為3
```C
/*****************************使能電機(jī),通信類型為3*******************************
* @brief 使能小米電機(jī)
* @param[in] Motor:對應(yīng)控制電機(jī)結(jié)構(gòu)體
* @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);//寫入指令
}
```
### 電機(jī)停止運(yùn)行,通信類型為4
```C
/************************電機(jī)停止運(yùn)行,通信類型為4********************************
* @brief 停止電機(jī)
* @param[in] Motor:對應(yīng)控制電機(jī)結(jié)構(gòu)體
* @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;//清除錯誤位設(shè)置
txMsg.ExtId = Communication_Type_MotorStop<<24|Master_CAN_ID<<8|Motor->CAN_ID;
MyCAN_Transmit(txMsg.ExtId,txMsg.DLC,tx_data);//寫入指令
}
```
### 小米電機(jī)初始化
```C
/**
* @brief 小米電機(jī)初始化
* @param[in] Motor: 電機(jī)結(jié)構(gòu)體
* @param[in] Can_Id: 小米電機(jī)ID(默認(rèn)0x7F)
* @param[in] Motor_Num: 電機(jī)編號
* @param[in] mode: 電機(jī)工作模式(0.運(yùn)動模式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發(fā)送:標(biāo)準(zhǔn)幀清零
txMsg.ExtId = 0; //配置CAN發(fā)送:擴(kuò)展幀清零
txMsg.IDE = CAN_ID_EXT; //配置CAN發(fā)送:擴(kuò)展幀
txMsg.RTR = CAN_RTR_DATA; //配置CAN發(fā)送:數(shù)據(jù)幀
txMsg.DLC = 0x08; //配置CAN發(fā)送:數(shù)據(jù)長度
Motor->CAN_ID=Can_Id; //ID設(shè)置
set_mode_cybergear(Motor,mode);//設(shè)置電機(jī)模式
start_cybergear(Motor); //使能電機(jī)
}
```
### 單個參數(shù)讀取,通信類型17
```C
/*************************單個參數(shù)讀取,通信類型17******************
*@brief 電機(jī)參數(shù)讀取
*@param[in] ID,電機(jī)的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;//裝填擴(kuò)展幀數(shù)據(jù)
tx_data[0]=index>>8;//高8位
tx_data[1]=index;//低8位
MyCAN_Transmit(txMsg.ExtId,txMsg.DLC,tx_data);//寫入指令
}
```
### 對應(yīng)說明書的單個參數(shù)寫入,通信類型為18
```C
/******************對應(yīng)說明書的單個參數(shù)寫入,通信類型為18*************
* @brief 寫入電機(jī)參數(shù)
* @param[in] Motor:對應(yīng)控制電機(jī)結(jié)構(gòu)體
* @param[in] Index:寫入?yún)?shù)對應(yīng)地址
* @param[in] Value:寫入?yún)?shù)值
* @param[in] Value_type:寫入?yún)?shù)數(shù)據(jù)類型,可以對照字節(jié)數(shù)進(jìn)行區(qū)分
* @retval none
*/
static void Set_Motor_Parameter(MI_Motor *Motor,uint16_t Index,float Value,char Value_type)
{
uint8_t tx_data[8]={0};//寫入的數(shù)據(jù)
//擴(kuò)展ID,包括三個部分:通信類型、主ID、電機(jī)ID
txMsg.ExtId = Communication_Type_SetSingleParameter<<24|Master_CAN_ID<<8|Motor->CAN_ID;
//參見說明書的通信類型18里面,Index的相關(guān)應(yīng)用方法,Index共
tx_data[0]=Index; //高8位
tx_data[1]=Index>>8; //低8位
tx_data[2]=0x00;
tx_data[3]=0x00;
//如果參數(shù)類型為浮點(diǎn)型,則對應(yīng)的數(shù)據(jù)所占字節(jié)數(shù)為4,對應(yīng)的數(shù)據(jù)需要轉(zhuǎn)化為8個字節(jié)
if(Value_type == 'f'){
Float_to_Byte(Value);//將數(shù)值轉(zhuǎn)化為4個byte 作為返回值
tx_data[4]=byte[3];//高8位
tx_data[5]=byte[2];
tx_data[6]=byte[1];
tx_data[7]=byte[0];//低8位
}
//如果參數(shù)類型為uint8,只有一個字節(jié)
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);//寫入指令
}
```
### 小米速度模式指令
此代碼根據(jù)電機(jī)說明書中給出的速度模式通訊順序編寫
```C
/*——————————————————————————————————————————————————————————————————————————————————*/
/** @brief 小米速度模式指令,通信類型:2
* @param[in] Motor: 目標(biāo)電機(jī)結(jié)構(gòu)體
* @param[in] CurValue: 電流設(shè)置[0,23] A
* @param[in] SpeedValue: 速度設(shè)置[-30,30] rad
* @retval none
**/
void motor_speedmode(MI_Motor *Motor, float CurValue, float SpeedValue)
{
//設(shè)置limit_cur參數(shù)(最大電流指令)
Set_Motor_Parameter(Motor,Limit_Cur,CurValue,'f');
DelayMs(10);
//設(shè)置spd_ref參數(shù)(轉(zhuǎn)速模式轉(zhuǎn)速指令)
Set_Motor_Parameter(Motor,Spd_Ref,SpeedValue,'f');
DelayMs(10);
}
```
下圖為說明書中速度模式指令順序

main函數(shù)中根據(jù)此順序進(jìn)行小米電機(jī)初始化,然后設(shè)置速度模式,使能電機(jī),寫入單個參數(shù)limit_cur(最大電流),然后寫入單個參數(shù)spd_ref(最大速度)。即可讓電機(jī)按照速度模式轉(zhuǎn)動。
下面為main函數(shù):
```C
MI_Motor Cyber;
uint8_t Motor_ID=0x01; //電機(jī)ID,初始狀態(tài)默認(rèn)為0x7F,這里調(diào)整為0x01
uint8_t Mode = Speed_mode;//電機(jī)工作模式(0.運(yùn)動模式Motion_mode 1. 位置模式Position_mode 2. 速度模式Speed_mode 3. 電流模式Current_mode)
uint32_t id;
/*
************************************************************
* 函數(shù)名稱: Hardware_Init
*
* 函數(shù)功能: 硬件初始化
************************************************************
*/
void Hardware_Init(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中斷控制器分組設(shè)置
Delay_Init(); //systick初始化
uart1_init(115200); //串口1
uart2_init(115200); //串口2
LED_Init();
MyCAN_Init();
}
/*
************************************************************
* 函數(shù)名稱: main
*
* 函數(shù)功能:
************************************************************
*/
int main(void)
{
Hardware_Init(); //初始化外圍硬件
DelayMs(1000);
//以下用于調(diào)用程序驗(yàn)證相應(yīng)的通信數(shù)據(jù)是否準(zhǔn)確
init_cybergear(&Cyber, 0X01, Mode);//初始化電機(jī)
//*校驗(yàn)用的內(nèi)容
check_cybergear(Cyber.CAN_ID);//小米電機(jī)ID檢查,通信類型為0
//電機(jī)運(yùn)控模式
// motor_controlmode(&Cyber, 0, 0, 1, 0, 0.5);
//電機(jī)速度模式
motor_speedmode(&Cyber,23,1);
while(1)
{
LED_STA();
// MyCAN_Transmit(0X555, 8 ,AA);
DelayMs(10);
}
}
原理圖: 無
仿真: 無
代碼:
STM32控制小米電機(jī).7z
(198.2 KB, 下載次數(shù): 3)
2024-11-8 19:50 上傳
點(diǎn)擊文件名下載附件
程序 下載積分: 黑幣 -5
|
|