News Download Tutorial FAQ Reference Buy

C 언어 : 센서 두 개를 이용한 라인 트레이서

개요
지난 시간에는 햄스터 로봇의 바닥 센서 한 개를 이용하여 주행하는 방법에 대해 알아보았습니다. 이번에는 바닥 센서 두 개를 이용하여 주행하는 방법에 대해 알아보도록 하겠습니다.

실습 자료:   PPT PDF
기존의 방법
실습을 하기 위해 A4 용지를 준비하고, 햄스터 로봇이 이동할 직선을 검은색 테이프 또는 펜으로 그립니다. 미리 제작된 실습 자료를 내려 받아 프린터로 인쇄하여도 됩니다.

햄스터 로봇의 양쪽 바닥 센서를 사용하여 검은색 선의 중앙을 따라 주행하는 프로그램을 작성하시오.

기존의 방법부터 살펴 보도록 하겠습니다. 기본적으로는 앞으로 이동하면서 햄스터 로봇의 왼쪽 바닥 센서가 검은색 선 위에 있으면 중앙으로 가기 위해 왼쪽으로 움직이고, 오른쪽 바닥 센서가 검은색 선 위에 있으면 오른쪽으로 움직이면 됩니다.

원리는 간단한데 이를 실제로 구현하기 위해서는 두 가지가 필요합니다.

하나씩 문제를 풀어 봅시다.
우선 왼쪽 바닥 센서가 검은색 선 위에 있는지 알기 위해서는 왼쪽 바닥 센서의 값을 읽어야 합니다. 다음 그림과 같이 햄스터 로봇의 바닥면 좌우에는 바닥 센서(적외선 센서)가 있는데, 종이 위에 그려진 선이나 책상의 가장자리 등을 검출할 때 사용됩니다. 바닥 센서는 적외선을 방출하는 IR-LED와 적외선을 감지하는 광 트랜지스터 한 쌍으로 이루어져 있습니다. IR-LED가 방출하는 적외선이 바닥에 반사되어 들어오는 광량을 광 트랜지스터가 검출합니다. 바닥 센서가 하얀색 종이 위에 있으면 반사된 광량이 많아져서 측정되는 값이 증가하고, 검은색 선 위에 있으면 반사된 광량이 적어져서 측정되는 값이 감소하게 됩니다.

왼쪽 바닥 센서의 값을 읽기 위해서는 read 함수를 사용하면 됩니다. 프로그램을 구현하기 전에 우선 바닥 센서의 값을 관찰해 보도록 합시다. 파이썬의 경우에는 다음 코드와 같이 센서 값을 출력할 수 있습니다.

#include <stdio.h>
#include "hamster.h"

int main(int argc, char *argv[]) {

    hamster_create();

    while(1) {
        printf("%d\n", hamster_read(HAMSTER_LEFT_FLOOR));
    }

    hamster_dispose_all();
    return 0;
}

햄스터 로봇의 왼쪽 바닥 센서가 A4 용지의 하얀색 종이 위에 있을 때와 검은색 선 위에 있을 때 센서 값이 어떻게 다른지 관찰하여 기록해 봅시다.

하얀색 종이 위에 있을 때 검은색 선 위에 있을 때
왼쪽 바닥 센서의 값

측정된 센서 값으로부터 햄스터 로봇의 왼쪽 바닥 센서가 검은색 선 위에 있는지 판단하기 위해서는 크기를 비교하면 됩니다. 기준이 되는 숫자가 필요한데 앞에서 측정한 두 개의 센서 값의 중간 값을 사용해 봅시다. 즉, 하얀색 종이 위에 있을 때 센서 값이 100, 검은색 선 위에 있을 때 센서 값이 0이었다면 기준이 되는 숫자는 50으로 하면 됩니다. 왼쪽 바닥 센서가 검은색 선 위에 있는 경우를 다음과 같이 표현할 수 있습니다.

hamster_read(HAMSTER_LEFT_FLOOR) < 50

마찬가지로 오른쪽 바닥 센서가 검은색 선 위에 있는 경우를 다음과 같이 표현할 수 있습니다.

hamster_read(HAMSTER_RIGHT_FLOOR) < 50

이제 두 번째 문제를 풀어 봅시다. 햄스터 로봇을 왼쪽 또는 오른쪽으로 움직여야 합니다. 기본적으로는 앞으로 이동하고 있기 때문에 제자리에서 회전하는 방법을 사용해 봅시다. 왼쪽으로 회전하기 위해서는 왼쪽 바퀴를 뒤로 움직이고, 오른쪽 바퀴를 앞으로 움직이면 됩니다. 오른쪽으로 회전하기 위해서는 왼쪽 바퀴를 앞으로 움직이고, 오른쪽 바퀴를 뒤로 움직이면 됩니다.

