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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2900|回復: 0
打印 上一主題 下一主題
收起左側

57&42步進電機_速度閉環_位置式PID STM32源程序

[復制鏈接]
跳轉到指定樓層
樓主
ID:301684 發表于 2019-9-25 09:50 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
黑石H7開發板步進電機驅動  親測可用
  1. #include "stm32h7xx_hal.h"
  2. #include "bsp_led.h"
  3. #include "bsp_key.h"
  4. #include "bsp_debug_usart.h"
  5. #include "bsp_stepmotor.h"
  6. #include "bsp_encoder.h"
  7. #include <string.h>
  8. #include <math.h>
  9. #include <stdbool.h>
  10. #include <stdlib.h>

  11. /* 私有類型定義 --------------------------------------------------------------*/
  12. typedef struct
  13. {
  14.   __IO float    SetPoint;    // 目標值  單位:r/m
  15.   __IO int32_t  LastError;   // 前一次誤差   
  16.   __IO int32_t  PrevError;   // 前兩次誤差
  17.   __IO int32_t  SumError;    // 累計誤差
  18.   float    Proportion;       // Kp系數
  19.   float    Integral;         // Ki系數
  20.   float    Derivative;       // Kd系數
  21. }PID_Typedef;

  22. /* 私有宏定義 ----------------------------------------------------------------*/
  23. #define    PID_DEFAULT_P          0.4f  //
  24. #define    PID_DEFAULT_I          0.2f  //
  25. #define    PID_DEFAULT_D          0.0f  //
  26. #define    SPEED                  5.3f  // 移動速度 mm/s

  27. #define    MM_ROUND               5   // 絲桿導程 mm/r
  28. #define    INTERVAL               20  //  采樣和PID計算時間間隔 ms

  29. /* 私有變量 ------------------------------------------------------------------*/

  30. __IO static PID_Typedef vPID; // 速度環PID結構體

  31. __IO uint16_t time_count = 0; // 時間計數,每1ms增加一(與滴答定時器頻率有關)
  32. __IO uint8_t Time_Flag   = 0; // 任務時間標記
  33. bool Start_flag = false;      // 啟動/停止

  34. /* 擴展變量 ------------------------------------------------------------------*/

  35. /* 私有函數原形 --------------------------------------------------------------*/

  36. static void SystemClock_Config( void );
  37. static void CPU_CACHE_Enable( void );

  38. /* 函數體 --------------------------------------------------------------------*/
  39.   
  40. /**
  41.   * 函數功能:位置式PID速度環計算
  42.   * 輸入參數: @NextPoint    由編碼器得到的計數值
  43.   *           @TargetVal    目標值
  44.   * 返 回 值:經過PID運算得到的增量值
  45.   * 說    明:位置式 PID 速度環控制設計,計算得到的結果仍然是速度值
  46.   */
  47. float IncPIDCalc(int NextPoint,float TargetVal)       //臨時變量,期望值
  48. {
  49.   float iError = 0,iIncpid = 0;                       //當前誤差
  50.   
  51.   iError = TargetVal - NextPoint;                     // 增量計算
  52.   if((iError < 0.5f)&&(iError>-0.5f))
  53.     iError = 0;                                       // |e| < 0.5,不做調整
  54.   
  55.   vPID.PrevError = iError - vPID.LastError;
  56.   vPID.SumError += iError;
  57.   iIncpid=(vPID.Proportion * iError)                  // E[k]項
  58.               +(vPID.Integral * vPID.SumError)        // E[k-1]項
  59.               +(vPID.Derivative * vPID.PrevError);    // E[k-2]項
  60.   
  61.   vPID.PrevError = vPID.LastError;                    // 存儲誤差,用于下次計算
  62.   vPID.LastError = iError;
  63.   return(iIncpid);                                    // 返回增量值
  64. }

  65. /**
  66.   * 函數功能: PID結構體初始化
  67.   * 輸入參數: 無
  68.   * 返 回 值: 無
  69.   * 說    明: 初始化PID參數
  70.   */
  71. void Init_PIDStruct()
  72. {
  73.   vPID.SetPoint   = SPEED;          // 目標值  單位:mm/s
  74.   vPID.Proportion = PID_DEFAULT_P;  // Kp系數
  75.   vPID.Integral   = PID_DEFAULT_I;  // Ki系數
  76.   vPID.Derivative = PID_DEFAULT_D;  // Kd系數
  77.   vPID.LastError  = 0;
  78.   vPID.PrevError  = 0;
  79.   vPID.SumError   = 0;
  80. }
  81. /**
  82.   * 函數功能: 主函數.
  83.   * 輸入參數: 無
  84.   * 返 回 值: 無
  85.   * 說    明: 無
  86.   */
  87. int main(void)
  88. {
  89.   float     Exp_Val     = 0;  // PID計算出來的期望值
  90.   float     Vel_Target  = 0;; // 速度目標值
  91.   int16_t   MSF = 0;          // 電機反饋速度
  92.   int32_t   Enc_Cap     = 0;  // 編碼器輸入捕獲數
  93.   int32_t   lastEnc_Cap = 0;  // 編碼器上一次捕獲值
  94.   
  95.   CPU_CACHE_Enable();
  96.   /* 復位所有外設,初始化Flash接口和系統滴答定時器 */
  97.   HAL_Init();
  98.   /* 配置系統時鐘 */
  99.   SystemClock_Config();
  100.   /* 板載LED,按鍵初始化 */
  101.   LED_GPIO_Init();
  102.   KEY_GPIO_Init();
  103.   /* 初始化PID參數結構體 */
  104.   Init_PIDStruct();
  105.   /* 調試串口初始化 */
  106.   MX_DEBUG_UART_Init();

  107.   /* 編碼器定時器初始化并配置輸入捕獲功能 */
  108.   ENCODER_TIMx_Init();
  109.   /* 啟動編碼器接口 */
  110.   HAL_TIM_Encoder_Start(&htimx_Encoder, TIM_CHANNEL_ALL);
  111.   
  112.   HAL_Delay(10);
  113.   
  114.   /* 步進電機定時器初始化*/
  115.   SMOTOR1_TIMx_Init();
  116.   
  117.   /* 首先禁止步進電機動作*/
  118.   SMotor_Set_State(MOTOR_DISABLE);
  119.   /* 比較輸出和中斷 */
  120.   HAL_TIM_OC_Stop_IT(&htimx_SMotor1,TIM_CHANNEL_1);
  121.   
  122.   /* 移動速度轉換為PID的目標值
  123.    * 目標值是每個采樣周期的編碼器計數值,SetPoint是移動速度(mm/s),INTERVAL是采樣周期間隔
  124.    * 1mm/s對應的編碼器計數值是 ENCODER_RESOLUTION/MM_ROUND -> 2400/5 = 480 Hz
  125.    * 每個采樣周期之間的編碼器計數值就是 480/(1000/INTERVAL) = 9.6f
  126.    * SetPoint*9.6 就是 SetPoint mm/s 對應的采樣周期間隔編碼器計數值
  127.    */
  128.   Vel_Target = round(fabs(vPID.SetPoint) * (ENCODER_RESOLUTION/MM_ROUND)/(1000/INTERVAL)  );//每單位采樣周期內的脈沖數(頻率)
  129.   
  130.   __HAL_DBGMCU_FREEZE_TIM8();// debug 的時候停止定時器時鐘
  131.   __HAL_DBGMCU_FREEZE_TIM2();// debug 的時候停止定時器時鐘
  132.   while (1)
  133.   {
  134.    
  135.     /* KEY1啟動電機,并且使能PID計算 */
  136.     if(KEY1_StateRead() == KEY_DOWN)
  137.     {
  138.       SMotor_Set_State(MOTOR_ENABLE);
  139.       Exp_Val = 0;
  140.       Init_PIDStruct();
  141.       if(vPID.SetPoint < 0 )
  142.         SMotor_Set_Dir( MOTOR_DIR_CCW );
  143.       else
  144.         SMotor_Set_Dir( MOTOR_DIR_CW );
  145.       SMotor_Set_Speed(0.01); // 低速啟動
  146.       HAL_TIM_OC_Start_IT(&htimx_SMotor1,TIM_CHANNEL_1);
  147.       Start_flag = true;           // 啟動/停止
  148.       printf("啟動PID計算\n");
  149.       printf("設置的目標值是 %f mm/s \n",vPID.SetPoint);//
  150.       printf("對應的編碼器計數值是 %d pulse/s \n",(int32_t)Vel_Target*(1000/INTERVAL));//
  151.     }
  152.     /* KEY2停止電機,并且停止PID計算 */
  153.     if(KEY2_StateRead() == KEY_DOWN)
  154.     {
  155.       SMotor_Set_State(MOTOR_DISABLE);
  156.       HAL_TIM_OC_Stop_IT(&htimx_SMotor1,TIM_CHANNEL_1);
  157.       Start_flag = false;           // 啟動/停止
  158.     }
  159.     /* KEY3/KEY4用于調控電機位置 */
  160.     if(KEY3_StateRead() == KEY_DOWN)
  161.     {
  162.       Start_flag = false;          // 啟動/停止
  163.       SMotor_Set_State( MOTOR_ENABLE );
  164.       SMotor_Set_Dir( MOTOR_DIR_CW );
  165.       SMotor_Set_Speed( 160 );     //設置低速啟動
  166.       HAL_TIM_OC_Start_IT(&htimx_SMotor1, SMOTOR1_PUL_TIMx_CHANNELx);
  167.     }
  168.     if(KEY4_StateRead() == KEY_DOWN)
  169.     {
  170.       Start_flag = false;          // 啟動/停止
  171.       SMotor_Set_State( MOTOR_ENABLE );
  172.       SMotor_Set_Dir( MOTOR_DIR_CCW );
  173.       SMotor_Set_Speed( 160 );     // 設置低速啟動
  174.       HAL_TIM_OC_Start_IT(&htimx_SMotor1, SMOTOR1_PUL_TIMx_CHANNELx);
  175.     }
  176.     // 采樣和控制周期為20ms
  177.     if(Time_Flag & 0x01)
  178.     {
  179.       //獲得編碼器的脈沖值
  180.       Enc_Cap  = YS_Encoder_GetCounting();

  181.       //M法 測速度
  182.       MSF = Enc_Cap - lastEnc_Cap;
  183.       lastEnc_Cap = Enc_Cap;
  184.       MSF = abs(MSF);
  185.       
  186.       Exp_Val    = IncPIDCalc(MSF, Vel_Target);
  187.       Exp_Val    = fabs(Exp_Val);

  188.       SMotor_Set_Speed(Exp_Val);
  189.       Time_Flag &= ~0x01;
  190.     }
  191.    
  192.     // 數據發送周期為1s, 顯示轉速
  193.     if(Time_Flag & 0x02)
  194.     {
  195.       int32_t pulse = YS_Encoder_GetCounting();
  196.       static int32_t tmp = 0;
  197.       float speed = (float)( pulse - tmp ) / ENCODER_RESOLUTION ;
  198.       
  199.       printf("1s內的編碼器計數值:  %d\n", pulse - tmp);
  200.       printf("電機轉速:  %.2f r/s  \n", speed );
  201.       printf("移動速度:  %.1f mm/s \n", speed*5.0f);// 1r就是5mm
  202.       tmp = pulse ;
  203.       Time_Flag &= ~0x02;
  204.     }
  205.   }
  206. }
  207. /**
  208.   * 函數功能: 系統滴答定時器中斷回調函數
  209.   * 輸入參數: 無
  210.   * 返 回 值: 無
  211.   * 說    明: 每發生一次滴答定時器中斷進入該回調函數一次
  212.   */
  213. void HAL_SYSTICK_Callback(void)
  214. {
  215.   // 每1ms自動增一
  216.   time_count++;         
  217.   if( (time_count % INTERVAL) == 0)// 20ms讀取一次編碼器數值
  218.   {
  219.     if(Start_flag )
  220.       Time_Flag |= 0x01;
  221.   }
  222.   else if(time_count >= 1000)      // 1s發送一次數據
  223.   {
  224.     Time_Flag |= 0x02;
  225.     time_count = 0;
  226.   }
  227. }


  228. /**
  229.   * 函數功能: 定時器比較輸出中斷回調函數
  230.   * 輸入參數: htim:定時器句柄指針
  231.   * 返 回 值: 無
  232.   * 說    明: 控制脈沖輸出
  233.   */
  234. void HAL_TIM_OC_DelayElapsedCallback( TIM_HandleTypeDef * htim)
  235. {
  236.   uint32_t Toggle = 0;
  237.   
  238.   if(htim == &htimx_SMotor1)
  239.   {
  240.     /* 設置下一次中斷的間隔 */
  241.     Toggle = __HAL_TIM_GET_COMPARE(&htimx_SMotor1, SMOTOR1_PUL_TIMx_CHANNELx);
  242.     Toggle += SMotor1.PulseWidth; // 計算實際的比較值
  243.     __HAL_TIM_SET_COMPARE(&htimx_SMotor1, SMOTOR1_PUL_TIMx_CHANNELx, (uint16_t)Toggle);
  244.   }
  245. }
  246. /**
  247.   * 函數功能: 系統時鐘配置
  248.   * 輸入參數: 無
  249.   * 返 回 值: 無
  250.   * 說    明: 無
  251.   */
  252. static void SystemClock_Config(void)
  253. {
  254.   RCC_OscInitTypeDef RCC_OscInitStruct={0};
  255.   RCC_ClkInitTypeDef RCC_ClkInitStruct={0};

  256.   /* 使能PWR配置更新 */
  257.   MODIFY_REG(PWR->CR3, PWR_CR3_SCUEN, 0);

  258.   /* 設置調壓器輸出電壓級別1 */
  259.   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  260.   /* 等待D3區域VOS 輸出準備就緒 */
  261.   while ((PWR->D3CR & (PWR_D3CR_VOSRDY)) != PWR_D3CR_VOSRDY) // 等待內核電源就緒
  262.   {
  263.    
  264.   }
  265.   /* RCC 內部/外部晶振配置 ,用于CPU,AHB,APH總線時鐘 */
  266.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;// 外部晶振
  267.   RCC_OscInitStruct.HSEState = RCC_HSE_ON;//選擇外部時鐘晶振 HSE 25MHz
  268.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;//使能PLL
  269.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;//PLL時鐘源選擇HSE
  270.   RCC_OscInitStruct.PLL.PLLM = 5;  // 外部時鐘2分頻,得到5MHz 作為PLL時鐘源
  271.   RCC_OscInitStruct.PLL.PLLN = 160;// PLL 160倍頻,得到800MHz PLLCLK
  272.   RCC_OscInitStruct.PLL.PLLP = 2;  // PLLCLK 2分頻 得到400MHz SYSCLK
  273.   RCC_OscInitStruct.PLL.PLLQ = 2;  // PLLCLK 2分頻 得到400MHz用于部分外設的時鐘
  274.   RCC_OscInitStruct.PLL.PLLR = 2;  // PLLCLK 2分頻 得到400MHz用于部分外設的時鐘
  275.   RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;// PLL時鐘輸入范圍4-8MHz
  276.   RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;// PLL時鐘輸出范圍192-836MHz
  277.   RCC_OscInitStruct.PLL.PLLFRACN = 0;  // 此參數用于微調 PLL1 VCO 范圍0~2^13-1
  278.   HAL_RCC_OscConfig(&RCC_OscInitStruct);
  279.   
  280.   /* RCC CPU,AHB,APH總線時鐘配置*/
  281.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  282.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
  283.                               |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
  284.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;//SYSCLK 時鐘源400MHz
  285.   RCC_ClkInitStruct.SYSCLKDivider  = RCC_SYSCLK_DIV1;// SYSCLK 1分頻 HCLK=400MHz
  286.   RCC_ClkInitStruct.AHBCLKDivider  = RCC_HCLK_DIV2;  // HCLK 2分頻,AHB = 200Mhz
  287.   RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2; // APB3 2分頻,APB3 = 100MHz
  288.   RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2; // APB1 2分頻,APB1 = 100MHz
  289.   RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2; // APB2 2分頻,APB2 = 100MHz
  290.   RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2; // APB4 2分頻,APB4 = 100MHz
  291.   HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
  292.   

  293.   /* 使能時鐘安全機制 */
  294.   HAL_RCC_EnableCSS();

  295.   /* 滴答定時器配置1ms */
  296.   // SystemCoreClock/1000    1ms中斷一次
  297.         // SystemCoreClock/100000         10us中斷一次
  298.         // SystemCoreClock/1000000 1us中斷一次
  299.   HAL_SYSTICK_Config(SystemCoreClock/(1000));

  300.   /* 系統滴答定時器時鐘源 */
  301.   HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  302.   /* 系統滴答定時器中斷優先級配置 */
  303.   HAL_NVIC_SetPriority(SysTick_IRQn, 1, 1);
  304. }

  305. /**
  306.   * 函數功能: 使能CPU L1-Cache
  307.   * 輸入參數: 無
  308.   * 返 回 值: 無
  309.   * 說    明: 無
  310.   */
  311. static void CPU_CACHE_Enable(void)
  312. {
  313.   /* 使能 I-Cache */
  314.   SCB_EnableICache();

  315.   /* 使能 D-Cache */
  316.   SCB_EnableDCache();
  317. }

  318. /********** (C) COPYRIGHT 2019-2030 硬石嵌入式開發團隊 *******END OF FILE******/
