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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

STM32編程實現直流有刷電機位置速度電流三閉環PID控制程序

  [復制鏈接]
跳轉到指定樓層
樓主
ID:831137 發表于 2021-6-27 20:31 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
固件庫開發的直流電機pid控制系統

單片機源程序如下:
  1. /**
  2.   ******************************************************************************
  3.   * 文件名程: BDCMOTOR.c
  4.   * 作    者: 學習小組
  5.   * 功    能: 有刷直流電機驅動板基本驅動程序
  6.   ******************************************************************************
  7.   * 說明:
  8.   ******************************************************************************
  9.   */
  10. /* 包含頭文件 ----------------------------------------------------------------*/
  11. #include "BDCMotor.h"

  12. /* 私有類型定義 --------------------------------------------------------------*/
  13. /* 私有宏定義 ----------------------------------------------------------------*/
  14. /* 私有變量 ------------------------------------------------------------------*/
  15. TIM_HandleTypeDef htimx_BDCMOTOR;
  16. __IO int16_t PWM_Duty=BDCMOTOR_DUTY_ZERO;         // 占空比:PWM_Duty/BDCMOTOR_TIM_PERIOD*100%
  17. /* 擴展變量 ------------------------------------------------------------------*/
  18. /* 私有函數原形 --------------------------------------------------------------*/
  19. /* 函數體 --------------------------------------------------------------------*/
  20. /**
  21.   * 函數功能: 基本定時器硬件初始化配置
  22.   * 輸入參數: htim_base:基本定時器句柄類型指針
  23.   * 返 回 值: 無
  24.   * 說    明: BDCMOTOR相關GPIO初始化配置,該函數被HAL庫內部調用.
  25.   */
  26. void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
  27. {
  28.   /* BDCMOTOR相關GPIO初始化配置 */
  29.   if(htim == &htimx_BDCMOTOR)
  30.   {
  31.     GPIO_InitTypeDef GPIO_InitStruct;
  32.     /* 引腳端口時鐘使能 */
  33.     __HAL_RCC_GPIOE_CLK_ENABLE();
  34.     BDCMOTOR_TIM_CH1_GPIO_CLK_ENABLE();
  35.     BDCMOTOR_TIM_CH1N_GPIO_CLK_ENABLE();
  36.     SHUTDOWN_GPIO_CLK_ENABLE();

  37.     /* BDCMOTOR輸出脈沖控制引腳IO初始化 */
  38.     GPIO_InitStruct.Pin = BDCMOTOR_TIM_CH1_PIN;
  39.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  40.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  41.     GPIO_InitStruct.Alternate = GPIO_AFx_TIMx;
  42.     HAL_GPIO_Init(BDCMOTOR_TIM_CH1_PORT, &GPIO_InitStruct);
  43.    
  44.     GPIO_InitStruct.Pin = BDCMOTOR_TIM_CH1N_PIN;
  45.     HAL_GPIO_Init(BDCMOTOR_TIM_CH1N_PORT, &GPIO_InitStruct);
  46.       
  47.     __HAL_RCC_GPIOE_CLK_ENABLE();
  48.     GPIO_InitStruct.Pin = GPIO_PIN_11;
  49.     HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
  50.    
  51.     GPIO_InitStruct.Pin = SHUTDOWN_PIN;
  52.     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  53.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  54.     GPIO_InitStruct.Alternate = 0;
  55.     HAL_GPIO_Init(SHUTDOWN_PORT, &GPIO_InitStruct);
  56.    
  57.     /* 使能電機控制引腳 */
  58.     ENABLE_MOTOR();

  59.   }
  60. }

  61. /**
  62.   * 函數功能: BDCMOTOR定時器初始化
  63.   * 輸入參數: 無
  64.   * 返 回 值: 無
  65.   * 說    明: 無
  66.   */
  67. void BDCMOTOR_TIMx_Init(void)
  68. {
  69.   TIM_ClockConfigTypeDef sClockSourceConfig;             // 定時器時鐘
  70.   TIM_OC_InitTypeDef sConfigOC;
  71.   TIM_BreakDeadTimeConfigTypeDef  sBDTConfig;            // 定時器死區時間比較輸出

  72.   /* 基本定時器外設時鐘使能 */
  73.   BDCMOTOR_TIM_RCC_CLK_ENABLE();
  74.   
  75.   /* 定時器基本環境配置 */
  76.   htimx_BDCMOTOR.Instance = BDCMOTOR_TIMx;                                 // 定時器編號
  77.   htimx_BDCMOTOR.Init.Prescaler = BDCMOTOR_TIM_PRESCALER;                  // 定時器預分頻器
  78.   htimx_BDCMOTOR.Init.CounterMode = TIM_COUNTERMODE_UP;                  // 計數方向:向上計數
  79.   htimx_BDCMOTOR.Init.Period = BDCMOTOR_TIM_PERIOD;                        // 定時器周期
  80.   htimx_BDCMOTOR.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;              // 時鐘分頻
  81.   htimx_BDCMOTOR.Init.RepetitionCounter = BDCMOTOR_TIM_REPETITIONCOUNTER;  // 重復計數器
  82.   /* 初始化定時器比較輸出環境 */
  83.   HAL_TIM_PWM_Init(&htimx_BDCMOTOR);

  84.   /* 定時器時鐘源配置 */
  85.   sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;       // 使用內部時鐘源
  86.   HAL_TIM_ConfigClockSource(&htimx_BDCMOTOR, &sClockSourceConfig);

  87.   /* 死區剎車配置,實際上配置無效電平是高電平 */
  88.   sBDTConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE ;
  89.   sBDTConfig.BreakPolarity = TIM_BREAKPOLARITY_LOW ;
  90.   sBDTConfig.BreakState = TIM_BREAK_DISABLE ;
  91.   sBDTConfig.DeadTime = 0 ;
  92.   sBDTConfig.LockLevel = TIM_LOCKLEVEL_OFF ;
  93.   sBDTConfig.OffStateIDLEMode= TIM_OSSI_DISABLE ;
  94.   sBDTConfig.OffStateRunMode = TIM_OSSR_ENABLE ;
  95.   HAL_TIMEx_ConfigBreakDeadTime(&htimx_BDCMOTOR,&sBDTConfig);

  96. /* 定時器比較輸出配置 */
  97.   sConfigOC.OCMode = TIM_OCMODE_PWM1;                  // 比較輸出模式:PWM1模式
  98.   sConfigOC.Pulse =  PWM_Duty;                         // 占空比
  99.   sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;          // 輸出極性
  100.   sConfigOC.OCNPolarity = TIM_OCNPOLARITY_LOW;        // 互補通道輸出極性
  101.   sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;           // 快速模式
  102.   sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;       // 空閑電平
  103.   sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;     // 互補通道空閑電平
  104.   HAL_TIM_PWM_ConfigChannel(&htimx_BDCMOTOR, &sConfigOC, TIM_CHANNEL_1);

  105.         /* 啟動定時器 */
  106.   HAL_TIM_Base_Start(&htimx_BDCMOTOR);
  107. }


  108. /**
  109.   * 函數功能: 基本定時器硬件反初始化配置
  110.   * 輸入參數: htim_base:基本定時器句柄類型指針
  111.   * 返 回 值: 無
  112.   * 說    明: 該函數被HAL庫內部調用
  113.   */
  114. void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base)
  115. {
  116.   if(htim_base->Instance==BDCMOTOR_TIMx)
  117.   {
  118.     /* 基本定時器外設時鐘禁用 */
  119.     BDCMOTOR_TIM_RCC_CLK_DISABLE();
  120.    
  121.     HAL_GPIO_DeInit(BDCMOTOR_TIM_CH1_PORT,BDCMOTOR_TIM_CH1_PIN);
  122.     HAL_GPIO_DeInit(BDCMOTOR_TIM_CH1N_PORT,BDCMOTOR_TIM_CH1N_PIN);
  123.   }
  124. }

  125. /************************************END OF FILE**************************/
