로봇과 함께하는 미션: 미로 탈출 로봇 만들기
페이지 정보
작성자 관리자 작성일 25-11-20 13:08 조회 250 댓글 0본문
로봇과 함께하는 미션: 미로 탈출 로봇 만들기
'미로 탈출 로봇 만들기'는 로봇에게 '눈(센서)'을 달아주고, 스스로 '판단(코딩)'하여 '길(미로)'을 찾아 나가는 탐험 과정을 구현하는 매우 흥미진진한 프로젝트입니다. 초보자분들도 차근차근 따라 하면 충분히 만들 수 있으며, 로봇의 인공지능 기초 개념을 이해하는 데 아주 좋은 출발점이 될 것입니다.
1단계: 미로 탈출 로봇의 '원리' 이해하기
미로 탈출 로봇은 기본적인 장애물 회피 로봇의 원리에 '탐색 및 판단' 로직이 더해진 형태입니다.
인지 (초음파 센서): 로봇의 앞쪽에 달린 초음파 센서가 전방의 장애물까지의 거리를 지속적으로 측정합니다.
판단 (컨트롤러/코드): 아두이노가 센서 값으로 장애물 유무와 거리를 판단하고, 그에 따라 다음 행동을 결정합니다.
전방에 장애물이 없을 때: 앞으로 직진.
전방에 장애물이 있을 때:
일단 정지.
좌우를 탐색하여 갈 수 있는 길(장애물이 없는 쪽)이 있는지 확인합니다.
갈 수 있는 길이 여러 개라면, 특정 규칙(예: 항상 오른쪽 우선)에 따라 방향을 선택하고 회전합니다.
모든 방향이 막혔다면 후진하여 다른 경로를 탐색합니다.
행동 (모터): 아두이노의 판단에 따라 로봇의 바퀴 모터를 제어하여 이동하고, 선택한 경로를 따라갑니다.
2단계: 필수 준비물 확인 및 구매
컨트롤러:
아두이노 우노 R3 (Arduino Uno R3) 호환 보드: 1개
USB 케이블: 아두이노와 컴퓨터 연결용.
로봇 섀시:
2WD 로봇 자동차 섀시 키트: 1개 (모터 2개, 바퀴 2개, 프레임, 캐스터 포함)
액추에이터:
모터 드라이버 (L298N): 1개
SG90 마이크로 서보 모터: 1개 (초음파 센서 방향 전환용 - 미로 탐색의 효율을 높여줍니다.)
센서:
초음파 센서 모듈 (HC-SR04): 1개 (장애물 감지 및 거리 측정용)
전원:
AA 배터리 홀더 (4개용): 1개 (모터 전원용)
AA 배터리: 4개
(선택 사항) 9V 배터리 & 스냅 커넥터: 아두이노 별도 전원용.
연결 재료:
브레드보드: 1개 (선택 사항)
점퍼 케이블 (수-수, 수-암): 넉넉하게
공구:
드라이버 세트, 니퍼, 양면테이프 또는 글루건.
미로:
골판지 박스나 두꺼운 종이를 잘라 로봇이 통과할 수 있는 크기의 통로와 벽을 가진 간단한 미로를 만듭니다. (벽의 높이가 로봇의 초음파 센서 높이보다 높아야 합니다.)
3단계: 로봇의 '몸' 조립하기 (기계적 조립)
장애물 회피 로봇과 거의 동일하게 조립합니다.
로봇 섀시 조립: 프레임, 바퀴 모터, 바퀴, 캐스터 등을 조립합니다.
아두이노/모터 드라이버 고정: 아두이노 보드와 L298N 모터 드라이버를 로봇 프레임(주로 상판)에 고정합니다.
초음파 센서 부착: SG90 서보 모터에 HC-SR04를 부착하여 로봇 앞쪽에 고정합니다. 서보 모터가 좌우로 회전하며 장애물 감지 시야를 넓히도록 합니다. 초음파 센서가 미로 벽을 잘 감지할 수 있도록 적절한 높이(로봇 바닥에서 약 5~10cm)에 고정합니다.
4단계: 로봇의 '신경망' 연결하기 (전기 배선)
장애물 회피 로봇과 동일합니다.
바퀴 모터와 L298N 모터 드라이버 연결
전원부 연결 (AA 배터리 홀더, 아두이노 GND-L298N GND 연결)
L298N 드라이버와 아두이노 연결
초음파 센서 (HC-SR04)와 아두이노 연결:
HC-SR04 VCC → 아두이노 5V
HC-SR04 GND → 아두이노 GND
HC-SR04 Trig → 아두이노 핀 4
HC-SR04 Echo → 아두이노 핀 7
SG90 서보 모터와 아두이노 연결:
SG90 Signal → 아두이노 핀 12
SG90 VCC → 아두이노 5V
SG90 GND → 아두이노 GND
배선 시 주의사항: (이전 프로젝트와 동일) 모든 배선은 전원이 없는 상태에서 하고, 정확한 연결을 거듭 확인해야 합니다.
5단계: 로봇의 '명령' 프로그래밍하기 (아두이노 코딩)
여기서는 기본적인 미로 탈출 전략 중 하나인 '오른쪽 벽면 따르기 (Right-Hand Rule)' 전략을 기반으로 코드를 작성해 보겠습니다.
오른쪽 벽면 따르기 전략: 항상 로봇의 오른쪽에 벽이 닿아 있도록 벽을 따라가는 전략입니다. 막다른 길에 다다르면 왼쪽으로 돌거나 후진하여 길을 찾습니다. 이 전략은 단순 연결 미로(벽을 따라가면 항상 출구가 나오는 미로)에서 유효합니다.
5.1. 아두이노 IDE 설정 (이전 프로젝트와 동일)
5.2. 미로 탈출 로봇 기본 코드 (예시)
cpp
#include <Servo.h> // 서보 모터 라이브러리 포함
// 바퀴 모터 제어 핀 (L298N)
const int motor1_in1 = 8;
const int motor1_in2 = 9;
const int motor2_in1 = 10;
const int motor2_in2 = 11;
const int motor1_ena = 5; // 왼쪽 바퀴 속도 (PWM)
const int motor2_enb = 6; // 오른쪽 바퀴 속도 (PWM)
// 초음파 센서 핀
const int trigPin = 4;
const int echoPin = 7;
// 서보 모터 핀
const int servoPin = 12;
// 모터 속도
const int drive_speed = 150; // 주행 속도
const int turn_speed = 100; // 회전 속도
// 장애물 감지 거리 임계값 (cm)
const int front_threshold = 20; // 전방 장애물 판단 기준 (20cm)
const int side_threshold = 15; // 옆면 벽 감지 기준 (15cm)
Servo myservo; // 서보 객체 생성
void setup() {
pinMode(motor1_in1, OUTPUT); pinMode(motor1_in2, OUTPUT);
pinMode(motor2_in1, OUTPUT); pinMode(motor2_in2, OUTPUT);
pinMode(motor1_ena, OUTPUT); pinMode(motor2_enb, OUTPUT);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
myservo.attach(servoPin);
myservo.write(90); // 서보 모터를 중앙 (90도)으로 초기화
delay(500);
Serial.begin(9600);
}
void loop() {
int front_distance = measureDistance(90); // 전방 거리 측정 (서보 90도)
Serial.print("Front: "); Serial.print(front_distance); Serial.println(" cm");
// 1. 전방에 장애물이 있는가?
if (front_distance < front_threshold) { // 장애물 있음
stopRobot(); // 정지
delay(200);
// 2. 우측 길 탐색 (오른쪽 우선 전략)
int right_distance = measureDistance(20); // 서보를 20도로 돌려 우측 측정 (대략 60도 방향)
Serial.print("Right: "); Serial.print(right_distance); Serial.println(" cm");
delay(200);
// 3. 좌측 길 탐색
int left_distance = measureDistance(160); // 서보를 160도로 돌려 좌측 측정 (대략 120도 방향)
Serial.print("Left: "); Serial.print(left_distance); Serial.println(" cm");
delay(200);
myservo.write(90); // 센서 다시 중앙으로
delay(200);
if (right_distance > side_threshold) { // 우측에 충분한 공간이 있으면 (오른쪽 우선)
turnRight(); // 오른쪽으로 회전
delay(700); // 충분히 회전
moveForward(); // 회전 후 전진
delay(300);
} else if (left_distance > side_threshold) { // 우측이 막혔고 좌측에 공간이 있으면
turnLeft(); // 왼쪽으로 회전
delay(700); // 충분히 회전
moveForward(); // 회전 후 전진
delay(300);
} else { // 우측도 막히고 좌측도 막혔다면 (막다른 길)
turnAround(); // 뒤로 돌기 (180도 회전)
delay(1400); // 180도 회전에 필요한 시간 (조절 필요)
moveForward(); // 회전 후 전진
delay(300);
}
} else { // 전방에 장애물 없음
moveForward(); // 앞으로 전진
delay(100); // 전진하는 시간
}
}
// 거리 측정 함수 (서보 모터를 사용하여 특정 각도에서 측정)
long measureDistance(int angle) {
myservo.write(angle);
delay(300); // 서보가 해당 각도로 이동할 시간을 줌
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
long duration = pulseIn(echoPin, HIGH);
if (duration == 0) return 999; // 펄스를 받지 못하면 아주 먼 거리로 처리 (오류 방지)
return duration * 0.034 / 2;
}
// 로봇 제어 함수들 (이전 프로젝트들과 유사)
void moveForward() {
digitalWrite(motor1_in1, HIGH); digitalWrite(motor1_in2, LOW);
analogWrite(motor1_ena, drive_speed);
digitalWrite(motor2_in1, HIGH); digitalWrite(motor2_in2, LOW);
analogWrite(motor2_enb, drive_speed);
}
void turnLeft() { // 제자리 좌회전 (왼쪽 바퀴 후진, 오른쪽 바퀴 전진)
digitalWrite(motor1_in1, LOW); digitalWrite(motor1_in2, HIGH);
analogWrite(motor1_ena, turn_speed);
digitalWrite(motor2_in1, HIGH); digitalWrite(motor2_in2, LOW);
analogWrite(motor2_enb, turn_speed);
}
void turnRight() { // 제자리 우회전 (왼쪽 바퀴 전진, 오른쪽 바퀴 후진)
digitalWrite(motor1_in1, HIGH); digitalWrite(motor1_in2, LOW);
analogWrite(motor1_ena, turn_speed);
digitalWrite(motor2_in1, LOW); digitalWrite(motor2_in2, HIGH);
analogWrite(motor2_enb, turn_speed);
}
void turnAround() { // 180도 회전
digitalWrite(motor1_in1, LOW); digitalWrite(motor1_in2, HIGH); // 왼쪽 바퀴 후진
analogWrite(motor1_ena, drive_speed);
digitalWrite(motor2_in1, LOW); digitalWrite(motor2_in2, HIGH); // 오른쪽 바퀴 후진
analogWrite(motor2_enb, drive_speed);
}
void stopRobot() {
digitalWrite(motor1_in1, LOW); digitalWrite(motor1_in2, LOW);
analogWrite(motor1_ena, 0);
digitalWrite(motor2_in1, LOW); digitalWrite(motor2_in2, LOW);
analogWrite(motor2_enb, 0);
}
5.3. 코드 업로드 및 테스트
위 코드를 아두이노 IDE에 복사하여 붙여넣기 합니다.
스케치(Sketch) → 컴파일/업로드(Upload)를 클릭하여 코드를 아두이노 보드에 업로드합니다.
툴(Tools) → 시리얼 모니터(Serial Monitor)를 열어 초음파 센서가 정확한 거리를 측정하는지 확인합니다. 센서를 좌우로 돌려가며 값이 변하는 것을 보세요.
6단계: 로봇 테스트 및 최적화
미로 만들기: 골판지나 종이 상자로 로봇이 통과할 수 있는 통로 폭(로봇 폭의 약 1.5~2배)을 가진 간단한 미로를 만듭니다. 벽의 높이는 초음파 센서보다 높아야 합니다. 미로의 시작과 끝을 정합니다.
시험 운행: 로봇을 미로 시작점에 놓은 후 전원을 켜서 작동을 시작합니다.
디버깅 및 조정:
거리 임계값: front_threshold와 side_threshold 값을 조절하여 로봇이 벽에 너무 가까이 가거나 너무 멀리 떨어지지 않도록 합니다. 미로의 벽 재질(반사율)에 따라 값이 달라질 수 있습니다.
회전 시간/각도: delay() 값을 조절하여 로봇이 적절한 각도로 회전하도록 합니다. 미로의 코너 폭에 따라 회전 시간(delay(700))을 세밀하게 조절해야 합니다.
모터 속도: drive_speed, turn_speed 값을 조정하여 로봇의 움직임을 안정화합니다.
센서 정확도: 센서가 제대로 동작하는지 확인하고, 혹시 초음파가 특정 각도에서 반사가 잘 안 되는 경우가 있는지 테스트합니다.
미로 복잡도: 처음에는 단순한 미로로 시작하여, 로봇이 잘 탈출하는 것을 확인한 후 점차 복잡한 미로에 도전합니다.
축하합니다! 이제 당신만의 미로 탈출 로봇이 완성되었습니다!
이 프로젝트는 로봇이 '인지', '판단', '행동'을 통합하여 자율적으로 '탐색' 임무를 수행하는 것을 보여줍니다. '오른쪽 벽면 따르기'는 가장 기본적인 미로 탈출 전략 중 하나이지만, 여기서 더 나아가:
라인 센서 추가: 미로 바닥에 선을 그려 지도를 만들거나, 미로 탈출 과정을 기록하게 할 수 있습니다.
다양한 탐색 알고리즘: 왼쪽 벽면 따르기, DFS(깊이 우선 탐색), BFS(너비 우선 탐색) 등 더 효율적인 탐색 알고리즘을 구현해 보세요. (더 많은 센서나 메모리 필요)
기록 및 학습: 미로를 탐색하는 과정을 기록하고, 다음에 같은 미로를 만났을 때 더 빠르게 탈출하도록 학습하는 인공지능 요소를 도입해 볼 수 있습니다 (라즈베리 파이 필요).
자신이 만든 로봇이 미로를 헤치고 출구를 찾아 나서는 모습을 보며, 미래 로봇 공학자의 꿈을 더욱 키워나가시길 바랍니다!
댓글목록 0
등록된 댓글이 없습니다.
