로봇카 기초 배우기

아두이노 로봇카

3. 서보모터 조립과 동작 그리고 주행하기

Contents

아두이노 로봇카 실습 세부목차


1. 프라이비 에듀 마이컴 보드 시작하기 

2. LED동작과 서보모터 제어 

3. 서보모터 조립과 동작 그리고 주행하기 

4. 더듬이센서로 주행하기 

5. 포토트랜지스터로 주행하기 

6. 적외선센서로 주행하기 

7. 주행거리 제어하기


※ 본 페이지의 내용은 패럴렉스(Learn.Parallax.com)사의 공식 홈페이지에서 제공되는 자료를 참고하여 작성되었습니다. 또한, 본 내용은 아두이노 neo-로봇카v2 또는 아두이노 로봇카N 키트실습에 사용할 수 있습니다.


본 자료의 원문을 참조하려면 패럴렉스 사의 아두이노를 위한 로보틱스 홈페이지를 방문할 수 있습니다. 이 자료의 로봇카 모든 제어명령 및 센서신호 수집작용은 프라이비 보드 또는 아두이노를 통하여 수행됩니다. 프라이비 보드는 아두이노 우노와 동일한 ATmega328P 마이컴이 사용된 호환보드이며, 아두이노 우노와 동일한 사용법이 적용됩니다.


아래 내용을 시작할 때 이미 조립된 로봇카를 준비하고 있다면, 조립단계를 건너뛰어도 좋습니다. 로봇카 동작을 시작하기 위한 시작신호를 만들거나, 주행속도를 제어하는 방법에 대하여 실습합니다. 그리고 함수 개념을 사용하여 더 다양한 로봇카 동작을 만들 것입니다. 여러분의 필요에 맞는 내용을 아래 링크에서 선택할 수 있습니다.


아래 세부 내용들을 살펴볼 수 있습니다.

1) 아두이노 neo-로봇카 v2 키트 조립하기

2) 서보모터 다시 점검하기

3) 로봇카 동작 시작신호 만들기

4) 로봇카의 속도제어 실습


로봇카의 주행동작에서 함수개념을 적용하여 천천히 원리를 이해하고 각각의 동작을 조금 더 쉽게 배울 수 있습니다. 


아래 링크들을 활용하기 바랍니다.

5) 로봇카 3초간 전방으로 전진하고 정지하기

6) 로봇카 후진 및 좌/우 회전 실습하기

7) 로봇카 중심축 회전하기

8) 로봇카 주행거리 계산하기

9) 로봇카 가속/감속 주행하기

10) 로봇카 주행거리 계산하기


로봇카 조립부터 시작하거나, 또는 이미 조립된 로봇카를 가지고 실습을 시작하는지에 따라 다음부터 소개하는 조립과정을 건너뛸 수 있습니다. 시작해볼까요!


1) 아두이노 neo-로봇카 v2 키트 조립하기


지금부터 설명하는 조립은 가장 표준방식으로 로봇카를 조립하는 것입니다. 사용자에 따라서 순서를 바꾸어 조립할 수도 있습니다. 하나의 부품도 빠지지 않도록 천천히 조립하세요. 로봇카 조립에 필요한 드라이버와 구성품들을 빠짐없이 준비해서 조립을 시작합니다.


단계 1 : 섀시에 서보모터 조립하기

1)   섀시 중앙의 구멍에 고무링을 끼운다.

2)   서보모터에서 서보혼을 빼고, 섀시에 볼트-너트를 사용하여 고정한다.


  그림입니다. 원본 그림의 이름: CLP00001b580013.bmp 원본 그림의 크기: 가로 217pixel, 세로 163pixel  그림입니다. 원본 그림의 이름: CLP00001b580014.bmp 원본 그림의 크기: 가로 218pixel, 세로 163pixel


  그림입니다. 원본 그림의 이름: CLP00001b580015.bmp 원본 그림의 크기: 가로 187pixel, 세로 140pixel  그림입니다. 원본 그림의 이름: CLP00001b580016.bmp 원본 그림의 크기: 가로 240pixel, 세로 139pixel


단계 2 : 배터리홀더 조립하기

1)  5AA배터리 홀더를 아래 사진과 같은 방향으로 끼운다.

