5. 햄스터 로봇 명령어 연습

지금부터 기초 명령어 연습을 통하여 차근차근 햄스터 로봇 프로그래밍을 해 보자. 여기서 배우는 내용 외에 더 많은 명령어를 공부하고 싶다면 햄스터 스쿨 홈페이지(http://hamster.school/ko/)에서 파이선 레퍼런스(http://hamster.school/ko/reference/python/)를 참조하자.

1햄스터 로봇 전진, 후진시키기

햄스터 로봇의 DC모터에는 2개의 바퀴가 연결되어 있다. 만져보면 이 바퀴에는 고무링이 끼워져 있어서 미끄러지지 않고 움직일 수 있게 해준다. 모터제어를 통해 자유자재로 이동하는 햄스터 로봇을 만들어 보자.


가. 햄스터 로봇을 전진시키기 위해 아래의 코드를 입력해 보자.

이미지. 햄스터 로봇이 전진하는 동영상의 스크린샷.

from roboid import * # 햄스터 로봇과 같은 로보이드 패키지를 사용하기 위해 반드시 필요한 코드이다.


h=Hamster() # 'h'라고 선언한 변수에 Hamster() 함수를 불러와 넣게 된다. 이후부터는 'h'변수를 사용하여 햄스터 로봇에게 명령을 전달할 수 있다.


h.wheels(30, 30) # 괄호 안의 숫자 중 첫 번째는 햄스터 로봇 왼쪽 바퀴의 속도를, 두 번째는 오른쪽 바퀴의 속도를 의미한다. 만약 다음과 같이 하나의 값만 입력하게 되면 양쪽 모두 같은 속도로 움직이게 된다. h.wheels(30)


나. 아래와 같이 wait() 대기 명령을 사용하여 지정한 시간 이후에 더 빠른 속도로 움직이는 햄스터 로봇을 만들어 볼 수 있다.

이미지. 햄스터 로봇이 전진하다가 지정한 시간 이후에 더 빠른 속도로 움직이는 동영상의 스크린샷.

사용하는 시간의 단위는 밀리세컨드(Millisecond)이므로 1000을 입력한다면 1초를 대기하게 된다. 코드를 실행해보면 1초 후에 속도는 빨라져 모터의 소리는 더 커질 것이다.


from roboid import *


h=Hamster()


h.wheels(30, 30)

wait(1000)

h.wheels(60, 60)


다. 햄스터 로봇의 바퀴 속도는 최대 속도에 대한 % 값의 개념으로 이해하면 된다.


-100~100까지의 숫자를 입력할 수 있으며 양수는 전진, 음수는 후진을 한다. 당연히 높은 숫자를 입력하면 햄스터 로봇이 빠르게 움직이며 모터의 소리도 더 커질 것이다. 바퀴의 속도를 0에서부터 100까지 증가시켜 보면서 모터 소리의 변화를 확인해 보자.


더 알아보기 - 햄스터 로봇의 속도는 빠를수록 좋을까?

햄스터 로봇의 바퀴 속도를 100으로 하면 가장 빠르게 움직일 수 있지만, 그만큼 배터리의 소모가 크기 때문에 사용시간은 줄어들게 된다. 그리고 연속적으로 사용하면 모터에 무리가 갈 수도 있으므로 50 이하의 속도 값을 입력하는 것이 바람직하다.

2햄스터 로봇 회전시키기

바퀴가 2개인 로봇의 회전은 보통 제자리 돌기(포인트 턴), 한쪽 바퀴를 축으로 돌기(스윙 턴), 큰 원을 그리며 돌기(커브 턴)의 3가지 방식으로 구분한다. 다음의 예제를 통해서 각 회전 방식에 따라 어떻게 회전이 달라지는지 확인하여 보자.


가. 먼저 제자리에서 회전하려면 어떻게 해야 할까? 왼쪽과 오른쪽 바퀴의 방향이 달라야 한다. 다음의 코드를 입력해 보자

이미지. 햄스터 로봇으로 제자리 회전하는 동영상의 스크린샷.
이미지. 햄스터 로봇 두대중 한대에는 양쪽 바퀴의 속도와 방향을 마이너스30과 30으로 화살표 표시, 나머지 한대는 회전 방향을 햄스터 로봇 중심을 기준으로 화살표 표시한 사진.

from roboid import *


h=Hamster()


h.wheels(-30, 30) # 왼쪽 바퀴의 속도를 -30, 오른쪽 바퀴의 속도를 30으로 입력하였다. 햄스터 로봇 양쪽 바퀴를 연결하는 가상의 선, 가운데 부분을 기준으로 하여 왼쪽 방향으로 3초간 제자리 화전을 하게 된다.

wait(3000)


나. 한쪽 바퀴를 축으로 회전하려면 어떻게 해야 할까? 한쪽 바퀴가 회전의 축이 되려면 해당 바퀴는 움직임이 없어야 할 것이다. 다음의 코드를 입력하여 보자.

이미지. 햄스터 로봇으로 한쪽 바퀴를 축으로 회전하는 동영상의 스크린샷.
이미지. 햄스터 로봇 두대중 한대에는 양쪽 바퀴의 속도와 방향을 0과 30으로 화살표 표시, 나머지 한대는 회전 방향을 햄스터 로봇 왼쪽 바퀴를 기준으로 화살표 표시한 사진.

from roboid import *


h=Hamster()


h.wheels(0, 30) # 왼쪽 바퀴의 속도를 0, 오른쪽 바퀴의 속도를 30으로 입력하였다. 왼쪽 바퀴는 정지한 채 왼쪽 방향으로 3초간 회전을 하게 된다.

wait(3000)


h.left_wheel(30)

h.right_wheel(30) # 왼쪽 혹은 오른쪽 특정 바퀴에만 속도 값을 입력하는 명령을 할 수도 있다.


다. 마지막으로 일반적인 자동차의 회전을 나타내는 큰 원을 그리며 돌기이다. 다음의 코드를 입력하여 보자.

이미지. 햄스터 로봇으로 큰 원을 그리며 도는 동영상의 스크린샷.
이미지. 햄스터 로봇 두대중 한대에는 양쪽 바퀴의 속도와 방향을 20과 40으로 화살표 표시, 나머지 한대는 회전 방향을 햄스터 로봇 왼쪽 밖을 기준으로 화살표 표시한 사진.

from roboid import *


h=Hamster()


h.wheels(20, 40) # 왼쪽 바퀴의 속도를 20, 오른쪽 바퀴의 속도를 40으로 입력하였다. 왼쪽과 오른쪽 바퀴의 속도 차가 발생한다면 속도가 느린 쪽으로 5초간 원을 그리며 회전하게 된다. 이때, 회전의 중심은 햄스터 로봇의 밖에 있으므로 3가지 회전 방식 중에서 회전반경이 가장 크다고 하겠다.

wait(5000)

라. 햄스터 로봇이 더 큰 원을 그리며 회전하게 하려면 왼쪽과 오른쪽 바퀴의 속도를 어떻게 변경해 줘야 할까? 바퀴의 속도 차를 변경하면서 회전하는 원의 크기가 어떻게 달라지는지 확인해 보자.


?
문제를 해결해 볼까요

햄스터 로봇이 정사각형 모양을 그리며 움직이도록 프로그래밍 해 보자.

이미지. 햄스터 로봇으로 정사각형 모양을 그리는 순서를 8단계로 설명한 사진.
이미지. 햄스터 로봇으로 정사각형 모양을 그리는 동영상의 스크린샷.

[생각 정리하기]

햄스터 로봇이 어떻게 움직여야 할까? 앞서 연습한 직진, 회전의 두 가지 명령을 사용하여 프로그래밍의 순서를 생각해 보자. 단, 마지막에 도착한 햄스터 로봇은 처음에 출발했을 때와 같은 방향을 바라보아야 한다.


[생각을 프로그래밍으로 구현하기]


from roboid import *


h=Hamster()


h.wheels(30) # 1초 동안 앞으로 이동한다.

wait(1000)


h.wheels(-30, 30)

wait(950) # 왼쪽으로 90° 회전한다. 햄스터 로봇마다 차이는 있지만 30의 속도로 했을때 대략 0.95초 동안 90°를 회전할 수 있다.


h.wheels(30)

wait(1000)


h.wheels(-30, 30)

wait(950)


h.wheels(30)

wait(1000)


h.wheels(-30, 30)

wait(950)


wait(950)


h.wheels(30)

wait(1000)


h.wheels(-30, 30)

wait(950)


h.stop()

- 위의 코드는 같은 구문이 계속 반복되는 구조이므로 반복문을 사용하면 더 효율적일 것이다.


from roboid import *


h=Hamster()


for i in range(4): # 4번을 반복한다.

    h.wheels(30)

    wait(1000)


    h.wheels(-30, 30)

    wait(950)


h.stop()

- 정사각형 그리기에 성공하였다면 반복문을 사용하여 정삼각형, 정오각형 그리기에도 도전해 보자. 과연 회전하는 각도를 몇 도로 설정해야 할까?


더 알아보기 - 햄스터 로봇이 정확히 정사각형을 그리며 이동할까?

입력한 코드로는 정사각형을 그리며 이동하는 것이 맞지만 실제로는 그렇게 움직이기 어렵다. 모터의 종류, 바닥의 재질, 배터리 충전상태 등의 상황이 영향을 미치기 때문이다. 이러한 움직임에 센서가 활용된다면 이를 보완할 수 있을 것이다. 다양한 센서의 활용에 대해서는 다음에 다루게 된다. 더 똑똑해진 햄스터 로봇을 기대해 보자.

3근접센서 사용하기

햄스터 로봇의 앞쪽을 만져보면 왼쪽과 오른쪽에 각각 움푹 패어 있는 부분이 있는데 이것이 적외선으로 거리를 측정할 수 있는 근접센서이다. 적외선이 물체에 반사되어 돌아오는 빛의 양을 측정하여 거리로 환산하게 되는데 어두운색은 흡수하고 밝은 색은 반사하는 적외선의 특성상 물체의 색상에 따라 그 값이 달라질 수 있다. 대략 1cm 이상, 30cm 이하의 거리에 있는 물체를 감지할 수 있다.


이미지. 햄스터 로봇 근접센서의 부품을 표시한 사진.

가. 근접센서의 값을 확인할 수 있는 명령어를 사용하여 햄스터 로봇이 앞으로 이동하다 장애물을 감지하면 정지하도록 해보겠다. 다음의 코드를 입력해 보자.

이미지. 햄스터 로봇이 앞으로 이동하다 장애물을 감지하면 정지하는 동영상의 스크린샷.

from roboid import *


h=Hamster()


while h.left_proximity() < 30 and h.right_proximity() < 30:

    h.wheels(30) # 측정된 좌·우 근접센서의 값이 모두 30보다 작으면 앞으로 이동한다.

    wait(20) # 20msec 동안 기다리게 하여 while 문의 과도한 반복수행을 줄여준다.

h.stop() # 정지한다.


나. 위의 입력된 코드는 순차적으로 처리하기 때문에 코드를 실행하면 측정된 근접센서의 값이 조건의 범위에 해당되는 동안 앞으로 이동하다 벗어나게 되면 정지하고 끝이 난다. 계속해서 조건의 해당 여부를 판단하고 움직이도록 코드를 변경해 보자.

이미지. 햄스터 로봇 근접센서의 값이 계쏙해서 조건의 해당 여부를 판단하고 움직이는 동영상의 스크린샷.

from roboid import *


h=Hamster()


while true:

    if h.left_proximity() < 30 and h.right_proximity() < 30:

        h.wheels(30)

    else:

        h.stop()

h.wait(20) # 이동과 정지의 명령이 모두 반복문 안에 들어가 있으므로 조건에 따라 계속해서 움직임을 수행하게 된다.


다. 위의 코드를 응용하여 햄스터 로봇 전면에 손을 갖다 대면 도망가고 손을 치우면 다가오는 하는 밀당 햄스터 로봇을 만들어 보자.

이미지. 햄스터 로봇 전면에 손을 갖대 대면 도망하고 손을 치우면 다가오는 동영상의 스크린샷.

from roboid import *


h=Hamster()


while true:

    if h.left_proximity() < 30 and h.right_proximity() < 30:

        h.wheels(30)

    else:

        h.wheels(-30)

h.wait(20) # 양쪽 근접센서의 값이 모두 30 보면 작으면(손이 없으면) 앞으로 이동하고, 그렇지 않으면 뒤로 이동한다.


라. 앞서 만들어 본 밀당 햄스터 로봇은 결과적으로 근접센서의 값을 30으로 계속 유지하며 앞·뒤로 움직이게 된다. 숫자의 값을 변경해 가며 움직임의 변화를 관찰해 보자.


?
문제를 해결해 볼까요

햄스터 로봇과 손의 거리에 따라 다른 소리를 내도록 프로그래밍 하고 손을 움직여 재미있게 연주해보자.

이미지. 햄스터 로봇과 손의 거리에 따라 다른 소리를 내는 동영상의 스크린샷.

[생각 정리하기]

햄스터 로봇에 손을 갖다 대보면 근접센서의 값이 대략 0~50사이에서 측정된다. 소리를 낼 때 사용하는 note() 명령어의 숫자 입력 범위는 1~88이며 이는 피아노의 88개의 건반을 의미한다. 근접센서의 값을 note() 명령어 괄호에 어떻게 대입하면 좋을까?


[생각을 프로그래밍으로 구현하기]


from roboid import *


h=Hamster()


while true:

    sensor=h.left_proximity() # 'sensor' 변수를 선언하고 왼쪽 근접센서의 값을 저장한다.

    h.note(sensor) # 'sensor' 변수의 값을 note() 명령어에 대입해 준다.

    wait(20)

- 재미있는 악기가 되었다. 하지만 실행해 보면 손이 없어도 가끔씩 소리가 나며, 측정되는 근접센서 값의 범위는 0~50이므로 그 이상의 소리는 내지는 못한다. 이러한 문제점을 어떻게 하면 개선할 수 있을까?


from roboid import *


h=Hamster()


while true:

    sensor=h.left_proximity()

    sound=0

    if sensor < 5:

        sensor=0 # 손이 없어도 5 미만의 값이 측정되어 소리가 나는 오류를 해결한다.

    sound=sensor * 1.5 # 50 이상의 소리를 낼 수 있도록 해준다.

    h.note(sound)

    wait(20)

4바닥 센서 사용하기

햄스터 로봇의 바닥 부분을 만져보면 동그랗게 살짝 튀어나와 있어 볼 캐스터 역할을 하는 부분이 있고 그 좌·우에 바닥 센서가 하나씩 있다. 근접센서와 마찬가지로 적외선이 바닥에 반사되어 돌아오는 빛의 양을 측정하게 되는데 바닥의 밝고 어두운 정도에 따라 대략 0~100사이의 값을 환산하여 보내준다.


이미지. 햄스터 로봇 바닥 센서의 부품을 표시한 사진.

가. 바닥의 밝고 어두운 정도에 따라 왼쪽 바닥 센서의 값이 어떻게 달라지는지 확인해 보도록 하겠다. 다음의 코드를 입력해 보자.

이미지. 햄스터 로봇의 왼쪽 바닥 센서 값을 화면에 출력하는 동영상의 스크린샷.

from roboid import *


h=Hamster()


while true:

    print(h.left_floor()) # 왼쪽 바닥 센서의 값을 화면에 출력한다.

    wait(20)


나. 먼저, A4용지 한 장과 검은색 절연테이프를 준비한 다음 검정 테이프를 A4용지 가운데 부분에 적당한 길이로 붙여준다. 위의 코드를 실행한 후 A4용지의 흰색 바탕과 검정 테이프 위에 햄스터 로봇의 왼쪽 바닥 센서를 각각 대어 보고 측정값이 어떻게 달라지는지 확인해 보자.


다. 주변의 밝기에 따라 차이가 있을 수 있지만 흰색 바탕에서는 100에 가까운 값이, 검정 테이프에서는 0에 가까운 값이 나오는 것을 확인할 수 있을 것이다.


라. 햄스터 로봇이 직진하다가 검정 테이프에 닿으면 정지하도록 해 보겠다.

이미지. 햄스터 로봇이 직진하다가 검정 테이프에 닿으면 정지하는 동영상의 스크린샷.

from roboid import *


h=Hamster()


while h.left_floor() > 50:

    h.wheels(30)

    wait(20) # 왼쪽 바닥 센서가 검정 테이프에 닿기 전까지(바닥 센서의 값이 50보다 작거나 같을 경우) 직진한다.


h.stop()


마. 이번에는 비슷한 상황인데 햄스터 로봇이 직진하다 검정 테이프에 닿아 있는 동안 버저 소리를 내도록 해보겠다.

이미지. 햄스터 로봇이 직진하다가 검정 테이프에 닿아 있는 동안 버저 소리를 내는 동영상의 스크린샷.

from roboid import *


h=Hamster()


h.wheels(30)


while True:

    if h.left_floor() < 50:

        h.buzzer(1000)

    else:

        h.buzzer(0) # 왼쪽 바닥 센서의 값이 50보다 작으면(검정 테이프에 닿으면) 버저 소리를 내고, 그렇지 않으면 소리를 끈다.

    wait(20)

더 알아보기 - 햄스터 로봇의 소리 내는 방법에 대해 알아볼까?

앞서 실습한 note() 명령어는 피아노 건반음과 같이 정확한 음정을 소리 낼 수 있는 반면, buzzer() 명령어는 0~167772.15Hz까지의 주파수를 직접 입력하여 쉽게 연속적인 소리를 낼 수 있다. 그리고 괄호 안의 숫자는 소수점 둘째 자리까지 입력할 수 있으며, 0을 입력하면 소리는 꺼지게 된다.

소리 내기에 관한 더 자세한 활동은 햄스터 스쿨(http://hamster.school/ko/)의 파이선 레퍼런스(http://hamster.school/ko/reference/python/)를 참조하자.

?
문제를 해결해 볼까요

A4용지에 두 줄의 검정 테이프 선을 붙이고 햄스터 로봇을 직진하게 한다. 햄스터 로봇이 지나간 검정 선의 개수를 세고 화면에 표시하도록 해 보자.

이미지. 두 줄의 검정 테이프 선을 붙인 A4용지에 햄스터 로봇이 직진하는 모습의 사진.
이미지. 햄스터 로봇이 지나간 검정 선의 개수를 세고 화면에 출력하는 동영상의 스크린샷.

[생각 정리하기]

검은색 선을 감지하는 것은 앞서 해본 방법대로 하면 되지만 햄스터 로봇이 지나간 검은색 선의 개수를 세고 기억하려면 저장 공간인 변수가 필요할 것이다. 선을 지날 때마다 변수의 값을 1씩 증가시키도록 해 보자.


[생각을 프로그래밍으로 구현하기]


from roboid import *


h=Hamster()


h.wheels(30)

count=0 # 'count' 변수를 선언하고 0으로 초기화 해준다.


while True:

    if h.left_floor() < 50:

        count+= 1

        print(count) # 왼쪽 바닥 센서의 값이 50보다 작으면 'count' 변수를 1씩 증가시키고 그 값을 화면에 나타낸다.

    wait(20)

- 위의 코드를 실행해보면 햄스터 로봇이 검정 선 하나를 지날 때 변수의 값이 20~30까지 한꺼번에 증가하는 것을 확인할 수 있다. 왜 그럴까? 그 이유는 검정 선을 지나는 동안에도 반복문이 계속 실행되기 때문이다. 이 문제를 어떻게 해결할 수 있을까?


from roboid import *


h=Hamster()


h.wheels(30)

count=0


while True:

    if h.left_floor() < 50:

        count+=1

        print(count)

        wait(1000) # 왼쪽 바닥 센서가 검은색 선에 닿으면 변숫값을 증가시킨 후 1초간 기다리게 하여 검은색 선을 벗어날 때까지 반복문이 실행되는 것을 방지한다.

    wait(20)


- 조건에 충족이 되면 변숫값을 증가시키고 기다리게 하여 간단히 문제를 해결해 보았다. 하지만 만약 검정 테이프가 두꺼워 1초가 지난 후에도 검은색 선에 닿아있다면 변수의 값이 계속 증가하는 처음의 문제는 지속될 것이다. 어떻게 하면 검정 테이프의 두께와 상관없이 선의 개수를 정확히 셀 수 있는지에 대해서도 한 번 생각해 보자.


5밝기 센서 사용하기

햄스터 로봇의 앞쪽을 만져보면 가운데 부분에 마치 입처럼 움푹 패어 있는 부분이 있다. 이것은 빛의 밝기를 감지하는 밝기 센서로 0부터 65,535Lux의 값을 측정할 수 있으며 밝을수록 값은 커진다.


이미지. 햄스터 로봇 밝기 센서의 부품을 표시한 사진.

가. 어두우면 소리를 내는 햄스터 로봇을 만들어 보도록 하겠다. 우선 현재 빛의 밝기를 측정하기 위해 다음의 코드를 입력해 보자.

이미지. 햄스터 로봇의 밝기 센서 값을 화면에 출력하는 동영상의 스크린샷.

from roboid import *


h=Hamster()


while True:

    print(h.light()) # light() 함수를 사용하여 현재 밝기 센서의 값을 측정한다.

    wait(20)

나. 현재의 밝기보다 어두워지면 밝기 센서의 값은 더 낮아지므로 적당한 값을 입력하여 버저 소리를 내도록 하자.

이미지. 햄스터 로봇의 밝기 센서 값으로 버저 소리를 내는 동영상의 스크린샷.

from roboid import *


h=Hamster()


while True:

    if h.light() < 10:

        h.buzzer(1000)

    else:

        h.buzzer(0) # 밝기 센서의 값이 10보다 낮아지면 소리를 내고 그렇지 않으면 소리를 멈춘다.

    wait(20)

?
문제를 해결해 볼까요

빛의 밝기에 따라 다른 소리를 내도록 프로그래밍 하고 재미있게 연주해 보자.

이미지. 햄스터 로봇으로 빛의 밝기에 따라 다른 소리를 내는 동영상의 스크린샷.

[생각 정리하기]

햄스터 로봇이 어두울수록 높은 음을 내도록 하려면 어떻게 해야 할까? 밝기 센서의 값의 범위는 대략 0~100이다. 그리고 사람이 보통 편하게 들을 수 있는 buzzer() 명령어의 숫자 입력 범위는 0~1000사이이므로 밝기 센서의 값에 따라 일정 비율로 소리의 높낮이가 달라질 수 있도록 해보자.


[생각을 프로그래밍으로 구현하기]


from roboid import *


h=Hamster()


while True:

    sensor=h.light()

    if h.light() < 5:

        h.buzzer(2000)

    elif sensor > 100:

        h.buzzer(0)

    else:

        h.buzzer(2100-sensor * 20) # 센서의 값에 따라 다른 버저음을 내도록 조건문을사용하여 코드를 입력한다.

    wait(20)