본문 바로가기

나래온 1기(~2012.6)/라인트레이서 이야기

(3부작) 라인트레이서 이야기 - 번외 #4 힘찬 시작을 위하여, 모터 파워 온!

 

 오늘은 이제 모터를 구동해 볼 차례입니다.
 일단 소스 먼저 보... 려다가는 저번 회의 전설의 명화 뭉크의 '절규'님이 또 나타나실것 같은 예감에 지식 먼저 쌓고 시작도록 합시다.


것이 오늘 배울 곳!
---------------------------------------------------------------------------
핵심어
1. if (조건)
: 조건이 참(= 1)일 경우 {} 안을 실행합니다
2. & : AND 연산자입니다.(둘 다 1이어야지 1이 반환됩니다)
3. | : OR 연산자입니다.(둘 중 하나만 1이어도 1이 반환됩니다)
4. ~ : 보수 연산자입니다.(1이면 0이, 0이면 1이 반환됩니다)
5. P(포트)(숫자) : 포트의 숫자 번 비트를 말합니다
---------------------------------------------------------------------------

숙지하셨다면 소스를 봅시다.

DC 모터 버전
출처 : 따르미 Pro 2008(하늘아이 社) DC 모터 버전 - link.c
void DC_MOVE(int L_POW, int R_POW) // motor speed & direction
{
 unsigned char DCdir_L=0;
 unsigned char DCdir_R=0;
 if(L_POW>1023)  L_POW=1023;  
 if(L_POW<-1023) L_POW=-1023;
 if(R_POW>1023)  R_POW=1023;
 if(R_POW<-1023) R_POW=-1023;
 if(L_POW>0)  {LMEN=L_POW; DCdir_L=0x08;}//cw
 else if(L_POW<0){LMEN=-L_POW; DCdir_L=0x04;}//ccw
 else    {LMEN=1023;  DCdir_L=0x0C;}//stop
 PORTD=DCdir_L; //DCdir_L은 OCR1B와 같습니다
 if(R_POW>0)   {RMEN=R_POW; DCdir_R=0x01;}//ccw
 else if(R_POW<0){RMEN=-R_POW; DCdir_R=0x02;}//cw
 else   {RMEN=1023;  DCdir_R=0x03;}//stop
 PORTC=DCdir_R;  //DCdir_R은 OCR1A와 같습니다
}

해설
1. 절대값이 1023 초과인지 확인하고 초과이면 1023으로 고정합니다
2. 양수인지 음수인지 나눠서 보냅니다
3. OCR변수에는 속도의 절대값을 지정합니다
4. 속도가 음수인 경우
왼쪽 : PORTD에서 세번째 비트 켜고 네번째 비트를 끕니다(00000100)
오른쪽 : PORTC에서 두번째 비트 켜고 첫번째 비트를 끕니다(00000010)
5. 속도가 양수
인 경우
왼쪽 : PORTD에서 세번째 비트 끄고 네번째 비트를 켭니다(00001000)
오른쪽 : PORTC에서 두번째 비트 끄고 첫번째 비트를 켭니다(00000001)
6. 속도가 0인 경우 앞 뒤 조절에 쓰는 비트 다 켭니다(00001100 or 00000011)




서보 모터 버전
출처 : 따르미 Pro 2008(하늘아이 社) 서보 모터 버전 - main.h
 SIGNAL(SIG_OVERFLOW1)
{
 int lstat = 0;
 int rstat = 0;
 if(timer>=10) timer = 0;
 else
 {
  timer++;
 }
 if(testleftspeed<0) lstat = 1;
 if(testrightspeed<0) rstat = 1;
 
 if((lstat==0) && (timer<testleftspeed/100))
 {
  PORTD &= ~(1<<PD3);
  PORTD |=  (1<<PD2);
 }
 else if((lstat==1) && (timer< -(testleftspeed/100)))
 {
  PORTD |=  (1<<PD3);
  PORTD &= ~(1<<PD2);
 }
 else
 {
  PORTD &= ~(1<<PD3);
  PORTD &= ~(1<<PD2);
 }
 if((rstat==0) && (timer<testrightspeed/100))
 {
  PORTC &= ~(1<<PC0);
  PORTC |=  (1<<PC1);
 }
 else if((rstat==1) && (timer<-(testrightspeed/100)))
 {
  PORTC |=  (1<<PC0);
  PORTC &= ~(1<<PC1);
 }
 else
 {
  PORTC &= ~(1<<PC0);
  PORTC &= ~(1<<PC1);
 }
TCNT1 = 1000;    
}


해설

1. 10번 타이머 돌때까지 timer 변수에 1을 더합니다
2. 양수인지 음수인지 나눠서 보냅니다
3. 숫자 세 놓은게 속도 ÷ 100과 같아질 때까지
왼쪽 : PORTD를 모조리 끕니다
오른쪽 : PORTC를 모조리 끕니다
4. 숫자 세 놓은게 속도 ÷ 100과 같으면 다음으로
5. 속도가 음수인 경우
왼쪽 : PORTD에서 세번째 비트 켜고 네번째 비트를 끕니다(00000100)
오른쪽 : PORTC에서 두번째 비트 켜고 첫번째 비트를 끕니다(00000010)
6. 속도가 양수인 경우
왼쪽 : PORTD에서 세번째 비트 끄고 네번째 비트를 켭니다(00001000)
오른쪽 : PORTC에서 두번째 비트 끄고 첫번째 비트를 켭니다(00000001)


.
.
.

클라나드...

이건 뭐야...

 이번 회는 분량이 좀 쎄죠?
 저도 정리하느라 머리가 상당히 힘들었습니다.(원래는 구버전의 경우 그냥 값 지정으로 처리할 수 있는건데 신버전에서는 AND와 OR가 난무하다 보니...)

 소스를 보시니 좀 이해가 가시나요?
 어라? 그런데 뭔가가 좀 이상합니다.
 뭐가 이상할까요?
 DC 모터 버전과 서보 모터 버전을 쭈~욱 살펴보시기 바랍니다.
.
.
.
.
.
.
.
.
 서보 모터 버전은 신호가 SIG_OVERFLOW인 것으로 봐서 타이머 활동인 것 같은데 DC 모터 버전과 왜 위치가 다를까요?
 사실 DC 모터 버전의 경우 OCR(포트)가 타이머와 계속해서 비교하는 것이기 때문에 서보 모터 버전과 비슷합니다.
 왜 이번 버전에 이렇게 바뀐건지는 잘 모르겠네요.(* 하늘아이 관계자 분들이 보시면 꼭 답을 해 주셨으면 좋겠네요 ^^)






ps. 참고로 서보 모터 버전에서는 DC_MOVE함수를 이렇게 쓴답니다.

출처 : 따르미 Pro 2008(하늘아이 社) 서보 모터 버전 - link.c
void DC_MOVE(int L_POW, int R_POW) // motor speed & direction
{
 testleftspeed = L_POW;
 testrightspeed = R_POW;
}

 상당히 썰렁하죠?
 저 위의 타이머 오버플로 신호 처리 때 값만 넘겨주는 역할로 바뀐 것 같습니다.
 그런데 왜 서보 모터인데 이름을 DC_MOVE로 쓰는지는 미스테리네요.(* 이전 버전과의 호환성 문제인 듯 합니다)