전에 스마트폰으로 대~충 적어서 서보모터 제어한 걸 올렸었는데
그건 보기도 불편하고 아무런 사진이나 소스등이 없어서 나중에 보기 편하게 자료 정리하기로 결정.
짜둔 소스랑 중간에 발생한 문제점을 어떻게 해결하였는지 좀 잘 써본다
먼저 서보모터 제어를 위해 가장 먼저 알아야 할 것은 PWM과 Duty 에 관해서 이다.
위 두가지를 기본적으로 알고 있어야 서보모터를 시작할 수 있으니 모르는 경우 일단 그것부터 알아보고오길..
이 글은 내 생각정리 용이므로 저 두가지는 당연히 알고 있다는 가정하에 생략하겠다
그 두가지를 알면, 이제 Coding을 하면 되는데...
1. PORT 설정을 한다.
1 2 3 4 5 6 7 8 9 10 11 | /*=========PORT IO 설정========*/ void PORT_init(void){ cli(); //모든 인터럽트 사용금지 /* 입출력 레지스터 */ DDRB=0xFF; //PB6: OC1B Pin.(1개) //OC1A(PB5):LPWM, OC1B(PB6):PWM_servo, OC1C(PB7):RPWM, PB3: EN, PB4: DIS PORTB=(1<<OC1A)|(1<<OC1B)|(1<<OC1C)|(1<<EN)|(1<<DIS); sei(); //SREG 레지스터 "I"비트 "1" 값으로 설정 //I 비트가 "0"이면 모든 인터럽트 작동X. } |
뭐 이런 식으로 따로 Function을 만들어 사용하는게 편하다.
여기서 PORTB 는 내가 사용한 Timer 1 과 관련된 OC1A, OC1B, OC1C 핀들이
이 PORTB 핀에 속하기에 설정해주었다.
저 3가지 핀 중 난 OC1B 핀인 PB6 을 서보모터에 사용했다
※ OC1A, OC1B 등은 define으로 미리 정의해 두었다.
2. Timer/Couter 1 설정을 해준다(PWM 설정)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | /* 타이머/카운터1 레지스터 */ void PWMS_init(void) { cli(); //모든 인터럽트 사용금지. // Timer/Counter1 로 PWM 사용하는 경우 // WGM13:12:11:10=0101 Fast PWM(8-bit) // COM1B1:COM1B0=11 Compare Match에서 OCR 일치시 H. 오버플로우 시 L. // CS12:11:10=101 clk/1024 분주비. 주기 : 16.32ms TCCR1A=(0<<WGM11)|(1<<WGM10)|(1<<COM1B1)|(1<<COM1B0); TCCR1B=(0<<WGM13)|(1<<WGM12)|(1<<CS12)|(0<<CS11)|(1<<CS10); TCNT1L=217; //주기: 2.4ms. 256-n. n=16.(1024/16000000=64us. 1ms=64us x 16.) OCR1BL=240; //0~240 Low. 240~255까지 H. 1/1024 분주비일때 1ms. //233 중앙 239 제일왼쪽 225 제일 오른쪽 TIMSK=(1<<TOIE1)|(1<<OCIE1B); //타이머/카운터1 Overflow 인터럽트 허용. //OC1B Compare Match 인터럽트 허용. sei(); //SREG 레지스터 "I"비트 "1" 값으로 설정 //I 비트가 "0"이면 모든 인터럽트 작동X. } /* 타이머/카운터1 루틴 iom128.h 파일 참조. */ SIGNAL(SIG_OUTPUT_COMPARE1B) { } SIGNAL(SIG_OVERFLOW1) { TCNT1L=217; } |
이 Function은 Servo motor용 PWM제어 함수인데,
주기: 2.4ms 로 TCNT1L 값이 설정된 217부터 255까지 Count 되는데 걸리는 시간이 약 2.432ms 이다.
TCNT1L이 255가 되어 Overflow interrupt 가 되는 순간 SIG_OVERFLOW1 이 가리키는 루틴 함수로 들어가게 되고
다시 TCNT1L은 217 이 되게 된다.
그리고 Duty는 OCR1BL이 240인 경우 TCNT1L이 240이 된 순간 High신호가 Output되고 그 순간 SIG_OUTPUT_COMPARE1B가 가리키는 루틴함수로 들어가게 된다. 따라서 이 루틴함수를 꼭 소스에 첨부해야한다. 그다음 TCNT1L이 255가 되어 Overflow 되면 다시 Low가 된다.
3. PWM을 실행한다.
이제 위에서 모든 설정은 끝났다.
남은건 내가 원하는 Duty 를 OCR1BL 에 넣으면 해당하는 시간만큼 High를 유지하게 된다.
테스트해본 결과,
OCR1BL = 233 인 경우(=1.4ms) 바퀴가 정가운데
OCR1BL = 239 인 경우(=1.0ms) 바퀴가 제일 왼쪽
OCR1BL = 225 인 경우(=1.9ms) 바퀴가 제일 오른쪽
뭐 이런 식으로 해서 동작하게 된다.
위에서 언급한 1.0ms, 1.4ms, 1.9ms는 내가 사용한 자동차에 달린 서보모터의 경우이고
실제 이 서보모터는 180도까지 지원되는 모델이므로 이보다 더 넓은 범위에서 동작하게 된다.
위 소스를 이용하면 쉽게 서보모터를 제어할 수 있다.
다만 서보모터마다 Duty가 약간씩 다르므로 그점은 유의해야 한다.
이제 실행한 모습을 보겠다
파형은 이처럼 깔끔하게 나온다.
그럼 동작모습을 보자
뭐 대충 이런식??
이로인해 서보모터 제어는 끝났다.
다음에 DC모터 제어에대해 올리겠다.
그럼 이만...
ps. 노이즈가 심해 서보모터가 지맘대로 움직이는 경우가 있는데 이경우 전압이 부족한거 일 수 있으니
5V의 전압을 제대로 줘야한다.(7805 레귤레이터의 경우 7V이상의 Input을 줘야 정확히 동작한다.)
또한 그라운드를 확실히 연결해줘야 제대로 동작하니 참고한다.
'Project > └ ATmega128' 카테고리의 다른 글
TFTLCD 참고 소스 (3) | 2013.10.02 |
---|---|
[AVR]서보모터 제어 (1) | 2013.09.12 |