2)  플라스틱 납작머리 나사 2개를 사용하여 스탠드오프, 섀시와 함께 고정한다.

  

그림입니다. 원본 그림의 이름: CLP00001b580017.bmp 원본 그림의 크기: 가로 209pixel, 세로 157pixel  그림입니다. 원본 그림의 이름: CLP00001b580018.bmp 원본 그림의 크기: 가로 210pixel, 세로 157pixel


그림입니다. 원본 그림의 이름: CLP00001b580019.bmp 원본 그림의 크기: 가로 209pixel, 세로 157pixel   그림입니다. 원본 그림의 이름: CLP00001b58001a.bmp 원본 그림의 크기: 가로 210pixel, 세로 157pixel


단계 3 : 바퀴 조립하기

1)  바퀴와 고무링을 결합하고, 서보모터에 끼운다. (서보모터의 나사를 사용하여 고정한다.)

2)  나머지 세번째 바퀴는 플라스틱 볼을 분할핀으로 고정한다.


그림입니다. 원본 그림의 이름: CLP00001b58001b.bmp 원본 그림의 크기: 가로 209pixel, 세로 157pixel  그림입니다. 원본 그림의 이름: CLP00001b58001c.bmp 원본 그림의 크기: 가로 210pixel, 세로 157pixel

  

단계 4 : 프라이비 에듀 마이컴 보드 조립하기

1)  스탠드오프를 섀시에 고정한 후, 프라이비 에듀 마이컴 보드를 스탠드오프와 결합한다.

1)  (마이컴 보드의 연결방향은 아래 사진을 참고한다)

2)  서보모터 연결선을 보드와 연결하고, 배터리 전원을 연결한다.


  그림입니다. 원본 그림의 이름: CLP00001b58001d.bmp 원본 그림의 크기: 가로 209pixel, 세로 157pixel  그림입니다. 원본 그림의 이름: CLP00001b58001e.bmp 원본 그림의 크기: 가로 205pixel, 세로 154pixel


  그림입니다. 원본 그림의 이름: CLP00001b58001f.bmp 원본 그림의 크기: 가로 208pixel, 세로 156pixel  그림입니다. 원본 그림의 이름: CLP00001b580020.bmp 원본 그림의 크기: 가로 205pixel, 세로 154pixel


2) 서보모터 다시 점검하기


서보 중심맞추기를 통해서 서보의 하드웨어 초기상태는 정확하게 1500 (또는 1.5ms 조건)에 맞추었지만, 로봇카 측면에서는 추가로 조정해야할 작업이 남아있습니다.


그림입니다. 원본 그림의 이름: CLP00001b580021.bmp 원본 그림의 크기: 가로 540pixel, 세로 406pixel


가령 왼쪽 바퀴를 구동하는 서보와 오른쪽 바퀴를 구동하는 서보가 바르게 설정되어 있는가에 따라 여러분의 스케치와 로봇카가 동일하게 동작할 수 있고, 그렇지 않을 수도 있습니다. 이제 이런 작업을 모두 일치시키기 위해 몇가지를 점검합니다.


오른쪽 바퀴와 왼쪽바퀴 점검하기 (그림의 오른쪽과 왼쪽을 참고하기 바랍니다)


우리는 오른쪽 바퀴 서보제어를 위해 디지털핀 12번을 사용합니다. 물론 본인의 판단에 따라 다르게 설정되어도 좋습니다. 아래 스케치를 보드에 업로드하고 오른쪽 바퀴가 정상적으로 동작하는지 살펴봅시다. 참고로 우회전 방향의 바퀴가 오른쪽 바퀴입니다.


#include <Servo.h>

Servo servoRight;

void setup()

{

  servoRight.attach(12);  

  servoRight.writeMicroseconds(1300);  

  delay(3000);  

  servoRight.writeMicroseconds(1500);  

  delay(1000);  

  servoRight.writeMicroseconds(1700);  

  delay(3000);

  servoRight.writeMicroseconds(1500);

void loop()

}


여러분의 예상대로 오른쪽 바퀴가 시계방향으로 3초회전하고 잠시 1초간 정지하다가 다시 반시계방향으로 3초간 회전하고 정지하는가? 이런 동작을 다시 재현하려면 보드의 리셋(RESET) 버튼을 누르십시오. 위 동작을 다시 한번 반복합니다.


