[ATmega128] 16bit PWM을 이용한 서보 모터 (SG90) 사용 방법
1. Servo Motor
서보모터는 sg90을 사용하고 스펙은 아래와 같다.


총 3개의 핀으로 구성되어있다.

위와 같이 데이터 시트 설명을 보면 50Hz의 주파수로 동작해야 하며 1~2ms의 high 신호를 주어 제어한다.
1.5ms인 경우 0도, 1ms인 경우 -90도 그리고 2ms인 경우 +90도로 동작한다.
2. 16bit PWM 제어
8비트 타이머 카운터를 사용해 PWM을 제어하면 fast Mode에서는 최대 16.384ms 약60Hz 정도가 나와 50Hz 사용이 불가능하고 Phase Correct PWM 모드를 사용하더라도 분주비 설정으로 50Hz를 만들 수 없다.
때문에 16비트 타이머 카운터를 사용해 50Hz를 만드는 작업을 해야한다.
16비트 타이머 카운터를 사용하면 더 큰 수 (0~65535)를 이용해 오버플로우 MAX (TOP)를 더 크게 설정할 수 있기 때문에 PWM 주기를 더 세분화하여 설정할 수 있다.

그리고 TOP 값은 OCRnA와 ICRn 레지스터를 사용해 설정할 수 있다.

이번 예제에서는 14번 모드를 설정하여 ICRn을 사용해 TOP을 설정하고 Fast PWM 모드로 제어한다.
임의로 OC3A 핀 (PE3)을 사용해 출력하는 걸로 설명을 한다.





50Hz (20ms 주기)와 1~2ms 설정이 용이하도록 분주비를 64로 설정한다.
* Period
=> 0.0625us (16MHz - 보드 클럭) * 64 (분주비) = 4us
=> 4us * 5000 (TOP) = 20ms
주기 계산식과 동일하게 틱당 4us로 계산하여 1ms ~ 2ms duty rate를 위해 OCR3A를 250 ~ 500으로 설정해 비교매치가 일어나도록 설정한다.
3. 회로 구성


4. 예제 코드
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
/* 16MHz(≈0.0625㎲) */
/* 0.0625㎲ * 64 * ICR3 */
int main(void)
{
DDRE = 0x08; // PE3 output
TCCR3A = 0x82; // COM3A1 set, WGM31 set
TCCR3B = 0x1b; // WGM33, 32 set, CS31, 30 set
ICR3 = 4999; //5000 tick
// OCR3A 1 ~ 2ms range => 249 ~ 499
int startCnt = 149;
int endCnt = 600;
while (1)
{
for(int i = startCnt; i < endCnt; i++)
{
OCR3A = i;
_delay_ms(10);
}
}
return 0;
}
실제 동작 확인해보니 계산했던 범위보다 더 넓게 줘야 180도로 동작하는 게 확인되어 위처럼 설정한다.
5. 동작 영상