본문 바로가기
Robot/Device Control

[STM32F10x-StdPeriph] 6. PWM을 이용한 Servo Motor Control

by lifeseed 2013. 12. 8.

1. Servo Motor 동작 개요

사용된 servo motor : TowerPro SG90 Micro Servo Motor

0.7 ~ 2.3 msec High를 유지하는 20msec 주기의 파형으로 -90도 ~ 90도로 Servo Motor를 동작시킬 수 있다.

 

즉 Servo Motor를 구동하기 위해 50hz  (1/20msec)  파형을 생성하여 Duty Cycle을 3.5% ~ 11.5%의 DutyCycle을 설정한다.

 

여기서는 TIM에서 제공하는 PWM 기능을 이용하며, 함수는 ST에서 제공하는 Standard Peripheral Library API를 이용하였다.

 

PWM 파형 주기 : 50Hz

Duty Cycle 

         3.5%  :   -90도

         7.5% :      0도

        11.5% :    90도

 

 

2. 20 msec 파형 생성

1) 72MHz의 System Clock에서 Prescaler를 이용하여 1MHz Timer Clock 생성

   Prescale = 72MHz / 1MHz  -1 =  71

2) 1 MHz Timer Clock 주기를 20,000으로 설정하여 5KHz 주기 파형을 생성

   TIM_Period = 1MHz/50Hz = 20,000

 

3. PWM Duty Cycle 계산

PWM의 Duty Cycle는 TIM_Period로 계산.

-90도  : 20,000 *3.5  /100  =  700

   0도  : 20,000 *7.5  /100  = 1500

 90도 : 20,000 * 11.5 / 100 = 2300

 

 

4. Source Code

1) Pin 속성 설정 :

 - SmartRobot Board의 J8-12 번핀 - PB8 을 Alternative Function 인 TIM4 Channel 3 로 설정

 

 GPIO_InitTypeDef GPIO_InitStructure;

 

 // TIM4 Ch3
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_Init(GPIOB, &GPIO_InitStructure);

 

2) TIM4 에 클럭 인가 : 클럭을 인가해야함 해당 Function이 동작한다.

 // RCC Configuration
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE );

 

3) 5KHz(20ms) 주기를 가지는 Timer 설정

 /* Time base configuration */

 // set to 1MHz Counter Clock
 TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t) (SystemCoreClock / 1000000) - 1;

 

// set to 5khz pulse with 1MHz Counter Clock
 TIM_TimeBaseStructure.TIM_Period = 20000-1;             // set to 50Hz PWM Clock


 TIM_TimeBaseStructure.TIM_ClockDivision = 0;
 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Down;
 TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

 

4) 0도에 해당하는 7.5% Duty Cycle 을 초기값으로 하는 PWM mode 설정

 /* PWM1 Mode configuration: Channel3 */
 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
 TIM_OCInitStructure.TIM_Pulse = 1500;                  // 50 % duty cycle value
 TIM_OC3Init(TIM4, &TIM_OCInitStructure);
 TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Disable);

 

5) Timer Enable

 TIM_ARRPreloadConfig(TIM4, ENABLE);

 TIM_Cmd(TIM4, ENABLE);

 

6) PWM duty cycle 변경

void change_pwm_duty_cycle(int percentx10)

{

   int pwm_pulse;

   pwm_pulse = percentx10 * 20000 / 100 ;
   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
   TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

   TIM_OCInitStructure.TIM_Pulse = pwm_pulse;

   TIM_OC3Init(TIM4, &TIM_OCInitStructure);

}

 

 

 

 

 

참조 :  http://www.thebackshed.com/forum/forum_posts.asp?TID=5611