【1】例程簡介
使用定時器功能輸出PWM信號到步進電機驅動器,使其驅動步進電機轉動。
編碼器用于電機測速。在電機轉動一圈時編碼器可以輸出固定的脈沖數,通過讀取編碼器
脈沖可以獲取當前電機轉動狀態。
一般處理編碼器脈沖有兩種方法:
1. T法:計算一定量的脈沖數所用的時間
2. M法:計算一段固定時間內所捕獲的脈沖數。
根據當前速度和目標速度之間的誤差,使用PID計算定時器輸出的脈沖頻率,使得滑臺能夠以目標速度
運動
【2】跳線帽情況
編碼器 A相 --> PC6
B相 --> PC7
步進電機驅動器 DIR- --> PB13
ENA- --> PB14
PUL- --> PA8
DIR+ --> +5V
ENA+ --> +5V
PUL+ --> +5V
【3】操作及現象
根據引腳定義方法連接開發板和步進電機驅動器和編碼器,另外步進電機
連接自行根據電機和驅動器標識連接,驅動器需要一個24V的直流電源供電。
接線時注意開發板與驅動器“共地”連接。編碼器的AB相輸出都是開漏輸出,
所以需要使用加上拉電阻才能連接,使用開發板配套的MINI USB線連接到開發
板標示“調試串口”字樣的MIMI USB接口為開發板提供電源。下載完程序之后
,開發板持續PWM脈沖給步進電機驅動器,電機以目標速度持續轉動,同時在
串口助手上每秒顯示一次當前位置,速度,捕獲值等信息.
單片機源程序如下:
- /**
- ******************************************************************************
- * 文件名程: main.c
- * 作 者: 硬石嵌入式開發團隊
- * 版 本: V1.1
- * 功 能: 基于PID速度環的步進電機速度調節
- ******************************************************************************
- * 說明:
- * 本例程配套硬石stm32開發板YS-F1Pro使用。
- *
- ******************************************************************************
- */
- /* 包含頭文件 ----------------------------------------------------------------*/
- #include "stm32f1xx_hal.h"
- #include "StepMotor/bsp_STEPMOTOR.h"
- #include "usart/bsp_debug_usart.h"
- #include "EncoderTIM/bsp_EncoderTIM.h"
- #include <stdlib.h>
- #include <string.h>
- /* 私有類型定義 --------------------------------------------------------------*/
- typedef struct
- {
- __IO float SetPoint; // 目標值 單位:mm/s
- __IO int LastError; // 前一次誤差
- __IO int PrevError; // 前兩次誤差
- __IO long SumError; // 累計誤差
- __IO double Proportion; // Kp系數
- __IO double Integral; // Ki系數
- __IO double Derivative; // Kd系數
- }PID;
- /* 私有宏定義 ----------------------------------------------------------------*/
- #define TXDCYCLE 1000 // 數據發送周期;單位:ms
- #define SAMPLING 0x01 // 采樣標記
- #define TXD 0x02 // 發送數據標記
- #define abs(x) ((x)<0?(-x):(x))
- #define SENDBUFF_SIZE 100 // 串口DMA發送緩沖區大小
- /* 私有變量 ------------------------------------------------------------------*/
- __IO static PID vPID;
- __IO uint16_t time_count = 0; // 時間計數,每1ms增加一(與滴答定時器頻率有關)
- __IO uint8_t Time_Flag = 0; // 任務時間標記
-
- /* 擴展變量 ------------------------------------------------------------------*/
- extern int16_t OverflowCount; //編碼器計數溢出 計數器
- /* 私有函數原形 --------------------------------------------------------------*/
- /* 函數體 --------------------------------------------------------------------*/
- /**
- * 函數功能:增量式PID速度環計算
- * 輸入參數:NextPoint 由編碼器得到的速度值
- * TargetVal 目標值
- * 返 回 值:經過PID運算得到的增量值
- * 說 明:增量式 PID 速度環控制設計,計算得到的結果仍然是速度值
- */
- float IncPIDCalc(int NextPoint,float TargetVal) //臨時變量,期望值
- {
- float iError = 0,iIncpid = 0; //當前誤差
- iError = TargetVal - NextPoint; // 增量計算
- if((iError<0.5)&&(iError>-0.5))
- iError = 0; // |e| < 0.5,不做調整
- iIncpid=(vPID.Proportion * iError) // E[k]項
- -(vPID.Integral * vPID.LastError) // E[k-1]項
- +(vPID.Derivative * vPID.PrevError); // E[k-2]項
-
- vPID.PrevError=vPID.LastError; // 存儲誤差,用于下次計算
- vPID.LastError = iError;
- return(iIncpid); // 返回增量值
- }
- /**
- * 函數功能: 系統時鐘配置
- * 輸入參數: 無
- * 返 回 值: 無
- * 說 明: 無
- */
- void SystemClock_Config(void)
- {
- RCC_OscInitTypeDef RCC_OscInitStruct;
- RCC_ClkInitTypeDef RCC_ClkInitStruct;
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; // 外部晶振,8MHz
- RCC_OscInitStruct.HSEState = RCC_HSE_ON;
- RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
- RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; // 9倍頻,得到72MHz主時鐘
- 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; // 系統時鐘:72MHz
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // AHB時鐘:72MHz
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; // APB1時鐘:36MHz
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // APB2時鐘:72MHz
- HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
- // 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, 1, 0);
- }
- /**
- * 函數功能: PID結構體初始化
- * 輸入參數: 無
- * 返 回 值: 無
- * 說 明: 初始化PID參數
- */
- void Init_PID()
- {
- vPID.SetPoint = 5; // 目標值 單位:mm/s
- vPID.Proportion = 0.11; // Kp系數
- vPID.Derivative = 0.03; // Ki系數
- vPID.Integral = 0.12; // Kd系數
- vPID.LastError = 0;
- vPID.PrevError = 0;
- vPID.SumError = 0;
- }
- /**
- * 函數功能: 主函數.
- * 輸入參數: 無
- * 返 回 值: 無
- * 說 明: 無
- */
- int main(void)
- {
- static float Exp_Val = 0; // PID計算出來的期望值
- float Vel_Target; // 速度目標值
- uint16_t SUM_Pulse = 0; // 1秒內的總脈沖
- int16_t MSF = 0; // 電機反饋速度
- __IO int32_t CaptureNumber=0; // 輸入捕獲數
- __IO int32_t Last_CaptureNumber=0; // 上一次捕獲值
- uint8_t aTxBuffer[SENDBUFF_SIZE]; // 串口DMA發送緩沖區
- /* 復位所有外設,初始化Flash接口和系統滴答定時器 */
- HAL_Init();
- /* 配置系統時鐘 */
- SystemClock_Config();
- Init_PID();
- /* 調試串口初始化 */
- MX_DEBUG_USART_Init();
- /* 編碼器定時器初始化并配置輸入捕獲功能 */
- ENCODER_TIMx_Init();
- /* 啟動編碼器接口 */
- HAL_TIM_Encoder_Start(&htimx_Encoder, TIM_CHANNEL_ALL);
-
- HAL_Delay(10);
- /* 步進電機定時器初始化*/
- STEPMOTOR_TIMx_Init();
- /* 首先禁止步進電機動作*/
- STEPMOTOR_OUTPUT_DISABLE();
- /* 啟動定時器 */
- HAL_TIM_Base_Start(&htimx_STEPMOTOR);
- /* 啟動比較輸出并使能中斷 */
- HAL_TIM_OC_Start_IT(&htimx_STEPMOTOR,TIM_CHANNEL_1);
-
- /* 目標值單位為:mm/s,這里需要轉換為頻率
- f = v*PPM;
- PPM是每mm的編碼器脈沖數,得到的F就是每秒的脈沖數 (Pulse/s,也就是頻率:Hz)
- Vel_Target = f/(1000/20);得到每個采樣周期(20ms)的脈沖數(Pulse/ms)
- */
- Vel_Target = (vPID.SetPoint*P_PERIOD);//每單位采樣周期內的脈沖數(頻率)
-
- /* 無限循環 */
- while (1)
- {
-
- //采樣和控制周期為20ms
- if(Time_Flag & SAMPLING)
- {
- //獲得編碼器的脈沖值
- CaptureNumber = OverflowCount*65535 + __HAL_TIM_GET_COUNTER(&htimx_Encoder);
- //M法 測速度
- MSF = CaptureNumber - Last_CaptureNumber;
- Last_CaptureNumber = CaptureNumber;
- MSF = abs(MSF);
- //對速度進行累計,得到1s內的脈沖數
- SUM_Pulse += MSF;
- Exp_Val += IncPIDCalc(MSF,Vel_Target);
- Exp_Val = abs(Exp_Val);
- /* 經過PID計算得到的結果是編碼器的輸出期望值的增量,
- 需要轉換為步進電機的控制量(頻率值),這里乘上一個系數6400/2400
- */
- STEPMOTOR_Motion_Ctrl(CW,Exp_Val*FEEDBACK_CONST);//乘上一個系數,6400/2400,將PID計算結果轉換為步進電機的頻率(速度)
- Time_Flag &= ~SAMPLING;
- }
- //數據發送周期為1s
- if(Time_Flag & TXD)
- {
- sprintf(aTxBuffer,"捕獲值:%d--速度:%.1f mm/s\n",CaptureNumber,(float)SUM_Pulse*MPP);
- sprintf(aTxBuffer+strlen((const char*)aTxBuffer),"1s內編碼器計數值:%d\n",SUM_Pulse);
- HAL_UART_Transmit_DMA(&husart_debug, aTxBuffer, strlen((const char*)aTxBuffer));
- SUM_Pulse = 0;
- Time_Flag &= ~TXD;
- }
- }
- }
- /**
- * 函數功能: 系統滴答定時器中斷回調函數
- * 輸入參數: 無
- * 返 回 值: 無
- * 說 明: 每發生一次滴答定時器中斷進入該回調函數一次
- */
- void HAL_SYSTICK_Callback(void)
- {
- // 每1ms自動增一
- time_count++;
- if(time_count%(SAMPLING_PERIOD) == 0) // 20ms
- {
- Time_Flag |= SAMPLING;
- }
- if(time_count >= TXDCYCLE) // 1s
- {
- Time_Flag |= TXD;
- time_count = 0;
- }
- }
- /******************* (C) COPYRIGHT 2015-2020 硬石嵌入式開發團隊 *****END OF FILE****/
復制代碼
所有資料51hei提供下載:
YSF1_HAL_MOTOR-018. 步進電機速度環控速.rar
(3.23 MB, 下載次數: 304)
2018-11-9 15:21 上傳
點擊文件名下載附件
|