여러분의 왼쪽바퀴를 동일한 방법으로 재현하려면 위 스케치의 디지털핀 번호를 12에서 13으로 변경합니다. 그렇지만 조금더 정확한 의미를 부여하기 위해 스케치에서의 서보 이름도 servoRight 에서 servoLeft 로 고치면 좋습니다.


여러분의 서보가 예상과 동일하게 잘 동작하는가요? 만약 그렇지 않다면 몇가지 원인을 생각해볼 수 있습니다.


서보가 돌지 않는가? 전원이 정상적으로 공급되지 않을 가능성이 높습니다. 하드웨어적인 연결상태를 다시 꼼곰하게 점검하기 바랍니다. 여기에는 서보의 3핀케이블을 보드에 연결하는 지점이 바르게 연결되었는지 살펴보아야 합니다. 나머지 한가지는 3접점 스위치 방향이 맨 오른쪽으로 변경되어 정상적으로 전원이 공급되는지를 살펴보아야 합니다.


오른쪽 서보와 왼쪽 서보가 서로 바뀌어 동작하는가? 그렇다면 보드와 연결된 두 개의 서보 연결핀을 뽑아서 서로 바꿔 다시 연결하면 해결됩니다. (참고: 로봇카 하드웨어 연결 작업은 로봇카 전원을 차단하고 실시하기 바랍니다.)


몇 초간의 실습점검이후에도 바퀴가 정지하지 움직이는가? 만약 그렇다면 서보 중심 맞추기를 다시 시도해야 합니다. 조금은 번거로운 작업이지만, 반드시 다시 실시하는 것이 이후 실습의 원만한 진행을 위하여 필요합니다.


3) 로봇카 동작 시작신호 만들기


로봇카 동작을 위한 스케치가 언제 시작하는지 소리로 표시하기 위하여 간단한 부저 회로를 만들어봅시다. 여러분의 부품들중 부저는 양극과 음극을 가지고 있어서, 용도에 맞게 사용하려면 부저에 붙은 극성 표시를 떼지 않도록 해야 합니다.


그림입니다. 원본 그림의 이름: CLP00001b580022.bmp 원본 그림의 크기: 가로 299pixel, 세로 275pixel



로봇카에서 하드웨어 부품을 연결하거나 제거할 때는 반드시 전원을 차단하고, 진행하는 것이 좋습니다. 전원을 먼저 차단한 후, 위 그림과 같이 부저를 연결하세요.


부저(또는 "피에조스피커"라고 부르기도 한다.)를 동작하기 위해 tone() 함수를 사용할 수 있습니다. tone() 함수는 두가지 선택사항을 지정할 수 있는데, 하나는 pin 번호이고, 다른 하나는 소리의 주파수 선택을 위한 것입니다. 그리고 소리가 지속되는 시간을 지정할 duration 값을 사용할 수 있습니다.


     tone( pin, frequency)

     tone( pin, frequency, duration)


부저는 4.5KHz 로 실행되도록 설계되어 있지만, 다양한 음 높이의 소리도 낼 수 있습니다. 대개 1KHz ~ 3.5KHz 범위에서 가장 좋은 소리가 나오기 때문에 로봇카 실습에서는 시작 알림음을 아래와 같이 사용할 것입니다.


    tone(4, 3000, 1000);

    delay(1000);


위 스케치 코드는 아두이노 디지털핀 4번에 부저가 연결되어 3KHz의 진동수 소리음을 1초간 지속하는 것의 명령문장입니다. 소리음이 지속되는 시간동안 다음 명령이 실행되지 않도록 하기 위하여 delay(1000); 문장을 추가하였습니다. 다시 설명하면 소리음이 종료된 후, 다음 단계 명령이 실행되도록 하기 위함입니다.


void setup()

{

   tone(4,   3000, 1000);

   delay(1000);

void loop()

}


위 코드는 여러분의 로봇카 동작에서도 다양하게 응용되어 사용될 수 있습니다. 가령 로봇카가 전진할 때와 후진할 때 그리고 좌회전과 우회전을 시도할 때 각각 다른 소리음이 나도록 설계할 수 있습니다.


