久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1222|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

STM32單片機(jī)控制小米電機(jī)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:861056 發(fā)表于 2024-11-8 10:00 | 只看該作者 回帖獎勵 |倒序?yàn)g覽 |閱讀模式
背景:項(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);
}
```

下圖為說明書中速度模式指令順序

![image-20241021172242942](assets/image-20241021172242942.png)

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)
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 成年人在线观看视频 | 欧美性久久久 | 熟女毛片 | 中文字幕乱码一区二区三区 | 99色在线 | 91av在线视频观看 | 久久这里只有精品首页 | 伊人精品视频 | 99热精品在线观看 | 欧美久久久久 | 日本成人在线观看网站 | 久久久精品网 | www.亚洲一区二区三区 | 日韩av在线一区 | www免费视频| 一区二区日本 | 蜜臀久久99精品久久久久久宅男 | 国产91在线 | 亚洲 | 久久精品国产一区 | 精品欧美乱码久久久久久 | 国产亚洲精品久久久久动 | 日韩一区二区在线免费观看 | 一区二区三区四区不卡 | 成人在线中文字幕 | 亚洲精品91 | 北条麻妃一区二区三区在线视频 | 成人国产一区二区三区精品麻豆 | 国产一区二区日韩 | 在线观看av中文字幕 | 全免费a级毛片免费看视频免 | av黄色免费在线观看 | 另类专区亚洲 | 精品国产成人 | 国产电影一区二区三区爱妃记 | www.夜夜骑 | 久久蜜桃精品 | 精品国产乱码久久久久久闺蜜 | h片在线免费看 | 九色国产 | 女女爱爱视频 | 国产精品一区二区日韩 |