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 로 설정
// 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_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 변경
{
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