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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1195|回復: 0
收起左側

STM32單片機控制小米電機

[復制鏈接]
ID:861056 發表于 2024-11-8 10:00 | 顯示全部樓層 |閱讀模式
背景:項目中需要用到可以低速轉動的電機,并且力矩需要滿足項目條件,因此這里選用小米電機(CyberGear 微電機)。

本實驗硬件條件:單片機,STM32F103RET6、CAN通訊芯片。

注:PCB由自己設計繪制,在設計中單片機本身的時鐘頻率無法與高頻率CAN同步,因此需要增加8M晶振。

## 原理圖設計

下圖為單片機主電路圖



下圖為CAN通訊電路圖



## 控制程序設計

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

## 小米電機ID檢查,通信類型為0

```c
/*—————————————————————————————————————————————————————————————————————————————————*/
/** @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

```C
/*——————————————————————————————————————————————————————————————————————————————————*/
/** @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

```C
/*——————————————————————————————————————————————————————————————————————————————————————*/
/** @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

```C
/*****************************使能電機,通信類型為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

```C
/************************電機停止運行,通信類型為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);//寫入指令        
}
```

### 小米電機初始化

```C
/**
  * @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

```C
/*************************單個參數讀取,通信類型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

```C
/******************對應說明書的單個參數寫入,通信類型為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);//寫入指令
}
```

### 小米速度模式指令

此代碼根據電機說明書中給出的速度模式通訊順序編寫

```C
/*——————————————————————————————————————————————————————————————————————————————————*/
/** @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);
}
```

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

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

main函數中根據此順序進行小米電機初始化,然后設置速度模式,使能電機,寫入單個參數limit_cur(最大電流),然后寫入單個參數spd_ref(最大速度)。即可讓電機按照速度模式轉動。

下面為main函數:

```C
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);
        }
}

原理圖: 無
仿真: 無
代碼: STM32控制小米電機.7z (198.2 KB, 下載次數: 3)
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产精品一区二区三区在线 | 日韩欧美国产一区二区三区 | 操皮视频 | 免费观看一级特黄欧美大片 | 成人二区 | 日韩中文字幕在线观看 | 欧美在线一区视频 | 国产精品永久 | a级在线观看 | 日韩一级一区 | 欧美2区 | 中文在线www| www日本高清 | 日韩av成人在线 | 国产黄色网址在线观看 | 国产福利精品一区 | 欧美一区二区三区视频在线播放 | 一区在线观看视频 | 色综合久久久久 | 激情在线视频 | 一区二区在线看 | 日韩中文字幕一区二区 | 毛片一区二区 | 久久久久久久久久久久91 | 成人免费看电影 | 一级黄色片一级黄色片 | 91操操操 | 黄色av一区 | a级大片免费观看 | av电影一区二区 | 99精彩视频 | 久久久久久久国产 | 日本不卡一区二区三区在线观看 | 久久久久国产一区二区三区 | 国产午夜精品理论片a大结局 | 久久伊人影院 | 欧美一区免费 | 毛片一级电影 | 国产精品午夜电影 | 精品视频一区二区三区在线观看 | 国产精品亚洲视频 |