hamster_write(HAMSTER_LEFT_WHEEL, -30);
hamster_write(HAMSTER_RIGHT_WHEEL, 30);

hamster_write(HAMSTER_LEFT_WHEEL, 30);
hamster_write(HAMSTER_RIGHT_WHEEL, -30);

둘 다 검은색 선 위에 없는 경우가 있기 때문에 왼쪽 바닥 센서가 검은색 선 위에 있는 경우와 오른쪽 바닥 센서가 검은색 선 위에 있는 경우를 모두 검사해 주어야 합니다. if else if 구문을 사용하도록 합시다. 앞으로 이동하면서 왼쪽 바닥 센서가 검은색 선 위에 있으면, 즉 센서 값이 50보다 작으면 왼쪽으로 회전하도록 하고, 오른쪽 바닥 센서가 검은색 선 위에 있으면, 즉 센서 값이 50보다 작으면 오른쪽으로 회전하도록 프로그램을 작성해 봅시다.

hamster_write(HAMSTER_LEFT_WHEEL, 30);
hamster_write(HAMSTER_RIGHT_WHEEL, 30);
if(hamster_read(HAMSTER_LEFT_FLOOR) < 50) {
    hamster_write(HAMSTER_LEFT_WHEEL, -30);
    hamster_write(HAMSTER_RIGHT_WHEEL, 30);
} else if(hamster_read(HAMSTER_RIGHT_FLOOR) < 50) {
    hamster_write(HAMSTER_LEFT_WHEEL, 30);
    hamster_write(HAMSTER_RIGHT_WHEEL, -30);
}

이제 이 코드를 계속 반복하면 프로그램이 완성됩니다.

#include "hamster.h"

int main(int argc, char *argv[]) {

    hamster_create();

    while(1) {
        hamster_write(HAMSTER_LEFT_WHEEL, 30);
        hamster_write(HAMSTER_RIGHT_WHEEL, 30);
        if(hamster_read(HAMSTER_LEFT_FLOOR) < 50) {
            hamster_write(HAMSTER_LEFT_WHEEL, -30);
            hamster_write(HAMSTER_RIGHT_WHEEL, 30);
        } else if(hamster_read(HAMSTER_RIGHT_FLOOR) < 50) {
            hamster_write(HAMSTER_LEFT_WHEEL, 30);
            hamster_write(HAMSTER_RIGHT_WHEEL, -30);
        }
    }

    hamster_dispose_all();
    return 0;
}

다음 그림과 같이 햄스터 로봇의 중앙이 검은색 선 위에 있도록 올려 놓고 프로그램을 실행해 봅시다.

추가 활동:
  • 크기를 비교하는 기준이 되는 숫자를 변경하면 햄스터 로봇의 동작이 어떻게 달라지는지 관찰하고 그 이유를 토의해 봅시다.

기존의 방법으로 하였을 때 햄스터 로봇이 검은색 선을 따라 비교적 잘 이동하는 것처럼 보입니다. 하지만 다음 그림과 같이 중앙에서 벗어나 출발하는 경우와 약간 비스듬하게 출발하는 경우, 곡선을 주행하는 경우에는 햄스터 로봇의 움직임이 부드럽지 않습니다. 특히 90도로 꺾어진 길을 주행할 때는 90도 꺾어진 부분에서 검은색 선을 잘 따라가지 못하고 선을 벗어나게 됩니다. 곡선을 따라 주행하거나 90도로 꺾어진 길도 잘 달려갈 수 있어야 물건을 이곳저곳으로 운반할 수 있는 멋진 햄스터 로봇이 될 수 있습니다.



두 번째 방법
지난 시간에 바닥 센서 한 개를 사용하여 햄스터 로봇이 부드럽게 주행하도록 한 것을 기억하나요? 바닥 센서 두 개를 사용하는 기존의 방법에서 햄스터 로봇의 움직임이 부드럽지 않은 이유는 마찬가지로 왼쪽 바닥 센서 또는 오른쪽 바닥 센서의 위치에 관계 없이 일정한 속도로 움직이기 때문입니다. 중앙의 검은색 선을 약간 벗어났을 때는 조금만 움직여도 되지 않을까요?

검은색 선을 따라 주행하는 원리는 같습니다. 다른 점은 왼쪽 바닥 센서와 오른쪽 바닥 센서의 값에 따라 왼쪽 바퀴와 오른쪽 바퀴의 속도를 변경한다는 것입니다. 규칙을 한번 생각해 봅시다.

이를 왼쪽 바퀴와 오른쪽 바퀴 관점에서 정리하면 다음과 같습니다.