4) 로봇카의 속도제어 실습


본 로봇카에 사용된 Parallax 연속회전형 서보의 전달곡선 그래프를 참고하면 쉽게 로봇카의 주행속도를 제어할 수 있습니다. 아래 서보 그래프는 1300에서 1400까지 회전속도가 완만히 변화하다가 1400에서 1500 사이에서 급격하게 회전수 변화가 발생합니다. 그리고 1500을 전후하여 회전방향이 반대방향으로 바뀌고 1600까지 회전속도가 급격이 다시 증가하다가 1600 부터 1700까지 다시 완만한 속도변화를 나타냅니다.


이제 여러분은 로봇카의 진행속도를 제어하기 위해 어떤 값들을 선택해야 하는지 어떤 영감을 얻었으리라 생각합니다. 실제로 서보 바퀴의 회전속도를 제어할 수 있는 실질적인 제어범위는 1400 ~ 1500 (시계 방향 회전) 과 1500 ~ 1600 (반시계 방향 회전)사이의 값이라는 것을 참고할 수 있습니다.


그림입니다. 원본 그림의 이름: CLP00001b580023.bmp 원본 그림의 크기: 가로 405pixel, 세로 240pixel


로봇카의 주행속도를 점진적으로 증가시키거나 감소시키는 코드를 구형할 수 있을까? 지금까지의 여러분 경험을 이용하여 시도해봅시다. 로봇카의 전진속도와 후진속도를 다르게 사용할 수 있을까? 두 개의 다양한 서보 속도개념을 적용하여 죄회전과 우회전 동작도 매우 다양하게 설계하여 표현할 수 있습니다. 여러분의 상상은 어떤 것들인가요?


5) 로봇카 3초간 전방으로 전진하고 정지하기


지금부터 로봇카의 간편한 동작을 시도하기 위하여 함수 개념을 활용합니다. 로봇카의 모든 주행동작은 아래 방향설정을 기준으로 합니다. 여러분도 아래 방향설정에 대한 기준을 고려하여 프로그램을 이해하십시오.


그림입니다. 원본 그림의 이름: CLP00001b580021.bmp 원본 그림의 크기: 가로 540pixel, 세로 406pixel


로봇카의 모든 동작은 서보 라이브러리의 writeMicroseconds() 함수 값을 다양하게 변화하면서 만들어 낼 수 있습니다. 각각의 로봇 동작사이를 구분하기 위해서는 주로 delay() 함수를 사용하지만, 이전에 설명한 바와 같이 부저 소리음을 추가로 사용할 수도 있습니다. 아래 스케치를 보드로 업로드하십시오.


#include <Servo.h>

Servo servoLeft;

Servo servoRight;

void setup()

{

   tone(4, 3000, 1000);

   delay(1000);

   servoLeft.attach(13);

   servoRight.attach(12);


   servoLeft.writeMicroseconds(1700);

   servoRight.writeMicroseconds(1300);

   delay(3000);


   servoLeft.detach();

   servoRight.detach();

void loop()

}


스케치를 업로드하면 로봇카는 전속력으로 3초간 전진하고 정지해야 합니다. 만약 무한히 전진하도록 스케치를 변경하려면 writeMicroseconds() 함수를 loop() 함수로 옮기고, detach() 함수를 제거하면 됩니다.


6) 로봇카 후진 및 좌/우 회전 실습하기


로봇카를 후진하게 하려면 servoLeft와 servoRight의 writeMicroseconds() 함수값을 서로 바꾸면 됩니다. 그렇게 하면 로봇카의 좌측과 우측 바퀴가 이전과는 반대방향으로 회전하기 때문에 로봇카는 후진하게 됩니다.


   servoLeft.writeMicroseconds(1300);   // Left wheel clockwise

   servoRight.writeMicroseconds(1700);  // Right wheel counterclockwise


아래 스케치는 좌회전과 우회전을 위한 로봇카 동작을 위한 것입니다.


   좌회전을 위한 서보 스케치

   servoLeft.writeMicroseconds(1300);    // Left wheel clockwise

   servoRight.writeMicroseconds(1300);   // Right wheel clockwise


   우회전을 위한 서보 스케치

   servoLeft.writeMicroseconds(1700);     // Left wheel counterclockwise

   servoRight.write Microseconds(1700);   // Right wheel counterclockwise