復制代碼


YS-H7Multi_HAL_MOTOR-236. 57&amp;42步進電機_速度閉環_位置式PID.7z

7.37 MB, 下載次數: 78, 下載積分: 黑幣 -5

黑石H7步進電機驅動

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

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产一级片久久久 | 天天躁日日躁狠狠躁白人 | 青青草一区二区三区 | 九九热这里 | 91在线视频国产 | 亚洲一区播放 | 精品九九 | 91成人在线视频 | 日韩欧美手机在线 | 午夜国产羞羞视频免费网站 | 亚洲成人精品 | 亚洲高清在线 | 自拍在线 | 国产成人精品一区二区三区网站观看 | 欧美日韩毛片 | 欧美一级黄色片免费观看 | 亚洲精选一区 | 激情五月综合 | 蜜桃在线视频 | 97日韩精品 | 成人在线播放网站 | 中文精品一区二区 | 国产欧美精品一区二区三区 | 亚洲精品免费在线观看 | 国产免费一区二区 | 亚洲国产成人精品女人久久久 | 一级黄色录像毛片 | 亚洲欧美一区二区三区在线 | 日本一区二区三区免费观看 | 欧美爱爱视频 | 在线国产视频观看 | 91在线最新 | 久久99精品久久久久婷婷 | 免费国产成人av | 久久久毛片 | 国产精品亚洲第一区在线暖暖韩国 | 伊伊综合网 | 日韩一区中文字幕 | a毛片视频网站 | 国产精品精品视频一区二区三区 | 三级黄色片在线播放 |