본문 바로가기

공부생각/AVR C

[AVR C] 1. 서보모터 (Servo motor) 제어_ Atmega32 <뱀!>



Embedded System Project 에서 구현했던 것들...

1. Servo motor _ 서보모터
2. Keypad _ 키패드
3. Tachometer _ 타코미터
4. Delay _ 정확한 딜레이


Atmega32 _ DATASHEET (꼭 다운 받을것) 이거 안보면 헛거 -_-

다른 보드 사용하면 알아서 찾길 ㅠ


▶ 서보모터의 개략적인 설명

서보모터가 뭐하는 거냐하면, 시그널을 주입하면 그 시그널의 길이에 따라 모터가 돌아가게 되어있어. 그래서 내가 했던 자동차 프로젝트에서는 요놈을 휠로 썼더랬지. 휠이 므냐고... ㅡ_ㅡ 이놈을 가지고 바퀴의 방향을 조절했단 이말이지..

일단 시그널에 대해서는 나중에 설명하도록 하고, 시그널의 길이에 따라 0점에서 -85도~+85도 정도 움직일수 있어. 자동차 휠하기에는 딱 좋지 뱀!

음.. 더 얘기해줘야 할 것이 있나...

흠.. 없는듯?
메인보드(뭐건간에)에서 output PIN 을 이용해서 시그널을 서보모터로 보내는 이런 식이지..

▶ PWM 시그널 만들기 _ Generating PWM signal
Timer를 이용해서 일정한 길이의 시그널을 만들어. 일단 목표가 뭐냐믄 아래쪽에 있는 그림인데 차분하게 설명해볼께..

아 이거 제대로 설명하는 곳 없나고 존내 불평했었는데 설명하기 존나 어렵네 ㅠ 기본적인 베이스가 있다고 생각하께 ㅠㅠ 모르면 이메일 주던가 ㅠㅠㅠ

타이머를 사용하는데 예를 들어보자,
인풋클럭이 조옹나 빨라 그래서 이놈의 클럭에 맞춰서 뭐를 할라는데 너무 빨라서 감당이 안돼. 그럼 우짜까? 클럭을 축적시켜가지고 일정 클럭이 되면 마치 클럭이 한번 뛴것처럼 하면 (Interrupt)좀더 느리게 클럭이 꿈틀대겠지. 일단 이놈을 위해서 사용하는게 Prescaler 프리스케일러 라고, 클럭을 나눠주는거야 만약에

인풋클럭 : 16M
프리스케일러 : 1024

-> 실제로 사용하는 클럭길이 = 15625(16M/1024)개의 인풋 클럭길이

Atmega32 에서는 PWM signal을 위해서 타이머0, 타이머1 을 사용할 수 있는데 각 타이머마다 특징도 다르고, 뭘 고르냐에 따라 조정해야 될 레지스터도 다르니까 Datasheet을 한번 봐바

(PWM signal 도 여러가지가 있는데 여기서는 Fast PWM mode 로 설명하겠음)

>TCNT : 타이머 축척

>ICR1 : TCNT 타이머축척의 최대값, TCNT 값이 ICR1에 닿으면 set이 되던가 하는 식으로 조절할 수 있음

>OCR1 : TCNT가 여기 닿으면 PIN의 Signal 이 바뀐다. (어떻게 바뀌는지 바꾸고나서 어떻게 되는지는 여러가지 설정이 가능한데 설명할라카면 한도끝도 없어서 일단 간단하게 ㅠㅠㅠ)


자, 이제 타이머를 조정하기 위해 레지스터 얘기좀 해보자 일단...

⊙ TCCR1A


이 레지스터는 Timer1의 속성을 설정하는 놈이다.

> COM1A1:0 , COM1B1:0

이두놈은 같은데 output PIN에 따라 다르다. 이거가지고 한 두세시간 삽질했었지 ㅠㅠㅠ PWM signal을 어느 아웃풋 핀으로 보낼것인가에 따라서 다르니까 꼭 Data sheet하고 확인해 보도록..


> WGM11:0 밖에 없는데 TCCR1B레지스터에 WGM13:2 도 있으니 요놈 네개가 모두 같은 묶음...