지금까지의 로봇카 동작을 모두 함께 연결해서 구현할 수 있습니다. 아래 스케치를 업로드하여 시도해봅시다.


#include <Servo.h>

Servo servoLeft;

Servo servoRight;

void setup()

{

tone(4, 3000, 1000);

delay(1000); 

servoLeft.attach(13); 

servoRight.attach(12); 


servoLeft.writeMicroseconds(1700);  

servoRight.writeMicroseconds(1300);  

delay(2000); 


servoLeft.writeMicroseconds(1300);  

servoRight.writeMicroseconds(1300);  

delay(600); 


servoLeft.writeMicroseconds(1700);  

servoRight.writeMicroseconds(1700);  

delay(600); 


servoLeft.writeMicroseconds(1300);  

servoRight.writeMicroseconds(1700);  

delay(2000); 


servoLeft.detach(); 

servoRight.detach();

void loop()

}


7) 로봇카 중심축 회전하기

 

로봇카 중심축 회전은 제자리에서 회전하는 것을 말합니다. 로봇카는 두바퀴로 움직이는 구조이기 때문에 제자리 회전을 간단히 구현할 수 있습니다. 원리는 하나의 바퀴는 회전하지만, 나머지 다른 하나의 바퀴는 회전하지 않고 정지해 있는 것입니다. 그러면 정지한 바퀴를 중심으로 로봇카가 회전할 수 있습니다.


이런 로봇카의 중심축 회전을 농구경기처럼 피봇회전이라고 할 수 있는데, 전체 4가지 경우로 나누어 생각할 수 있습니다. 다음에 소개하는 스케치 종류들을 참고하기 바랍니다.


// Pivot forward-left

servoLeft.writeMicroseconds(1500); // Left wheel stop

servoRight.writeMicroseconds(1300); // Right wheel clockwise

// Pivot forward-right

servoLeft.writeMicroseconds(1700); // Left wheel counterclockwise

servoRight.writeMicroseconds(1500); // Right wheel stop

// Pivot backward-left

servoLeft.writeMicroseconds(1500); // Left wheel stop

servoRight.writeMicroseconds(1700); // Right wheel counterclockwise

// Pivot backward-right

servoLeft.writeMicroseconds(1300); // Left wheel clockwise

servoRight.writeMicroseconds(1500); // Right wheel stop


이런 다양한 로봇카 동작을 구현할 수 있다면, 로봇카가 포물선을 그리면서 좌회전 또는 우회전하는 동작도 쉽게 구현할 수 있을 것입니다. 물론 회전반경을 정확하게 구현하는 것을 한번의 시도로 쉽게 구현하는 것은 현재의 서보 제어방식만으로는 간단하지 않을 수 있습니다.


로봇카의 좌측과 우측 바퀴 회전속도를 어떻게 선택 제어하는가에 따라 로봇카는 직선운동을 하거나 곡선운동을 합니다.


여러분의 로봇카가 전진하거나 후진하는 서보동작을 제어하는 것은 비교적 간단합니다. 그렇지만, 정확히 좌측으로 90도 회전하거나 정확히 90도 우측으로 회전하는 것은 생각보다 간단하지 않습니다. 여러분은 여러 번의 시행착오를 거쳐 회전조건에서의 지연함수 delay() 함수 시간을 조절하는 방법으로 90도 회전하는 조건을 찾을 수 있습니다.


여러분이 직접 로봇카의 좌측 90도 회전 또는 우측 90도 회전할 수 있는 정확한 명령코드값을 여러번의 실습으로 찾아보기 바랍니다. 이렇게 찾은 실헙 값은 이후의 로봇카 실습과정들에서 다양하게 응용하는데 사용됩니다.


8) 로봇카 주행거리 계산하기