復制代碼

  1. /**
  2.   ******************************************************************************
  3.   * 文件名程: main.c
  4.   * 作    者: 學習小組
  5.   * 功    能: 位置速度電流閉環控制
  6.   ******************************************************************************
  7.   * 說明:
  8.   ******************************************************************************
  9.   */
  10. /* 包含頭文件 ----------------------------------------------------------------*/
  11. #include "stm32f4xx_hal.h"
  12. #include "key.h"
  13. #include "encoder.h"
  14. #include "usartx.h"
  15. #include "adc.h"
  16. #include "BDCMotor.h"
  17. /* 私有類型定義 --------------------------------------------------------------*/
  18. typedef struct
  19. {
  20.   __IO int32_t  SetPoint;     // 設定目標 Desired Value
  21.   __IO float    SumError;     // 誤差累計
  22.   __IO float    Proportion;   // 比例常數 Proportional Const
  23.   __IO float    Integral;     // 積分常數 Integral Const
  24.   __IO float    Derivative;   // 微分常數 Derivative Const
  25.   __IO int      LastError;    // Error[-1]
  26.   __IO int      PrevError;    // Error[-2]
  27. }PID_TypeDef;

  28. /* 私有宏定義 ----------------------------------------------------------------*/
  29. #define ADC_Base      8            // 取2的整數倍作為緩存區大小,得到14bits
  30. /* 使用DMA傳輸數據,采集n個數據點的時間是0.65ms,采樣率大約是 1500 KHz */
  31. #define ADC_BUFFER    1024         // 采樣數據緩存區


  32. #define SPEEDRATIO    270
  33. #define ENCODER_RESOLUTION    11
  34. #define PPR           ((SPEEDRATIO*ENCODER_RESOLUTION)*4) // Pulse/Round 每圈可捕獲到的脈沖數

  35. /*************************************/
  36. // 定義PID相關宏
  37. // 這三個參數設定對電機運行影響非常大
  38. // PID參數跟采樣時間息息相關
  39. /*************************************/
  40. #define  CUR_P_DATA     0.35f       // P參數
  41. #define  CUR_I_DATA     0.6f        // I參數
  42. #define  CUR_D_DATA     0.0f        // D參數
  43. #define  TARGET_CURRENT 300         // 最大電流值 300mA

  44. #define  SPD_P_DATA     4.5f        // P參數
  45. #define  SPD_I_DATA     0.5f        // I參數
  46. #define  SPD_D_DATA     0.0f        // D參數
  47. #define  TARGET_SPEED   20.0f       // 目標速度    20r/m

  48. #define  LOC_P_DATA     0.009f      // P參數
  49. #define  LOC_I_DATA     0.002f      // I參數
  50. #define  LOC_D_DATA     0.04f       // D參數
  51. #define  TARGET_LOC     (3*PPR)     // 目標位置    11880Pulse = 1r

  52. /* 私有變量 ------------------------------------------------------------------*/
  53. __IO uint8_t  Start_flag = 0;       // PID 開始標志
  54. uint32_t Motor_Dir = CW;             // 電機方向

  55. __IO int32_t tmpPWM_DutySpd = 0;
  56. __IO int32_t tmpPWM_Duty = 0;
  57. /* 用于保存轉換計算后的數值 */
  58. __IO float ADC_VoltBus;                                                          // 總線電壓值

  59. __IO int32_t Sample_Pulse;           // 編碼器捕獲值 Pulse
  60. __IO int32_t LastSample_Pulse;       // 編碼器捕獲值 Pulse
  61. __IO int32_t Spd_PPS;                // 速度值 Pulse/Sample
  62. __IO float Spd_RPM;                  // 速度值 r/m

  63. /* AD轉換結果值 */
  64. __IO int16_t ADC_ConvValueHex[ADC_BUFFER];  // AD轉換結果緩存
  65. __IO int32_t AverSum = 0;                   // 平均值的累加值
  66. __IO int32_t AverCnt = 0;                   // 平均值的計數器
  67. __IO uint32_t OffsetCnt_Flag = 0 ;          // 偏差值的計數器標志
  68. __IO int32_t  OffSetHex ;           // 偏差值
  69. /* 擴展變量 ------------------------------------------------------------------ */
  70. extern __IO uint32_t uwTick;

  71. /* PID結構體 */
  72. PID_TypeDef  cPID,sPID,lPID;               // PID參數結構體

  73. /* 擴展變量 ------------------------------------------------------------------*/
  74. /* 私有函數原形 --------------------------------------------------------------*/
  75. void PID_ParamInit(void) ;
  76. int32_t CurPIDCalc(int32_t NextPoint);
  77. int32_t SpdPIDCalc(float NextPoint);
  78. int32_t LocPIDCalc(int32_t NextPoint);
  79. int32_t ADC_GetSampleAvgN(int16_t *Data, uint32_t N );
  80. /* 函數體 --------------------------------------------------------------------*/
  81. /**
  82.   * 函數功能: 系統時鐘配置
  83.   * 輸入參數: 無
  84.   * 返 回 值: 無
  85.   * 說    明: 無
  86.   */
  87. void SystemClock_Config(void)
  88. {
  89.   RCC_OscInitTypeDef RCC_OscInitStruct;
  90.   RCC_ClkInitTypeDef RCC_ClkInitStruct;

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

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

  93.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;      // 外部晶振,8MHz
  94.   RCC_OscInitStruct.HSEState = RCC_HSE_ON;                        // 打開HSE
  95.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;                    // 打開PLL
  96.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;            // PLL時鐘源選擇HSE
  97.   RCC_OscInitStruct.PLL.PLLM = 8;                                 // 8分頻MHz
  98.   RCC_OscInitStruct.PLL.PLLN = 336;                               // 336倍頻
  99.   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;                     // 2分頻,得到168MHz主時鐘
  100.   RCC_OscInitStruct.PLL.PLLQ = 7;                                 // USB/SDIO/隨機數產生器等的主PLL分頻系數
  101.   HAL_RCC_OscConfig(&RCC_OscInitStruct);

  102.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  103.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  104.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;       // 系統時鐘:168MHz
  105.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;              // AHB時鐘: 168MHz
  106.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;               // APB1時鐘:42MHz
  107.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;               // APB2時鐘:84MHz
  108.   HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);

  109.   HAL_RCC_EnableCSS();                                            // 使能CSS功能,優先使用外部晶振,內部時鐘源為備用
  110.   
  111.         // HAL_RCC_GetHCLKFreq()/1000    1ms中斷一次
  112.         // HAL_RCC_GetHCLKFreq()/100000         10us中斷一次
  113.         // HAL_RCC_GetHCLKFreq()/1000000 1us中斷一次
  114.   HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);                 // 配置并啟動系統滴答定時器
  115.   /* 系統滴答定時器時鐘源 */
  116.   HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  117.   /* 系統滴答定時器中斷優先級配置 */
  118.   HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
  119. }
  120.          
  121. /**
  122.   * 函數功能: 主函數.
  123.   * 輸入參數: 無
  124.   * 返 回 值: 無                                                                     
  125.   * 說    明: 無
  126.   */
  127. int main(void)
  128. {
  129.   /* 復位所有外設,初始化Flash接口和系統滴答定時器 */
  130.   HAL_Init();
  131.   /* 配置系統時鐘 */
  132.   SystemClock_Config();
  133.   /* 串口初始化 */
  134.   MX_USARTx_Init();
  135.   /* 按鍵初始化 */
  136.   KEY_GPIO_Init();
  137.   /* 編碼器初始化及使能編碼器模式 */
  138.   ENCODER_TIMx_Init();
  139.         /* ADC-DMA 初始化 */
  140.   MX_ADCx_Init();
  141.   /* 啟動AD轉換并使能DMA傳輸和中斷 */
  142.   HAL_ADC_Start_DMA(&hadcx,(uint32_t*)ADC_ConvValueHex,ADC_BUFFER);
  143.   __HAL_DMA_DISABLE_IT(&hdma_adcx,DMA_IT_HT);
  144.   __HAL_DMA_DISABLE_IT(&hdma_adcx,DMA_IT_TE);
  145.   __HAL_DMA_DISABLE_IT(&hdma_adcx,DMA_IT_FE);
  146.   __HAL_DMA_DISABLE_IT(&hdma_adcx,DMA_IT_DME);
  147.         /* 高級控制定時器初始化并配置PWM輸出功能 */
  148.   BDCMOTOR_TIMx_Init();

  149.   /* 啟動定時器通道和互補通道PWM輸出 */
  150.   PWM_Duty = 0;
  151.   __HAL_TIM_SET_COMPARE(&htimx_BDCMOTOR,TIM_CHANNEL_1,PWM_Duty);  // 0%

  152.   /* PID 參數初始化 */
  153.   PID_ParamInit();
  154.   /* 無限循環 */
  155.   while (1)
  156.   {
  157.     /* 停止按鈕 */
  158.     if(KEY1_StateRead()==KEY_DOWN)
  159.     {
  160.       HAL_TIM_PWM_Start(&htimx_BDCMOTOR,TIM_CHANNEL_1);
  161.       HAL_TIMEx_PWMN_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1);
  162.       __HAL_TIM_SET_COMPARE(&htimx_BDCMOTOR,TIM_CHANNEL_1,0);  // 0%
  163.       Start_flag = 1;
  164.     }
  165.     if(KEY2_StateRead()==KEY_DOWN)
  166.     {
  167.       SHUTDOWN_MOTOR();
  168.       HAL_TIM_PWM_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1);
  169.       HAL_TIMEx_PWMN_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1);         // 停止輸出
  170.     }
  171.     if(KEY3_StateRead()==KEY_DOWN)    // 圈數+1
  172.     {
  173.       lPID.SetPoint += PPR;
  174.     }
  175.     if(KEY4_StateRead()==KEY_DOWN)    // 圈數-1
  176.     {
  177.       lPID.SetPoint -= PPR;
  178.     }
  179.   }
  180. }

  181. /**
  182.   * 函數功能: 系統滴答定時器中斷回調函數
  183.   * 輸入參數: 無
  184.   * 返 回 值: 無
  185.   * 說    明: 每隔一定的時間就執行pid算法
  186.   */
  187. void HAL_SYSTICK_Callback(void)
  188. {
  189.   __IO int32_t ADC_Resul= 0;
  190.   __IO float Volt_Result = 0;
  191.   __IO float ADC_CurrentValue;                                  // 電流

  192.   /* 位置環周期250ms */
  193.   if(uwTick % 250 == 0)
  194.   {
  195.     /* 獲取當前位置值,編碼器4倍頻之后的數值 */
  196.     Sample_Pulse = (OverflowCount*CNT_MAX) + (int32_t)__HAL_TIM_GET_COUNTER(&htimx_Encoder);
  197.     /* 計算PID結果 */
  198.     if(Start_flag == 1)
  199.     {
  200.       tmpPWM_DutySpd = LocPIDCalc(Sample_Pulse);
  201.       
  202.       /* 設定速度環的目標值 */
  203.       if(tmpPWM_DutySpd >= TARGET_SPEED)
  204.         tmpPWM_DutySpd = TARGET_SPEED;
  205.       if(tmpPWM_DutySpd <= -TARGET_SPEED)
  206.         tmpPWM_DutySpd = -TARGET_SPEED;
  207.     }
  208.   }
  209.   /* 速度環周期100ms */
  210.   if(uwTick % 100 == 0)
  211.   {
  212.     /* 獲得當前速度 */
  213.     Sample_Pulse = (OverflowCount*CNT_MAX) + (int32_t)__HAL_TIM_GET_COUNTER(&htimx_Encoder);
  214.     Spd_PPS = Sample_Pulse - LastSample_Pulse;
  215.     LastSample_Pulse = Sample_Pulse ;
  216.     /* 11線編碼器,270減速比,一圈脈沖信號是11*270*4 PPR */
  217.     Spd_RPM = ((((float)Spd_PPS/(float)PPR)*10.0f)*(float)60);//單位是rpm
  218.    
  219.     /* 計算PID結果 */
  220.     if(Start_flag == 1)
  221.     {
  222.       sPID.SetPoint = tmpPWM_DutySpd;
  223.       tmpPWM_Duty = SpdPIDCalc(Spd_RPM);
  224.       
  225.       /* 根據速度環的計算結果判斷當前運動方向 */
  226.       if(tmpPWM_Duty < 0)
  227.       {
  228.         Motor_Dir = CW;
  229.         BDDCMOTOR_DIR_CW();
  230.         tmpPWM_Duty = -tmpPWM_Duty;
  231.         
  232.       }
  233.       else
  234.       {
  235.         Motor_Dir = CCW;
  236.         BDDCMOTOR_DIR_CCW();
  237.       }
  238.       
  239.       /* 設定電流環的目標值,電流沒有負數 */
  240.       if(tmpPWM_Duty >= TARGET_CURRENT)
  241.         tmpPWM_Duty = TARGET_CURRENT;
  242.     }
  243.   }
  244.   /* 電流環周期是40ms,電流單次采集周期大約是 2ms,最好不要低于2ms */
  245.   if(uwTick % 40 == 0)
  246.   {
  247.     ADC_Resul = AverSum/AverCnt ;
  248.     /* 連續采樣16次以后,作為偏差值 */
  249.     OffsetCnt_Flag++;
  250.     if(OffsetCnt_Flag >= 16)
  251.     {
  252.       if(OffsetCnt_Flag == 16)
  253.       {
  254.         OffSetHex /= OffsetCnt_Flag-1;
  255.       }
  256.       OffsetCnt_Flag = 32;
  257.       ADC_Resul -= OffSetHex;//減去偏差值
  258.     }
  259.     else
  260.       OffSetHex += ADC_Resul;
  261.     /* 計算電壓值和電流值 */
  262.     Volt_Result = ( (float)( (float)(ADC_Resul) * VOLT_RESOLUTION) );
  263.     ADC_CurrentValue = (float)( (Volt_Result / GAIN) / SAMPLING_RES);
  264.     if(Volt_Result<0)
  265.       Volt_Result = 0;
  266.     /* 清空計數 */
  267.     AverCnt = 0;
  268.     AverSum = 0;
  269.    
  270.     /* 計算PID結果 */
  271.     if(Start_flag == 1)
  272.     {  
  273.       cPID.SetPoint = tmpPWM_Duty ;
  274.       PWM_Duty = CurPIDCalc( (int32_t)ADC_CurrentValue);
  275.       if(PWM_Duty >= BDCMOTOR_DUTY_FULL)
  276.         PWM_Duty = BDCMOTOR_DUTY_FULL;
  277.       if(PWM_Duty <=0)
  278.           PWM_Duty = 0;
  279.       __HAL_TIM_SET_COMPARE(&htimx_BDCMOTOR,TIM_CHANNEL_1,PWM_Duty);
  280.     }
  281.     printf("LOC:%d Sped: %2.2f r/m Curr: %d mA \n",Sample_Pulse,
  282.               Spd_RPM ,(int32_t)ADC_CurrentValue);
  283.   }
  284. }


  285. /**
  286.   * 函數功能: ADC轉換完成回調函數
  287.   * 輸入參數: hadc:ADC外設設備句柄
  288.   * 返 回 值: 無
  289.   * 說    明: 中斷一次的時間是1.479ms,利用過采樣和求均值方法,提高分辨率
  290.   */
  291. void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)  
  292. {
  293.   int32_t ADConv = 0 ;
  294.   /* ADC采集太快,需要先停止再處理數據 */
  295.   HAL_ADC_Stop_DMA(hadc);
  296.   /* 采集總線電壓 */
  297.   SetChannelAsRank1(hadc,ADC_VOLT_CHANNEL);
  298.   HAL_ADC_Start(hadc);
  299.   
  300.   /* 去掉高和低總共SORT_NUM個采樣數據,取中間部分的數據做平均 */
  301.         ADConv = ADC_GetSampleAvgN((int16_t*)&ADC_ConvValueHex,ADC_BUFFER);
  302.   
  303.   /* 累加采樣結果并記錄采樣次數*/
  304.   AverSum += ADConv;
  305.   AverCnt++;

  306.   /* 讀取總線電壓值 */
  307.   HAL_ADC_Stop(hadc);
  308.   SetChannelAsRank1(hadc,ADC_CURRENT_CHANNEL);
  309.   
  310.   HAL_ADC_Start_DMA(hadc,(uint32_t*)ADC_ConvValueHex,ADC_BUFFER);
  311. }

  312. /**
  313.   * 函數功能: ADC看門狗中斷回調函數
  314.   * 輸入參數: ADC句柄
  315.   * 返 回 值: 無
  316.   * 說    明: 檢測到電壓過低或者過高的時候就調用這個函數,停止輸出.
  317.   */
  318. void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef* hadc)
  319. {
  320.   /* 使能電機控制引腳 */
  321.   static uint8_t i = 0;
  322.   i++;
  323.   if(ADC_VoltBus > VOLT_LIMIT_MIN && ADC_VoltBus < VOLT_LIMIT_MAX)
  324.     i = 0 ;
  325.   else if(i>=6)
  326.   {
  327.     SHUTDOWN_MOTOR();
  328.     HAL_TIM_PWM_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1);
  329.     HAL_TIMEx_PWMN_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1);
  330.     PWM_Duty = 0;
  331.     printf("Bus Voltage is out of range!!\n");
  332.     printf("Please Reset the Target!\n");
  333.     while(1);
  334.   }
  335. }
  336. /**
  337.         * 函數功能: 得到N 個ADC 采樣的均值
  338.         * 輸入參數: 要做平均的ADC 采樣數
  339.         * 返 回 值: 均值
  340.         * 說                明: 計算平均值,獲得14bitsADC值
  341.         */
  342. int32_t ADC_GetSampleAvgN(int16_t *Data, uint32_t N)
  343. {
  344.         int32_t avg_sample =0x00;
  345.         uint32_t index=0x00;

  346.         /* 累加N 個ADC 采樣 */
  347.         for (index = 0; index < N; index++)
  348.         {
  349.                 avg_sample += ((int32_t)Data[index]);
  350.         }
  351.         /* 計算N 個ADC 采樣的均值 */
  352.         avg_sample >>= ADC_Base;
  353.         /* 返回均值 */
  354.         return avg_sample;
  355. }
  356. /******************** PID 控制設計 ***************************/
  357. /**
  358.   * 函數功能: PID參數初始化
  359.   * 輸入參數: 無
  360.   * 返 回 值: 無
  361.   * 說    明: 無
  362.   */
  363. void PID_ParamInit()
  364. {
  365.     cPID.LastError = 0;            // Error[-1]
  366.     cPID.PrevError = 0;            // Error[-2]
  367.     cPID.Proportion = CUR_P_DATA;  // 比例常數 Proportional Const
  368.     cPID.Integral = CUR_I_DATA;    // 積分常數  Integral Const
  369.     cPID.Derivative = CUR_D_DATA;  // 微分常數 Derivative Const
  370.     cPID.SetPoint = TARGET_CURRENT;// 設定目標Desired Value

  371.     sPID.LastError = 0;               // Error[-1]
  372.     sPID.PrevError = 0;               // Error[-2]
  373.     sPID.Proportion = SPD_P_DATA; // 比例常數 Proportional Const
  374.     sPID.Integral = SPD_I_DATA;   // 積分常數  Integral Const
  375.     sPID.Derivative = SPD_D_DATA; // 微分常數 Derivative Const
  376.     sPID.SetPoint = TARGET_SPEED;     // 設定目標Desired Value
  377.   
  378.     lPID.LastError = 0;               // Error[-1]
  379.     lPID.PrevError = 0;               // Error[-2]
  380.     lPID.Proportion = LOC_P_DATA; // 比例常數 Proportional Const
  381.     lPID.Integral = LOC_I_DATA;   // 積分常數  Integral Const
  382.     lPID.Derivative = LOC_D_DATA; // 微分常數 Derivative Const
  383.     lPID.SetPoint = TARGET_LOC;     // 設定目標Desired Value
  384. }

  385. /**
  386.   * 函數名稱:電流閉環PID控制設計
  387.   * 輸入參數:當前控制量
  388.   * 返 回 值:目標控制量
  389.   * 說    明:無
  390.   */
  391. int32_t CurPIDCalc(int32_t NextPoint)
  392. {
  393.   int32_t iError,dError;
  394.   iError = cPID.SetPoint - NextPoint; //偏差
  395.   /* 設定閉環死區 */
  396.   if((iError >= -3) && (iError <= 3))
  397.     iError = 0;
  398.   
  399.   cPID.SumError += iError; //積分
  400.   dError = iError - cPID.LastError; //微分
  401.   cPID.LastError = iError;
  402.   
  403.   return (int32_t)(cPID.Proportion * (float)iError //比例項
  404.   + cPID.Integral * (float)cPID.SumError //積分項
  405.   + cPID.Derivative * (float)dError);    //微分項
  406. }

  407. /**
  408.   * 函數名稱:速度閉環PID控制設計
  409.   * 輸入參數:當前控制量
  410.   * 返 回 值:目標控制量
  411.   * 說    明:無
  412.   */
  413. int32_t SpdPIDCalc(float NextPoint)
  414. {
  415.   float iError,dError;
  416.   iError = sPID.SetPoint - NextPoint; //偏差
  417.   
  418.   if((iError<0.3f )&& (iError>-0.3f))
  419.     iError = 0.0f;
  420. ……………………

  421. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼


所有代碼51hei提供下載:
STM32編程實現直流有刷電機位置速度電流三閉環PID控制.7z (1.54 MB, 下載次數: 135)


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

使用道具 舉報

沙發
ID:871077 發表于 2021-6-28 17:01 | 只看該作者
只有代碼,沒有原理圖,作為參考吧。
回復

使用道具 舉報

板凳
ID:473517 發表于 2023-3-7 16:33 | 只看該作者
參考一下
回復

使用道具 舉報

地板
ID:291668 發表于 2023-3-8 13:35 | 只看該作者
可參考! 配一下簡單的說明更好了
回復

使用道具 舉報

5#
ID:613605 發表于 2023-5-23 16:13 | 只看該作者
有原理圖嗎?
回復

使用道具 舉報

6#
ID:1090151 發表于 2023-8-21 16:07 | 只看該作者
參考一下,求原理圖
回復

使用道具 舉報

7#
ID:792289 發表于 2024-12-28 17:25 | 只看該作者
求參考原理圖,現在做牙科項目
回復

使用道具 舉報

8#
ID:50577 發表于 2025-1-16 16:04 | 只看該作者
stm32比51更強大
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 欧美videosex性极品hd | 夜夜精品浪潮av一区二区三区 | 久久久av一区 | 国产福利视频导航 | 成人性视频免费网站 | 日韩视频免费看 | 青青草免费在线视频 | 国产欧美精品区一区二区三区 | 国产综合在线视频 | 91久色| 午夜看电影在线观看 | 午夜欧美一区二区三区在线播放 | 亚洲va在线va天堂va狼色在线 | 一区精品视频在线观看 | 亚洲久久 | 特一级毛片 | va精品| 成人精品视频 | 亚洲一区 中文字幕 | 欧美成人精品 | 国产69精品久久99不卡免费版 | 久久高清| 久久男女视频 | 国产精品视频一 | 国产一区二区三区视频 | 99视频免费 | 毛片国产 | 一级免费毛片 | 天天久| 成人自拍av| 午夜视频一区 | 一区二区精品电影 | www.伊人.com| 国产综合在线视频 | 91久久 | 久久久久一区二区三区 | 成人免费在线电影 | 三极网站| 欧美一区二| 国产精品美女久久久av超清 | 在线观看日韩精品视频 |