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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

STM32編程實現(xiàn)直流電機(jī)位置速度PID雙閉環(huán)控制 HAL庫源程序

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:663189 發(fā)表于 2021-7-23 15:44 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
雙環(huán)閉環(huán)

單片機(jī)源程序如下:
  1. /**
  2.   ******************************************************************************
  3.   * 文件名程: main.c
  4.   * 作    者: 學(xué)習(xí)小組
  5.   * 功    能: GM37-545_位置速度閉環(huán)控制
  6.   ******************************************************************************
  7.   * 說明:
  8.   ******************************************************************************
  9.   */
  10. /* 包含頭文件 ----------------------------------------------------------------*/
  11. #include "stm32f4xx_hal.h"
  12. #include "key.h"
  13. #include "encoder.h"
  14. #include "usartx.h"
  15. #include "BDCMotor.h"
  16. /* 私有類型定義 --------------------------------------------------------------*/
  17. typedef struct
  18. {
  19.   __IO int32_t  SetPoint;   //設(shè)定目標(biāo) Desired Value
  20.   __IO float    SumError;   //誤差累計
  21.   __IO float    Proportion; //比例常數(shù) Proportional Const
  22.   __IO float    Integral;   //積分常數(shù) Integral Const
  23.   __IO float    Derivative; //微分常數(shù) Derivative Const
  24.   __IO int      LastError;  //Error[-1]
  25.   __IO int      PrevError;  //Error[-2]
  26. }PID_TypeDef;

  27. /* 私有宏定義 ----------------------------------------------------------------*/
  28. #define SPEEDRATIO    270
  29. #define ENCODER_RESOLUTION    11
  30. #define PPR           ((SPEEDRATIO*ENCODER_RESOLUTION)*4) // Pulse/Round 每圈可捕獲到的脈沖數(shù)

  31. /*************************************/
  32. // 定義PID相關(guān)宏
  33. // 這三個參數(shù)設(shè)定對電機(jī)運行影響非常大
  34. // PID參數(shù)跟采樣時間息息相關(guān)
  35. /*************************************/
  36. #define  SPD_P_DATA     50.0f        // P參數(shù)
  37. #define  SPD_I_DATA     8.5f         // I參數(shù)
  38. #define  SPD_D_DATA     0.0f         // D參數(shù)
  39. #define  TARGET_SPEED   10.0f        // 目標(biāo)速度    10r/m

  40. #define  LOC_P_DATA     0.01f       // P參數(shù)
  41. #define  LOC_I_DATA     0.0f       // D參數(shù)
  42. #define  LOC_D_DATA     0.08f       // D參數(shù)
  43. #define  TARGET_LOC     (3*PPR)    // 目標(biāo)位置    11880 Pulse = 1r

  44. /* 私有變量 ------------------------------------------------------------------*/
  45. __IO uint8_t  Start_flag = 0;       // PID 開始標(biāo)志
  46. uint32_t Motor_Dir = CW;             // 電機(jī)方向

  47. __IO int32_t tmpPWM_DutySpd = 0;
  48. __IO int32_t tmpPWM_Duty = 0;

  49. __IO int32_t Sample_Pulse;           // 編碼器捕獲值 Pulse
  50. __IO int32_t LastSample_Pulse;       // 編碼器捕獲值 Pulse
  51. __IO int32_t Spd_PPS;                // 速度值 Pulse/Sample
  52. __IO float Spd_RPM;                  // 速度值 r/m

  53. /* 擴(kuò)展變量 ------------------------------------------------------------------ */
  54. extern __IO uint32_t uwTick;

  55. /* PID結(jié)構(gòu)體 */
  56. PID_TypeDef  sPID,lPID;               // PID參數(shù)結(jié)構(gòu)體

  57. /* 擴(kuò)展變量 ------------------------------------------------------------------*/
  58. /* 私有函數(shù)原形 --------------------------------------------------------------*/
  59. void PID_ParamInit(void) ;
  60. int32_t SpdPIDCalc(float NextPoint);
  61. int32_t LocPIDCalc(int32_t NextPoint);
  62. /* 函數(shù)體 --------------------------------------------------------------------*/
  63. /**
  64.   * 函數(shù)功能: 系統(tǒng)時鐘配置
  65.   * 輸入?yún)?shù): 無
  66.   * 返 回 值: 無
  67.   * 說    明: 無
  68.   */
  69. void SystemClock_Config(void)
  70. {
  71.   RCC_OscInitTypeDef RCC_OscInitStruct;
  72.   RCC_ClkInitTypeDef RCC_ClkInitStruct;

  73.   __HAL_RCC_PWR_CLK_ENABLE();                                     // 使能PWR時鐘

  74.   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);  // 設(shè)置調(diào)壓器輸出電壓級別1

  75.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;      // 外部晶振,8MHz
  76.   RCC_OscInitStruct.HSEState = RCC_HSE_ON;                        // 打開HSE
  77.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;                    // 打開PLL
  78.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;            // PLL時鐘源選擇HSE
  79.   RCC_OscInitStruct.PLL.PLLM = 8;                                 // 8分頻MHz
  80.   RCC_OscInitStruct.PLL.PLLN = 336;                               // 336倍頻
  81.   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;                     // 2分頻,得到168MHz主時鐘
  82.   RCC_OscInitStruct.PLL.PLLQ = 7;                                 // USB/SDIO/隨機(jī)數(shù)產(chǎn)生器等的主PLL分頻系數(shù)
  83.   HAL_RCC_OscConfig(&RCC_OscInitStruct);

  84.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  85.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  86.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;       // 系統(tǒng)時鐘:168MHz
  87.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;              // AHB時鐘: 168MHz
  88.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;               // APB1時鐘:42MHz
  89.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;               // APB2時鐘:84MHz
  90.   HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);

  91.   HAL_RCC_EnableCSS();                                            // 使能CSS功能,優(yōu)先使用外部晶振,內(nèi)部時鐘源為備用

  92.          // HAL_RCC_GetHCLKFreq()/1000    1ms中斷一次
  93.         // HAL_RCC_GetHCLKFreq()/100000         10us中斷一次
  94.         // HAL_RCC_GetHCLKFreq()/1000000 1us中斷一次
  95.   HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);                 // 配置并啟動系統(tǒng)滴答定時器
  96.   /* 系統(tǒng)滴答定時器時鐘源 */
  97.   HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  98.   /* 系統(tǒng)滴答定時器中斷優(yōu)先級配置 */
  99.   HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
  100. }

  101. /**
  102.   * 函數(shù)功能: 主函數(shù).
  103.   * 輸入?yún)?shù): 無
  104.   * 返 回 值: 無
  105.   * 說    明: 無
  106.   */
  107. int main(void)
  108. {
  109.   /* 復(fù)位所有外設(shè),初始化Flash接口和系統(tǒng)滴答定時器 */
  110.   HAL_Init();
  111.   /* 配置系統(tǒng)時鐘 */
  112.   SystemClock_Config();
  113.   /* 串口初始化 */
  114.   MX_USARTx_Init();
  115.   /* 按鍵初始化 */
  116.   KEY_GPIO_Init();
  117.   /* 編碼器初始化及使能編碼器模式 */
  118.   ENCODER_TIMx_Init();

  119.         /* 高級控制定時器初始化并配置PWM輸出功能 */
  120.   BDCMOTOR_TIMx_Init();

  121.   /* 啟動定時器通道和互補(bǔ)通道PWM輸出 */
  122.   PWM_Duty = 0;
  123.   __HAL_TIM_SET_COMPARE(&htimx_BDCMOTOR,TIM_CHANNEL_1,PWM_Duty);  // 0%

  124.   /* PID 參數(shù)初始化 */
  125.   PID_ParamInit();
  126.   /* 無限循環(huán) */
  127.   while (1)
  128.   {
  129.     /* 停止按鈕 */
  130.     if(KEY1_StateRead()==KEY_DOWN)
  131.     {
  132.       if( lPID.Proportion < 0 )
  133.       {
  134.         Motor_Dir = CW;
  135.         BDDCMOTOR_DIR_CW();
  136.         PWM_Duty = -PWM_Duty;
  137.       }
  138.       else
  139.       {
  140.         Motor_Dir = CCW;
  141.         BDDCMOTOR_DIR_CCW();
  142.       }
  143.       __HAL_TIM_SET_COMPARE(&htimx_BDCMOTOR,TIM_CHANNEL_1,0);  // 0%
  144.       Start_flag = 1;
  145.     }
  146.     if(KEY2_StateRead()==KEY_DOWN)
  147.     {
  148.       SHUTDOWN_MOTOR();
  149.       HAL_TIM_PWM_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1);
  150.       HAL_TIMEx_PWMN_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1);         // 停止輸出
  151.     }
  152.     if(KEY3_StateRead()==KEY_DOWN)    // 圈數(shù)+1
  153.     {
  154.       lPID.SetPoint += PPR;
  155.     }
  156.     if(KEY4_StateRead()==KEY_DOWN)    // 圈數(shù)-1
  157.     {
  158.       lPID.SetPoint -= PPR;
  159.     }
  160.   }
  161. }

  162. /**
  163.   * 函數(shù)功能: 系統(tǒng)滴答定時器中斷回調(diào)函數(shù)
  164.   * 輸入?yún)?shù): 無
  165.   * 返 回 值: 無
  166.   * 說    明: 每隔一定的時間就執(zhí)行pid算法
  167.   */
  168. void HAL_SYSTICK_Callback(void)
  169. {
  170.   __IO int32_t ADC_Resul= 0;
  171.   __IO float Volt_Result = 0;

  172.   /* 位置環(huán)周期100ms */
  173.   if(uwTick % 100 == 0)
  174.   {
  175.     /* 獲取當(dāng)前位置值,編碼器4倍頻之后的數(shù)值 */
  176.     Sample_Pulse = (OverflowCount*CNT_MAX) + (int32_t)__HAL_TIM_GET_COUNTER(&htimx_Encoder);

  177.     /* 計算PID結(jié)果 */
  178.     if(Start_flag == 1)
  179.     {
  180.       tmpPWM_DutySpd = LocPIDCalc(Sample_Pulse);

  181.       /* 設(shè)定速度環(huán)的目標(biāo)值 */
  182.       if(tmpPWM_DutySpd >= TARGET_SPEED)
  183.         tmpPWM_DutySpd = TARGET_SPEED;
  184.       if(tmpPWM_DutySpd <= -TARGET_SPEED)
  185.         tmpPWM_DutySpd = -TARGET_SPEED;
  186.     }
  187.   }
  188.   /* 速度環(huán)周期50ms */
  189.   if(uwTick % 50 == 0)
  190.   {
  191.     /* 獲得當(dāng)前速度 */
  192.     Sample_Pulse = (OverflowCount*CNT_MAX) + \
  193.                     (int32_t)__HAL_TIM_GET_COUNTER(&htimx_Encoder);
  194.     Spd_PPS = Sample_Pulse - LastSample_Pulse;
  195.     LastSample_Pulse = Sample_Pulse ;

  196.     /* 11線編碼器,270減速比,一圈脈沖信號是11*270*4 PPR */
  197.     Spd_RPM = ((((float)Spd_PPS/(float)PPR)*20.0f)*(float)60);//單位是rpm

  198.     /* 計算PID結(jié)果 */
  199.     if(Start_flag == 1)
  200.     {
  201.       sPID.SetPoint = tmpPWM_DutySpd;
  202.       PWM_Duty = SpdPIDCalc(Spd_RPM);
  203.       if(PWM_Duty < 0)
  204.       {
  205.         Motor_Dir = CW;
  206.         BDDCMOTOR_DIR_CW();
  207.         PWM_Duty = -PWM_Duty;
  208.       }
  209.       else
  210.       {
  211.         Motor_Dir = CCW;
  212.         BDDCMOTOR_DIR_CCW();
  213.       }

  214.       __HAL_TIM_SET_COMPARE(&htimx_BDCMOTOR,TIM_CHANNEL_1,PWM_Duty );

  215.     }
  216.     printf("LOC:%d Sped: %2.2f r/m \n",Sample_Pulse,
  217.            Spd_RPM );
  218.   }
  219. }

  220. /******************** PID 控制設(shè)計 ***************************/
  221. /**
  222.   * 函數(shù)功能: PID參數(shù)初始化
  223.   * 輸入?yún)?shù): 無
  224.   * 返 回 值: 無
  225.   * 說    明: 無
  226.   */
  227. void PID_ParamInit()
  228. {
  229.     sPID.LastError = 0;           // Error[-1]
  230.     sPID.PrevError = 0;           // Error[-2]
  231.     sPID.Proportion = SPD_P_DATA; // 比例常數(shù) Proportional Const
  232.     sPID.Integral = SPD_I_DATA;   // 積分常數(shù)  Integral Const
  233.     sPID.Derivative = SPD_D_DATA; // 微分常數(shù) Derivative Const
  234.     sPID.SetPoint = TARGET_SPEED; // 設(shè)定目標(biāo)Desired Value

  235.     lPID.LastError = 0;           // Error[-1]
  236.     lPID.PrevError = 0;           // Error[-2]
  237.     lPID.Proportion = LOC_P_DATA; // 比例常數(shù) Proportional Const
  238.     lPID.Integral = LOC_I_DATA;   // 積分常數(shù)  Integral Const
  239.     lPID.Derivative = LOC_D_DATA; // 微分常數(shù) Derivative Const
  240.     lPID.SetPoint = TARGET_LOC;   // 設(shè)定目標(biāo)Desired Value
  241. }


  242. /**
  243.   * 函數(shù)名稱:速度閉環(huán)PID控制設(shè)計
  244.   * 輸入?yún)?shù):當(dāng)前控制量
  245.   * 返 回 值:目標(biāo)控制量
  246.   * 說    明:無
  247.   */
  248. int32_t SpdPIDCalc(float NextPoint)
  249. {
  250.   float iError,dError;
  251.   iError = sPID.SetPoint - NextPoint; //偏差

  252.   if((iError<0.2f )&& (iError>-0.2f))
  253.     iError = 0.0f;

  254.   sPID.SumError += iError; //積分
  255.     /* 設(shè)定積分上限 */
  256.   if(lPID.SumError >= TARGET_SPEED*10)
  257.     lPID.SumError = TARGET_SPEED*10;
  258.   if(lPID.SumError <= -TARGET_SPEED*10)
  259.     lPID.SumError = -TARGET_SPEED*10;

  260.   dError = iError - sPID.LastError; //微分
  261.   sPID.LastError = iError;
  262.   return (int32_t)(sPID.Proportion * (float)iError //比例項
  263.   + sPID.Integral * (float)sPID.SumError //積分項
  264.   + sPID.Derivative * (float)dError); //微分項
  265. }

  266. /**
  267.   * 函數(shù)名稱:位置閉環(huán)PID控制設(shè)計
  268.   * 輸入?yún)?shù):當(dāng)前控制量
  269.   * 返 回 值:目標(biāo)控制量
  270.   * 說    明:無
  271.   */
  272. int32_t LocPIDCalc(int32_t NextPoint)
  273. {
  274.   int32_t iError,dError;
  275.   iError = lPID.SetPoint - NextPoint; //偏差
  276.   /* 設(shè)定閉環(huán)死區(qū) */
  277.   if((iError >= -50) && (iError <= 50))
  278.   {
  279.     iError = 0;
  280.     lPID.SumError = 0;
  281.   }

  282.   /* 積分分離 */
  283.   if((iError >= -1000) && (iError <= 1000))
  284.   {
  285.     lPID.SumError += iError; //積分

  286.     /* 設(shè)定積分上限 */
  287.     if(lPID.SumError >= 1000)
  288.       lPID.SumError = 1000;
  289.     if(lPID.SumError <= -1000)
  290.       lPID.SumError = -1000;
  291.   }

  292.   dError = iError - lPID.LastError; //微分
  293.   lPID.LastError = iError;

  294.   return (int32_t)(lPID.Proportion * (float)iError //比例項
  295.   + lPID.Integral * (float)lPID.SumError //積分項
  296.   + lPID.Derivative * (float)dError);    //微分項
  297. }

  298. /**********************************END OF FILE****************************/