본 실습은 로봇카의 주행거리를 사전에 예상할 수 있도록 합니다. 다시 설명하면 어떤 약속된 주행경로를 사전에 미리 설계하여 주행하도록 명령할 수 있다는 의미입니다. 꽤 복잡한 도시의 도로를 어떤 센서로 감지하고 주행하는 것과 달리 사전에 설계된 경로로 로봇카가 주행하도록 설계할 수 있다는 의미입니다. 물론 오차가 어느 정도 발생하는지는 공학을 대하는 학생들의 노력에 따라 다르게 나타날 수 있습니다.


먼저 로봇카의 주행거리는 물리학의 법칙을 사용하여 아래 공식으로 계산할 수 있습니다.


   주행시간(Time) = 주행거리(Distance) / 주행속도(Speed)


동일한 원리를 로봇카에 적용하면 다음식으로 관련지어 생각할 수 있습니다.


   서보 동작시간 = 로봇카 진행거리 / 로봇카 속도


여러분은 다음 그림과 같이 로봇카의 진행방향으로 자를 놓고 실제로 로봇카가 진행한 거리를 제법 정확하게 측정할 수 있습니다. 측정 오차를 줄이려면 동일한 조건에서 여러 번 실험을 반복하여 그 값을 평균하면 됩니다. 아래 그림과 같이 로봇카를 놓고 스케치를 전속력 전진모드에서의 속도를 구해보세요. 로봇카는 1초간만 전진할 것입니다. 그래서 측정되는 거리 값이 곧 로봇카의 전속력 전진속도 실험값이 됩니다.


그림입니다. 원본 그림의 이름: CLP00001b580024.bmp 원본 그림의 크기: 가로 393pixel, 세로 172pixel


#include <Servo.h>

Servo servoLeft;

Servo servoRight;

void setup()

{

tone(4, 3000, 1000);

delay(1000); 

servoLeft.attach(13); 

servoRight.attach(12); 


// Full speed forward

servoLeft.writeMicroseconds(1700);  

servoRight.writeMicroseconds(1300);  

delay(1000); 

servoLeft.detach(); 

servoRight.detach();

void loop()

}


이제 여러분이 찾은 로봇카 전진속도를 사용하여 원하는 거리에서 정확히 로봇카를 정지하도록 할 수 있습니다. 여러분이 원하는 목표거리에서 로봇카가 멈추도록 하려면 어떻게 하면될까요? 앞에서 소개했던 물리학 공식을 사용하여 원하는 목표거리에 도달하기 위해서는 목표거리(로봇카 진행거리)를 로봇카 속도 값으로 나누면 서보 동작시간을 쉽게 계산할 수 있습니다. 이렇게 계산된 서보동작시간을 스케치의 delay() 함수 값에 대입하기만 하면 원하는 동작을 완료할 수 있습니다.

만약 이렇게 계산된 시간이 2.22 second 라는 값으로 얻었다면, 다음과 같은 스케치로 사용할 수 있습니다. 스케치 delay() 함수는 밀리초 (또는 milli second 단위)를 사용하므로 2.22초는 2220 으로 환산되어 사용됩니다.


     servoLeft.writeMicroseconds(1700);

     servoRight.writeMicroseconds(1300);

     delay(2220);


목표거리를 또 다르게 변경하여 시도해봅시다. 원하는 지점에 정확히 여러분의 로봇카가 정확히 도착하는가요?


9) 로봇카 가속/감속 주행하기


지금까지의 로봇카 주행은 어떤 정해진 속도를 순간적으로 구현하는 것이었습니다. 이런 순간적인 서보 제어방식은 서보 동작을 위해 순간적으로 많은 전류를 흐르게 하기 때문에 보드의 수명, 서보의 수명 그리고 순간적인 로봇카 흔들림과 현상을 수반하게 됩니다. 물론 배터리의 소모율도 더 증가합니다.


이런 문제를 개선하기 위하여 로봇카가 출발할 때와 정지할 때 순간적으로 정지상태에서 최대속도로 동작하거나, 그 반대의 경우를 점진적으로 변하게 할 것입니다. 서보의 점진적 동작을 구현하기 위해 for 반복문을 활용할 수 있습니다.


