2022年5月3日星期二

[STM32] 透過 ADC 數值控制 PWM 及 伺服馬達 Servo

最近在使用 Arduino AmebaIot 控制 SG90 Servo, 心想也有一段時間沒在寫 STM32 的 Code了,想要練練手感所以發起這個小實驗。想要目的結果是透過 VR可變電阻改變 ADC 值,確認比例之後。間接改變 Servo 的 0度 ~ 180度。 總結來說,會用到的功能環節是 ADC 讀值 , PWM 空占比控制。

 

MCU 設定

這次使用自製的開發板,MCU 為 K051。除了基本設定外,個別加入 ADC IN 及 Time PWM Out 設定
ADC -> ADC_IN8
TIMER -> TIM3_CH2

STM32 PWM

Time 設定 ,使用 Tim3 的 Channel2 。

STM32 PWM

ADC 輸入

使用 Polling 方式輸入 , 請參考 ADC 轉換器 - 使用 Polling 多通道輪詢模式 (連結)
這裡是透過 可變電阻 VR 影響 ADC IN 的輸入值,進而計算出當時的比例值
提示 : STM32 預設解析度為 12 bit = 4096

可變電阻 VR 電路

STM32 PWM ADC

例如:
ADC_in = 1024
比例值 = 1024 /4096 = 25%

Servo 控制

SG-90 可控制角度為 0度 ~ 180 度之間。控制方式需要輸入50Hz 的 PWM 訊號,由訊號寬度來判別控制角度。寬度範圍是 0.5ms ~ 2.5ms 間。

0.5ms 寬度 -> -90 度
1.5ms 寬度 -> 0 度
2.5ms 寬度 -> 90 度

頻率 50Hz = 1/50 = 0.02s = 20ms,所以SG-90 的控制範圍是

0.5ms = 0.5 / 20 = 2.5%
1.5ms = 1.5 / 20 = 7.5%
2.5ms = 2.5 / 20 = 12.5%

STM32 Timer / PWM 設定

MCU CLOCK = 48000000

目標 50 Hz

所以,48000000 / 50 = 960000 ,如果 Period 設定為 1000 ,
則 Prescaler 可以設定為 960000 / 1000 = 960

因此要調整 PWM 空佔比的範圍是 0 ~ 1000
假設需要 1.5ms 的 PWM 寬度 = (1.5ms / 20 ) x 1000 = 75

綜合以上, 導出以下公式


PWMValue = ((2.5*val)/20)*TimePeriod;

val 為 ADC 計算出的比例。

在 STM32 的 HAL 庫, 設定空佔比。可用


__HAL_TIM_SET_COMPARE()

主要控制程式碼


  while (1)
  {
    /* USER CODE END WHILE */
      HAL_ADC_Start(&hadc);


      if(HAL_ADC_PollForConversion(&hadc,100) == HAL_OK)
      {
          ADCValue = HAL_ADC_GetValue(&hadc);
      }
      val = (float)ADCValue/pow(2,12);
      PWMValue = ((2.5*val)/20)*TimePeriod;
      printf("Count[%ld],Value= [%d] ,VR[%d]\%%,PWM value[%d]\r\n",x,(uint16_t)ADCValue ,(uint8_t)((val) * 100),PWMValue);


      if(PWMValue < 25)
      {
          __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_2,25);
      }
      else
      {
          __HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_2,PWMValue);
      }




      HAL_Delay(250);
      x++;
    /* USER CODE BEGIN 3 */
  }

實際上在示波器測試結果

2.5ms

STM32,PWM,ADC

0.5ms

STM32,PWM,ADC

實體測試電路

原始碼連結

https://github.com/cold63/STM32_Code/tree/master/K051KRunPWM

0 comments:

發佈留言