復(fù)制代碼

所有代碼51hei附件下載:
STM32編程實現(xiàn)_位置速度PID雙閉環(huán)控制.7z (1.53 MB, 下載次數(shù): 103)

評分

參與人數(shù) 1黑幣 +20 收起 理由
admin + 20 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂1 踩
回復(fù)

使用道具 舉報

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

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 久久在线 | 国产欧美精品一区二区色综合朱莉 | 新疆少妇videos高潮 | 亚洲综合一区二区三区 | 一区二区在线不卡 | 精品成人佐山爱一区二区 | 高清18麻豆 | 欧美在线视频一区 | 久久免费精品 | 97国产精品视频人人做人人爱 | 久热爱 | 日本一区二区三区在线观看 | 欧美aaaa视频 | 国产精品毛片一区二区三区 | 国产精品久久久久久久久久久免费看 | 97日韩精品| 99久久中文字幕三级久久日本 | 亚洲一二视频 | 精品国产一区二区三区久久狼黑人 | 久久精品国产一区二区电影 | 国产精品色 | 欧美成年人视频在线观看 | 午夜激情视频 | 欧美做暖暖视频 | 欧美一极视频 | 涩涩导航 | 国产精品久久久久久久久免费丝袜 | 婷婷综合五月天 | 久久久久国| 久久美女视频 | 国产精品久久久久久模特 | 久久com| h片在线观看免费 | 国产目拍亚洲精品99久久精品 | 成人免费福利 | 999精彩视频 | 黄频免费 | 亚洲色视频 | 日韩欧美国产精品一区二区 | 免费看片国产 | 国产欧美日韩在线 |