이놈은 PWM 시그널의 종류 및 특성을 설정하는놈. 


-> 자세한 내용은 Datasheet 107page부터 표로 정리되어 있음, 자기가 필요한걸 고르길~ 정 모르겠으면, 나중에 아래쪽에 간단한 소스코드 올릴테니 참고하시라 뱀!


⊙TCCR1B



아까 위에서 말한 WGM13, WGM12 는 PWM시그널 종류 설정할때 쓰이는거고 중요한건

CS12:0 이놈이다!!

> CS12:0
이놈에게 값을 주는 순간 Timer를 스타트 하라는 명령이 된다.



이놈이 000 이면 타이머가 움직이지 않는 것이고,
설정함에 따라 특정 프리스케일러를 가지고 클럭을 돌리게 되.
이것은 입맛따라 하는거지뭐...

그럼 일단 초기화는 000으로 했다가 타이머가 필요한 시점에 키면 되것제?

( 아 야구보고 있는데 비오노 ㅠ)



흠 어쨋든, 뭐 대충 얘기가 끝난듯?

그럼 소스를 보면서 생각해보자.
#define CLK_IO 16000000
#define round(x) (int) (x + (x >= 0.0 ? 0.5 : -0.5)) //반올림 함수

Int main(){

//initialization
// ICR1에서 보면 이상한 계산이 있는데 이건 -> 0.02초, 20ms를 클럭의 한 주기로 만드려는 계산, 요고 아래에서 설명해주꼐
ICR1 = round( CLK_IO / PRESCALER * 0.02 ); TCCR1A = 0x20;
TCCR1B = 0x10;
TCNT = 0x00;

// 1.5ms 을 만들기 위한 OCR1B 를 설정하고
OCR1B = round(CLK_IO / PRESCALER * 0.015);

// Timer ON!
TCCR1B |= (1<<CS12);
TCCR1B &= ~(1<<CS11) & ~(1<<CS10);
}


위에 처럼 하면 가운데 1.5ms 의 시그널을 만들면서 서보모터가 가운데를 가르키게 된다.  뭐 대충한거니까 알아서 코드 꾸며 제길, 내가 무슨 과외 선생인가 -_-+ ㅋㅋㅋ

어쨋든 계산에 대해서 알려주께.
>ICR1 을 가지고 설명해보자.

서보모터는 20ms 를 주기로 PWM 시그널을 체크하거던? 그래서 전체적인 클럭의 주기는 20ms를 맞춰주는게 좋아 그래서

CLK_IO * 0.20 / PRESCALER
이라는 계산이 나와, 이게 무슨뜻이냐면, 20ms 를 만들기 위해서는 인풋클럭으로 몇개가 필요한가 를 계산하는거야. 한번 수학시간 가동시켜볼까 ㅠㅠㅠ 아 귀찮아 단위만 보자 단위만

CLK_IO = 횟수/초, 잖아? 그럼 단위만 줄줄 나열하면

횟수/ * / PRESCALER


약분되지? 이거 못따라 오면 난 모르겠따 배째.
그럼 결국 횟수가 나오는데 이 횟수가 아까 말한

투입한 초 와 같은 길이를 위해서는 주어진 인풋클럭이 몇개나 필요한가, 이거야.

OCR1B도 마찬가지지, 거기서는 0.015를 넣었잖아, PWM시그널을 1.5ms로 만들기 위해서, 흠흠 똑같은겨~


뱀!

아 끝낼래 힘들다 증말, 다음편은 나중에 ㅂㅂ

p.s. 데이터시트를 봐라 봐라 하는거 나도 쓔ㅣ발 하나도 모르겠는데 뭘 보란 얘기야 했는데, 여기저기서 잡다한거 읽어보고 보면~ 오호~ 정말 Data sheet에 다있구나 하는걸 느낄껴




<킅>

 

 



 

'공부생각 > AVR C' 카테고리의 다른 글

I2C IO-expander를 이용한 keypad의 구현  (6) 2009.08.11
[AVR_C] Volatile 변수에 대해서  (0) 2009.07.06