雙環閉環
單片機源程序如下:
- /**
- ******************************************************************************
- * 文件名程: main.c
- * 作 者: 學習小組
- * 功 能: GM37-545_位置速度閉環控制
- ******************************************************************************
- * 說明:
- ******************************************************************************
- */
- /* 包含頭文件 ----------------------------------------------------------------*/
- #include "stm32f4xx_hal.h"
- #include "key.h"
- #include "encoder.h"
- #include "usartx.h"
- #include "BDCMotor.h"
- /* 私有類型定義 --------------------------------------------------------------*/
- typedef struct
- {
- __IO int32_t SetPoint; //設定目標 Desired Value
- __IO float SumError; //誤差累計
- __IO float Proportion; //比例常數 Proportional Const
- __IO float Integral; //積分常數 Integral Const
- __IO float Derivative; //微分常數 Derivative Const
- __IO int LastError; //Error[-1]
- __IO int PrevError; //Error[-2]
- }PID_TypeDef;
- /* 私有宏定義 ----------------------------------------------------------------*/
- #define SPEEDRATIO 270
- #define ENCODER_RESOLUTION 11
- #define PPR ((SPEEDRATIO*ENCODER_RESOLUTION)*4) // Pulse/Round 每圈可捕獲到的脈沖數
- /*************************************/
- // 定義PID相關宏
- // 這三個參數設定對電機運行影響非常大
- // PID參數跟采樣時間息息相關
- /*************************************/
- #define SPD_P_DATA 50.0f // P參數
- #define SPD_I_DATA 8.5f // I參數
- #define SPD_D_DATA 0.0f // D參數
- #define TARGET_SPEED 10.0f // 目標速度 10r/m
- #define LOC_P_DATA 0.01f // P參數
- #define LOC_I_DATA 0.0f // D參數
- #define LOC_D_DATA 0.08f // D參數
- #define TARGET_LOC (3*PPR) // 目標位置 11880 Pulse = 1r
- /* 私有變量 ------------------------------------------------------------------*/
- __IO uint8_t Start_flag = 0; // PID 開始標志
- uint32_t Motor_Dir = CW; // 電機方向
- __IO int32_t tmpPWM_DutySpd = 0;
- __IO int32_t tmpPWM_Duty = 0;
- __IO int32_t Sample_Pulse; // 編碼器捕獲值 Pulse
- __IO int32_t LastSample_Pulse; // 編碼器捕獲值 Pulse
- __IO int32_t Spd_PPS; // 速度值 Pulse/Sample
- __IO float Spd_RPM; // 速度值 r/m
- /* 擴展變量 ------------------------------------------------------------------ */
- extern __IO uint32_t uwTick;
- /* PID結構體 */
- PID_TypeDef sPID,lPID; // PID參數結構體
- /* 擴展變量 ------------------------------------------------------------------*/
- /* 私有函數原形 --------------------------------------------------------------*/
- void PID_ParamInit(void) ;
- int32_t SpdPIDCalc(float NextPoint);
- int32_t LocPIDCalc(int32_t NextPoint);
- /* 函數體 --------------------------------------------------------------------*/
- /**
- * 函數功能: 系統時鐘配置
- * 輸入參數: 無
- * 返 回 值: 無
- * 說 明: 無
- */
- void SystemClock_Config(void)
- {
- RCC_OscInitTypeDef RCC_OscInitStruct;
- RCC_ClkInitTypeDef RCC_ClkInitStruct;
- __HAL_RCC_PWR_CLK_ENABLE(); // 使能PWR時鐘
- __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); // 設置調壓器輸出電壓級別1
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; // 外部晶振,8MHz
- RCC_OscInitStruct.HSEState = RCC_HSE_ON; // 打開HSE
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; // 打開PLL
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; // PLL時鐘源選擇HSE
- RCC_OscInitStruct.PLL.PLLM = 8; // 8分頻MHz
- RCC_OscInitStruct.PLL.PLLN = 336; // 336倍頻
- RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // 2分頻,得到168MHz主時鐘
- RCC_OscInitStruct.PLL.PLLQ = 7; // USB/SDIO/隨機數產生器等的主PLL分頻系數
- HAL_RCC_OscConfig(&RCC_OscInitStruct);
- RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
- |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 系統時鐘:168MHz
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB時鐘: 168MHz
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; // APB1時鐘:42MHz
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; // APB2時鐘:84MHz
- HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
- HAL_RCC_EnableCSS(); // 使能CSS功能,優先使用外部晶振,內部時鐘源為備用
- // HAL_RCC_GetHCLKFreq()/1000 1ms中斷一次
- // HAL_RCC_GetHCLKFreq()/100000 10us中斷一次
- // HAL_RCC_GetHCLKFreq()/1000000 1us中斷一次
- HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); // 配置并啟動系統滴答定時器
- /* 系統滴答定時器時鐘源 */
- HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
- /* 系統滴答定時器中斷優先級配置 */
- HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
- }
- /**
- * 函數功能: 主函數.
- * 輸入參數: 無
- * 返 回 值: 無
- * 說 明: 無
- */
- int main(void)
- {
- /* 復位所有外設,初始化Flash接口和系統滴答定時器 */
- HAL_Init();
- /* 配置系統時鐘 */
- SystemClock_Config();
- /* 串口初始化 */
- MX_USARTx_Init();
- /* 按鍵初始化 */
- KEY_GPIO_Init();
- /* 編碼器初始化及使能編碼器模式 */
- ENCODER_TIMx_Init();
- /* 高級控制定時器初始化并配置PWM輸出功能 */
- BDCMOTOR_TIMx_Init();
- /* 啟動定時器通道和互補通道PWM輸出 */
- PWM_Duty = 0;
- __HAL_TIM_SET_COMPARE(&htimx_BDCMOTOR,TIM_CHANNEL_1,PWM_Duty); // 0%
- /* PID 參數初始化 */
- PID_ParamInit();
- /* 無限循環 */
- while (1)
- {
- /* 停止按鈕 */
- if(KEY1_StateRead()==KEY_DOWN)
- {
- if( lPID.Proportion < 0 )
- {
- Motor_Dir = CW;
- BDDCMOTOR_DIR_CW();
- PWM_Duty = -PWM_Duty;
- }
- else
- {
- Motor_Dir = CCW;
- BDDCMOTOR_DIR_CCW();
- }
- __HAL_TIM_SET_COMPARE(&htimx_BDCMOTOR,TIM_CHANNEL_1,0); // 0%
- Start_flag = 1;
- }
- if(KEY2_StateRead()==KEY_DOWN)
- {
- SHUTDOWN_MOTOR();
- HAL_TIM_PWM_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1);
- HAL_TIMEx_PWMN_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1); // 停止輸出
- }
- if(KEY3_StateRead()==KEY_DOWN) // 圈數+1
- {
- lPID.SetPoint += PPR;
- }
- if(KEY4_StateRead()==KEY_DOWN) // 圈數-1
- {
- lPID.SetPoint -= PPR;
- }
- }
- }
- /**
- * 函數功能: 系統滴答定時器中斷回調函數
- * 輸入參數: 無
- * 返 回 值: 無
- * 說 明: 每隔一定的時間就執行pid算法
- */
- void HAL_SYSTICK_Callback(void)
- {
- __IO int32_t ADC_Resul= 0;
- __IO float Volt_Result = 0;
- /* 位置環周期100ms */
- if(uwTick % 100 == 0)
- {
- /* 獲取當前位置值,編碼器4倍頻之后的數值 */
- Sample_Pulse = (OverflowCount*CNT_MAX) + (int32_t)__HAL_TIM_GET_COUNTER(&htimx_Encoder);
- /* 計算PID結果 */
- if(Start_flag == 1)
- {
- tmpPWM_DutySpd = LocPIDCalc(Sample_Pulse);
- /* 設定速度環的目標值 */
- if(tmpPWM_DutySpd >= TARGET_SPEED)
- tmpPWM_DutySpd = TARGET_SPEED;
- if(tmpPWM_DutySpd <= -TARGET_SPEED)
- tmpPWM_DutySpd = -TARGET_SPEED;
- }
- }
- /* 速度環周期50ms */
- if(uwTick % 50 == 0)
- {
- /* 獲得當前速度 */
- Sample_Pulse = (OverflowCount*CNT_MAX) + \
- (int32_t)__HAL_TIM_GET_COUNTER(&htimx_Encoder);
- Spd_PPS = Sample_Pulse - LastSample_Pulse;
- LastSample_Pulse = Sample_Pulse ;
- /* 11線編碼器,270減速比,一圈脈沖信號是11*270*4 PPR */
- Spd_RPM = ((((float)Spd_PPS/(float)PPR)*20.0f)*(float)60);//單位是rpm
- /* 計算PID結果 */
- if(Start_flag == 1)
- {
- sPID.SetPoint = tmpPWM_DutySpd;
- PWM_Duty = SpdPIDCalc(Spd_RPM);
- if(PWM_Duty < 0)
- {
- Motor_Dir = CW;
- BDDCMOTOR_DIR_CW();
- PWM_Duty = -PWM_Duty;
- }
- else
- {
- Motor_Dir = CCW;
- BDDCMOTOR_DIR_CCW();
- }
- __HAL_TIM_SET_COMPARE(&htimx_BDCMOTOR,TIM_CHANNEL_1,PWM_Duty );
- }
- printf("LOC:%d Sped: %2.2f r/m \n",Sample_Pulse,
- Spd_RPM );
- }
- }
- /******************** PID 控制設計 ***************************/
- /**
- * 函數功能: PID參數初始化
- * 輸入參數: 無
- * 返 回 值: 無
- * 說 明: 無
- */
- void PID_ParamInit()
- {
- sPID.LastError = 0; // Error[-1]
- sPID.PrevError = 0; // Error[-2]
- sPID.Proportion = SPD_P_DATA; // 比例常數 Proportional Const
- sPID.Integral = SPD_I_DATA; // 積分常數 Integral Const
- sPID.Derivative = SPD_D_DATA; // 微分常數 Derivative Const
- sPID.SetPoint = TARGET_SPEED; // 設定目標Desired Value
- lPID.LastError = 0; // Error[-1]
- lPID.PrevError = 0; // Error[-2]
- lPID.Proportion = LOC_P_DATA; // 比例常數 Proportional Const
- lPID.Integral = LOC_I_DATA; // 積分常數 Integral Const
- lPID.Derivative = LOC_D_DATA; // 微分常數 Derivative Const
- lPID.SetPoint = TARGET_LOC; // 設定目標Desired Value
- }
- /**
- * 函數名稱:速度閉環PID控制設計
- * 輸入參數:當前控制量
- * 返 回 值:目標控制量
- * 說 明:無
- */
- int32_t SpdPIDCalc(float NextPoint)
- {
- float iError,dError;
- iError = sPID.SetPoint - NextPoint; //偏差
- if((iError<0.2f )&& (iError>-0.2f))
- iError = 0.0f;
- sPID.SumError += iError; //積分
- /* 設定積分上限 */
- if(lPID.SumError >= TARGET_SPEED*10)
- lPID.SumError = TARGET_SPEED*10;
- if(lPID.SumError <= -TARGET_SPEED*10)
- lPID.SumError = -TARGET_SPEED*10;
- dError = iError - sPID.LastError; //微分
- sPID.LastError = iError;
- return (int32_t)(sPID.Proportion * (float)iError //比例項
- + sPID.Integral * (float)sPID.SumError //積分項
- + sPID.Derivative * (float)dError); //微分項
- }
- /**
- * 函數名稱:位置閉環PID控制設計
- * 輸入參數:當前控制量
- * 返 回 值:目標控制量
- * 說 明:無
- */
- int32_t LocPIDCalc(int32_t NextPoint)
- {
- int32_t iError,dError;
- iError = lPID.SetPoint - NextPoint; //偏差
- /* 設定閉環死區 */
- if((iError >= -50) && (iError <= 50))
- {
- iError = 0;
- lPID.SumError = 0;
- }
- /* 積分分離 */
- if((iError >= -1000) && (iError <= 1000))
- {
- lPID.SumError += iError; //積分
- /* 設定積分上限 */
- if(lPID.SumError >= 1000)
- lPID.SumError = 1000;
- if(lPID.SumError <= -1000)
- lPID.SumError = -1000;
- }
- dError = iError - lPID.LastError; //微分
- lPID.LastError = iError;
- return (int32_t)(lPID.Proportion * (float)iError //比例項
- + lPID.Integral * (float)lPID.SumError //積分項
- + lPID.Derivative * (float)dError); //微分項
- }
- /**********************************END OF FILE****************************/
復制代碼
所有代碼51hei附件下載:
STM32編程實現_位置速度PID雙閉環控制.7z
(1.53 MB, 下載次數: 103)
2021-7-23 16:34 上傳
點擊文件名下載附件
|