즉, 왼쪽 바퀴의 속도는 왼쪽 바닥 센서의 값과 정비례 관계를 가지고, 오른쪽 바퀴의 속도는 오른쪽 바닥 센서의 값과 정비례 관계를 가집니다. 바닥 센서의 값은 0 ~ 100의 범위이고 바퀴의 속도는 -100 ~ 100의 범위인데, 앞으로 이동해야 하기 때문에 바퀴의 속도도 0 ~ 100의 범위가 되도록 해야 합니다. 이를 수식으로 표현하면 다음과 같습니다.

햄스터 로봇의 속도가 너무 빠르면 곡선을 주행하거나 90도로 꺾어진 길에서 급하게 회전하기가 어려워지기 때문에 최대 속도가 50이 되도록 0.5를 곱하여 다음과 같이 프로그램을 작성해 봅시다.

#include "hamster.h"

int main(int argc, char *argv[]) {
    int left, right;

    hamster_create();

    while(1) {
        left = hamster_read(HAMSTER_LEFT_FLOOR);
        right = hamster_read(HAMSTER_RIGHT_FLOOR);
        hamster_write(HAMSTER_LEFT_WHEEL, left * 0.5);
        hamster_write(HAMSTER_RIGHT_WHEEL, right * 0.5);
    }

    hamster_dispose_all();
    return 0;
}

어떤가요? 우선 직선을 주행해 보도록 합시다. 중앙에서 벗어나 출발하는 경우와 약간 비스듬하게 출발하는 경우, 곡선을 주행하는 경우 모두 실험해 보고 햄스터 로봇의 움직임이 어떻게 달라졌는지 확인해 보도록 합시다.

90도로 꺾어진 길을 주행할 때는 어떻게 되는지 실험해 봅시다. 여전히 90도로 꺽어진 길은 힘겨운가 봅니다. 더 큰 문제는 90도 꺾어진 부분에서 회전하다가 양쪽 바닥 센서 모두 검은색 선 위에 올라갈 수 있다는 것입니다. 이 프로그램에서 바퀴의 속도는 바닥 센서의 값과 정비례 관계를 가지기 때문에 양쪽 바닥 센서의 값이 모두 아주 작은 값이 되면 햄스터 로봇이 정지하게 될 수도 있습니다. 또한, 검은색 선의 폭이 양쪽 센서의 간격보다 넓은 경우에는 마찬가지로 양쪽 바닥 센서의 값이 모두 아주 작은 값이 되어서 햄스터 로봇이 움직이지 않을 수 있습니다. 다른 방법을 생각해 보아야겠습니다.

추가 활동:
  • 곱한 숫자 0.5를 변경해 보면서 햄스터 로봇의 움직임이 어떻게 달라지는지 살펴 보도록 합시다.
세 번째 방법
다시 원점으로 돌아가서 아래 그림을 보고 다르게 생각해 봅시다. 기본적으로는 앞으로 이동하면서 햄스터 로봇의 왼쪽 바닥 센서가 검은색 선 위에 있으면 중앙으로 가기 위해 왼쪽으로 움직이고, 오른쪽 바닥 센서가 검은색 선 위에 있으면 오른쪽으로 움직이면 됩니다.
그런데 왜 바닥 센서가 검은색 선 위에 있다는 것을 기준이 되는 숫자와 크기를 비교하여 판단을 할까요? 바닥 센서의 값이 50보다 작으면 검은색 선 위에 있다고 판단할 필요가 있을까요?
아래 그림을 자세히 살펴보면 햄스터 로봇이 중앙에서 오른쪽에 있는 경우에는 오른쪽 바닥 센서의 값이 왼쪽 바닥 센서의 값보다 커지게 됩니다. 반대로 햄스터 로봇이 중앙에서 왼쪽에 있는 경우에는 왼쪽 바닥 센서의 값이 오른쪽 바닥 센서의 값보다 커지게 됩니다. 즉, 기준이 되는 숫자를 사용하지 않고 왼쪽 바닥 센서 값과 오른쪽 바닥 센서 값의 크기를 비교하면 됩니다.

기존 방법의 프로그램을 약간 수정해 봅시다.

#include "hamster.h"

int main(int argc, char *argv[]) {
    int left, right;

    hamster_create();

    while(1) {
        left = hamster_read(HAMSTER_LEFT_FLOOR);
        right = hamster_read(HAMSTER_RIGHT_FLOOR);
        hamster_write(HAMSTER_LEFT_WHEEL, 30);
        hamster_write(HAMSTER_RIGHT_WHEEL, 30);
        if(left < right) { // 중앙에서 오른쪽에 있으면 왼쪽으로 회전
            hamster_write(HAMSTER_LEFT_WHEEL, -30);
            hamster_write(HAMSTER_RIGHT_WHEEL, 30);
        } else if(left > right) { // 중앙에서 왼쪽에 있으면 오른쪽으로 회전
            hamster_write(HAMSTER_LEFT_WHEEL, 30);
            hamster_write(HAMSTER_RIGHT_WHEEL, -30);
        }
    }

    hamster_dispose_all();
    return 0;
}