아래 예제는 정지상태에서 최대속도 상태까지 어떻게 가속하는지에 대한 것이다. for 반복문에 정수 변수 speed 를 사용하여 0.02 초 (delay() 함수값 20 에 해당함)마다 writeMicroseconds 값을 2 씩 증가시키는 방식입니다. 함수값을 2씩 증가시켜 50회 반복하는 반복문이고, 이때 소요되는 총 시간은 1초입니다. 실습 당사자가 느끼기에 1초는 매우 짧은 시간이지만, 로봇 공학 측면에서는 매우 긴 시간에 해당합니다.


    for (int speed = 0; speed <= 100; speed += 2)

    {

        servoLeft.writeMicroseconds(1500+speed);

        servoRight.writeMicroseconds(1500-speed);

        delay(20);

    }


이제 로봇카의 출발 동작이 훨씬 부드럽게 제어된다는 느낌을 받을 것입니다. 아래 스키치를 사용하여 로봇의 출발과 정지동작이 한결 부드러워졌는지 살펴봅시다.


#include <Servo.h>

Servo servoLeft;

Servo servoRight;

void setup()

{

tone(4, 3000, 1000);

delay(1000); 

servoLeft.attach(13); 

servoRight.attach(12); 

for(int speed=0;   speed<=100; speed+=2)

{

  servoLeft.writeMicroseconds(1500+speed);

  servoRight.writeMicroseconds(1500-speed);

  delay(20);

}

delay(1500); 

for(int speed=100;speed>=0;speed-=2)

{

  servoLeft.writeMicroseconds(1500+speed);

  servoRight.writeMicroseconds(1500-speed);

  delay(20);

}

servoLeft.detach(); 

servoRight.detach();

}

void loop()

}


여러분은 이제 로봇카가 좌회전/우회전할 때에도 급격한 속도로 동작하는 것이 아니라 점진적 속도변화로 로봇카의 동작을 만들 수 있습니다. 로봇카의 회전동작에 대하여 가속 개념을 적용하여 봅시다.


10) 함수를 사용하여 로봇카 주행하기


로봇카의 주행/정지/회전동작을 간단하게 표현하거나 조금 더 복잡하게 표현할 수 있다는 것을 살펴보았습니다. 프로그래밍 언어에서 함수개념은 로봇카 동작에 있어서 복잡한 스케치 구성을 하고 있지만, 개념적으로는 주행동작 또는 정지동작 회전동작과 같이 하나의 묶음 형태 스케치들이 존재한다는 것을 알아차릴 수 있습니다.


여기서는 이러한 코드의 묶음단위를 함수개념을 사용하여 로봇카 동작을 더욱 쉽고 간편하게 다루도록 합니다. 어떤 정의된 로봇카 동작을 함수로 정의하여 추가하고, 필요할 때마다 정의된 함수를 호출하여 로봇카 실습에 사용할 것입니다. 아래 소개하는 함수 예제는 가장 간단한 형태중 하나입니다.


그림입니다. 원본 그림의 이름: CLP00001b580025.bmp 원본 그림의 크기: 가로 404pixel, 세로 293pixel


예제의 setup() 함수내에서 example() 함수가 포함되어 실행되는데, 이때 example() 함수의 괄호안이 비어 있는 것은 파라미터가 필요없다는 의미입니다. example() 함수가 실행될 순서가 되면 아래 example() 함수에서 정의한 중괄호 { } 내부의 문장들을 실행하고 다시 다음 setup() 함수내 다음 문장들을 실행합니다. 위의 예제 출력은 어떻게 표시되는지 직접 출력해보세요!


파라미터를 갖는 함수호출 사용법

이제 조금 더 복잡한 경우의 함수사용법에 대하여 살펴봅시다. 파라미터란 함수를 호출할 때 별도의 조건을 달아서 함수를 호출하고, 함수를 실행한 결과 값도 종종 돌려받는 경우에 사용합니다. 함수의 파라미터는 한 개 또는 그 이상의 복수 개를 사용할 수 있습니다. 아래 예제는 앞장에서 살펴본 부저의 동작에 필요한 스케치를 사용하여 함수로 표현한 것입니다. 부저 동작을 위해서는 3가지 종류의 요소가 필요한데, 그 한가지가 소리음의 동작주파수이고, 다른 한가지는 소리음의 지속시간입니다. 아래 함수에서는 주파수 값만을 파라미터로 하여 부저를 필요한 소리음의 주파수로 사용하기 편리하도록 작성한 예제입니다.