조금 더 수정하면 다음과 같이 됩니다.

#include "hamster.h"

int main(int argc, char *argv[]) {
    int diff;

    hamster_create();

    while(1) {
        diff = hamster_read(HAMSTER_LEFT_FLOOR) - hamster_read(HAMSTER_RIGHT_FLOOR);
        hamster_write(HAMSTER_LEFT_WHEEL, 30);
        hamster_write(HAMSTER_RIGHT_WHEEL, 30);
        if(diff < 0) { // 중앙에서 오른쪽에 있으면 왼쪽으로 회전
            hamster_write(HAMSTER_LEFT_WHEEL, -30);
            hamster_write(HAMSTER_RIGHT_WHEEL, 30);
        } else if(diff > 0) { // 중앙에서 왼쪽에 있으면 오른쪽으로 회전
            hamster_write(HAMSTER_LEFT_WHEEL, 30);
            hamster_write(HAMSTER_RIGHT_WHEEL, -30);
        }
    }

    hamster_dispose_all();
    return 0;
}

왼쪽 바닥 센서 값과 오른쪽 바닥 센서 값의 차이인 diff가 음수이면 햄스터 로봇이 중앙에서 오른쪽에 있고, 양수이면 왼쪽에 있다고 할 수 있습니다. 이제 햄스터 로봇의 위치에 따라 바퀴의 속도를 다르게 해봅시다. 규칙은 다음과 같습니다.

왼쪽 바퀴와 오른쪽 바퀴 관점에서 정리하면 다음과 같습니다.

이를 수식으로 표현하면 다음과 같습니다.

햄스터 로봇이 앞으로 이동하는 것은 우리가 자동차를 운전할 때 가속 폐달을 밟는 것과 같고, diff 값에 따라 왼쪽, 오른쪽으로 회전하는 것은 자동차의 운전대를 돌리는 것과 같습니다. 이 두 가지를 결합하면 왼쪽 바퀴의 속도와 오른쪽 바퀴의 속도는 다음과 같이 됩니다.

여기서 고민이 한 가지 있습니다. 가속 폐달과 운전대, 두 가지를 어느 정도 비율로 결합해야 할까요? 가속 폐달 값은 30으로 유지한다고 했을 때 운전대를 얼마나 빨리 돌려야 할까요? 햄스터 로봇이 길에서 조금 벗어났다고 해서 운전대를 너무 빨리 돌리면 좌우로 왔다갔다 불안정하게 움직일 것 같습니다. 그렇다고 운전대를 너무 천천히 돌리면 90도로 꺾어진 길에서 빠르게 회전하지 못할 것 같습니다. 적절한 값이 필요한데 우선 0.4로 해보도록 하겠습니다.

프로그램으로 작성하면 다음과 같이 됩니다.

#include "hamster.h"

int main(int argc, char *argv[]) {
    int diff;

    hamster_create();

    while(1) {
        diff = hamster_read(HAMSTER_LEFT_FLOOR) - hamster_read(HAMSTER_RIGHT_FLOOR);
        hamster_write(HAMSTER_LEFT_WHEEL, 30 + diff * 0.4);
        hamster_write(HAMSTER_RIGHT_WHEEL, 30 - diff * 0.4);
    }

    hamster_dispose_all();
    return 0;
}

90도로 꺾어진 길을 잘 따라가는지 실험을 통해 확인해 보도록 합시다. 90도 꺾어진 부분에서 회전을 잘 하지 못하면 0.4의 값을 조금 더 크게 하고, 직선을 주행할 때 좌우로 왔다갔다 하면 0.4의 값을 조금 더 작게 하면 됩니다. 곱하는 숫자 0.4를 변경해 보면서 햄스터 로봇의 움직임이 어떻게 달라지는지 살펴 보도록 합시다.
목차
수업 준비
  1. 소프트웨어 설치
  2. 로봇과 PC 연결하기
  3. 소프트웨어 실행
기초
  1. 센서 한 개를 이용한 라인 트레이서
  2. 센서 두 개를 이용한 라인 트레이서
심화
Copyright Robot Software Education Institute. All rights reserved.
Please contact prof. Kwang-Hyun Park (akaii@kw.ac.kr) if you have any problem.