그림입니다. 원본 그림의 이름: CLP00001b580026.bmp 원본 그림의 크기: 가로 420pixel, 세로 378pixel


예제의 pitch() 함수가 부저를 동작시키는 함수이고, pitch() 함수 괄호안의 값을 3500 또는 2000 으로 각각 다르게 사용하면 부저에서 발생하는 소리음의 높이가 각각 다르게 동작합니다. 물론 여기서도 pitch() 함수에서 반환값은 사용하지 않는 형태입니다.


지금부터 로봇카의 다양한 동작에 필요한 스케치들을 어떻게 함수를 사용하여 쉽고 편리하게 사용할 수 있는지에 대해 살펴보겠습니다. 로봇카 함수에 사용할 정의된 동작의 범위는 전진/후진/왼쪽회전/오른쪽회전입니다. 여러분의 또 다른 상상에 의해 더 다양한 로봇카 동작을 정의하고 함수로 표현하여 쉽고 편리하게 호출하여 사용할 수 있습니다.


#include <Servo.h>

Servo servoLeft;

Servo servoRight;

void setup()

{

  tone(4, 3000, 1000);

  delay(1000);

  servoLeft.attach(13);

  servoRight.attach(12);


  forward(2000);

  turnLeft(600);

  turnRight(600);

  backward(2000);


  disableServos();

void loop()

}

void forward(int time)

{

  servoLeft.writeMicroseconds(1700);

  servoRight.writeMicroseconds(1300);

  delay(time);

}

void turnLeft(int time)

{

  servoLeft.writeMicroseconds(1300);

  servoRight.writeMicroseconds(1300);

  delay(time);

}

void turnRight(int time)

{

  servoLeft.writeMicroseconds(1700);

  servoRight.writeMicroseconds(1700);

  delay(time);

}

void backward(int time)

{

  servoLeft.writeMicroseconds(1300);

  servoRight.writeMicroseconds(1700);

  delay(time);

}

void disableServos()

  servoLeft.detach();

  servoRight.detach();

}


로봇카의 동작을 함수를 사용하여 조금 더 편리하게 설계하고 동작시킬 수 있다는 것을 이해할 것입니다. 이제 조금 더 사용자 편의성에 기초한 함수형태로 함수를 정의하여 로봇카의 동작을 더 정교하고 실질적으로 제어해 봅시다!


앞 부분에서 소개한 로봇카 함수는 한가지 동작속도만으로 정의했지만, 지금 부터 소개하는 로봇카 함수는 더 다양하고 유연한 로봇카 동작을 유도할 수 있는 함수가 될 것입니다. 아래는 3가지 종류의 파라미터를 가지고 로봇카 동작을 제어할 수 있는 함수의 예제입니다.


   void maneuver(int speedLeft, int speedRight, int msTime)

   {

      servoLeft.writeMicroseconds(1500+speedLeft);

      servoRight.writeMicroseconds(1500-speedRight);

      if(msTime==-1)

      {

         servoLeft.detach();

         servoRight.detach();

      }

      delay(msTime);

   }


함수의 파라미터를 각각 다르게 적용하면 로봇카의 동작을 다양하게 만들 수 있습니다. 아래 예제 파라미터 값 이외에 더 다양한 값들을 사용하여 로봇카를 제어할 수 있습니다.


    maneuver(200, 200, 2000);    // Forward 2 seconds

    maneuver(-200, 200, 600);    // Left 0.6 seconds

    maneuver(200, -200, 600);    // Right 0.6 seconds

    maneuver(-200, -200, 2000);  // Backward 2 seconds

    maneuver(0, 0, -1);           // Disable servos


여러분은 이제 maneuver() 함수의 파라미터값만으로 로봇카의 다양한 동작을 간단하고 편리하게 제어할 수 있습니다. 이외에도 배열의 개념을 사용하여 조금 더 스케치 내용을 편리하고 간단하게 표현할 수 있습니다. 배열에 대한 추가 내용이 핗요한 분은 프라이봇 자료실의 온라인 자료를 참고하거나, "야금야금 길들이기 아두이노로봇" 교재를 참고할 수 있습니다.



이전 페이지로     다음 페이지로