장애물 척척 피하는 똑똑한 로봇 만들기 (초보편) > 초보자를 위한 로봇 프로젝트

본문 바로가기
사이트 내 전체검색

초보자를 위한 로봇 프로젝트

장애물 척척 피하는 똑똑한 로봇 만들기 (초보편)

페이지 정보

profile_image
작성자 관리자
댓글 0건 조회 277회 작성일 25-11-20 12:35

본문

장애물 척척 피하는 똑똑한 로봇 만들기 (초보편)

장애물을 척척 피하는 로봇을 만드는 것은 로봇에게 '눈'을 달아주고 스스로 '생각'해서 '움직이도록' 하는 아주 흥미로운 과정입니다. 초보자분들도 쉽게 따라 할 수 있도록, 가장 기본적인 초음파 센서를 이용한 장애물 회피 로봇 만들기를 자세히 설명해 드릴게요. 라인트레이서 로봇과 비슷한 방식으로 '인지 - 판단 - 행동'의 기본 원리를 다시 한번 익힐 수 있습니다.


1단계: 장애물 회피 로봇의 '원리' 이해하기

장애물 회피 로봇은 다음과 같은 간단한 원리로 움직입니다.


인지 (센서): 로봇 앞쪽에 달린 '초음파 센서'가 주변의 물체까지의 '거리'를 측정합니다.

판단 (컨트롤러/코드): 측정된 거리 값을 아두이노가 읽어들여, 현재 로봇 앞에 '장애물이 있는지', '얼마나 멀리 있는지'를 판단합니다.

장애물이 없을 때 (멀리 있을 때): 계속 앞으로 직진.

장애물이 가까이 있을 때 (위험 거리 이내): 일단 정지. 그리고 다른 방향(예: 왼쪽, 오른쪽)에 장애물이 없는지 확인 후 그쪽으로 회전.

행동 (모터): 아두이노의 판단에 따라 모터를 제어하여 로봇의 움직임(직진, 정지, 회전)을 결정합니다.

2단계: 필수 준비물 확인 및 구매

라인트레이서 로봇과 유사하지만, 라인 센서 대신 초음파 센서가 사용됩니다.


컨트롤러:

아두이노 우노 R3 (Arduino Uno R3) 호환 보드: 1개

USB 케이블: 아두이노와 컴퓨터 연결용.

로봇 섀시:

2WD 로봇 자동차 섀시 키트: 1개 - 모터, 바퀴, 프레임, 캐스터 포함 (라인트레이서와 동일)

액추에이터:

모터 드라이버 (L298N): 1개

SG90 마이크로 서보 모터: 1개 (선택 사항이지만, 센서를 움직여 장애물 감지 시야를 넓히는 데 유용)

센서:

초음파 센서 모듈 (HC-SR04): 1개

전원:

AA 배터리 홀더 (4개용): 1개 (모터 전원용)

AA 배터리: 4개

(선택 사항) 9V 배터리 & 스냅 커넥터: 아두이노 별도 전원용.

연결 재료:

브레드보드: 1개 (선택 사항)

점퍼 케이블 (수-수, 수-암): 넉넉하게

공구:

드라이버 세트, 니퍼, 양면테이프 또는 글루건.

3단계: 로봇의 '몸' 조립하기 (기계적 조립)

라인트레이서 로봇과 거의 동일한 방식으로 조립하되, 초음파 센서의 위치가 다릅니다.


로봇 섀시 조립: 프레임, 모터, 바퀴, 캐스터 등을 조립합니다.

아두이노/모터 드라이버 고정: 아두이노 보드와 모터 드라이버(L298N)를 로봇 프레임에 고정합니다.

초음파 센서 부착:

SG90 서보 모터와 결합: 서보 모터의 축에 초음파 센서를 고정하여, 센서가 좌우로 회전하며 장애물을 감지할 수 있도록 합니다. 이 서보 모터를 로봇 앞쪽에 고정합니다. (센서의 감지 시야를 넓히는 데 큰 도움이 됩니다.)

서보 모터 없이 고정: 서보 모터 없이 로봇 앞쪽에 초음파 센서를 고정할 수도 있습니다. 이 경우 센서는 정면만 감지합니다.

높이: 초음파 센서의 송수신부가 바닥과 수평을 이루도록, 그리고 로봇의 높이 중앙에 위치하도록 고정하는 것이 좋습니다.

4단계: 로봇의 '신경망' 연결하기 (전기 배선 - L298N 모터 드라이버 기준)

라인트레이서 로봇과 대부분 동일합니다.


모터와 L298N 모터 드라이버 연결: (라인트레이서와 동일)

L298N OUT1, OUT2 → 왼쪽 모터

L298N OUT3, OUT4 → 오른쪽 모터

전원부 연결: (라인트레이서와 동일)

AA 배터리 홀더의 + → L298N +12V (또는 VCC)

AA 배터리 홀더의 - → L298N GND

L298N 드라이버와 아두이노 연결: (라인트레이서와 동일)

L298N IN1 → 아두이노 핀 8

L298N IN2 → 아두이노 핀 9

L298N IN3 → 아두이노 핀 10

L298N IN4 → 아두이노 핀 11

L298N ENA → 아두이노 핀 5 (PWM 핀)

L298N ENB → 아두이노 핀 6 (PWM 핀)

L298N GND → 아두이노 GND (가장 중요!)

초음파 센서 (HC-SR04)와 아두이노 연결:

HC-SR04 VCC → 아두이노 5V

HC-SR04 GND → 아두이노 GND

HC-SR04 Trig (트리거 핀) → 아두이노 핀 4 (아무 디지털 핀이나 가능)

HC-SR04 Echo (에코 핀) → 아두이노 핀 7 (아무 디지털 핀이나 가능)

(선택 사항) SG90 서보 모터와 아두이노 연결:

SG90 오렌지/노란색 (Signal) → 아두이노 핀 12 (PWM 핀 중 아무거나 가능)

SG90 빨간색 (VCC) → 아두이노 5V

SG90 갈색/검은색 (GND) → 아두이노 GND

배선 시 주의사항: (라인트레이서와 동일) 모든 배선은 전원이 없는 상태에서 하고, 정확한 연결을 거듭 확인해야 합니다.


5단계: 로봇의 '명령' 프로그래밍하기 (아두이노 코딩)

이제 로봇에게 장애물 회피 방법을 가르쳐 줄 차례입니다. 아두이노 IDE를 사용하여 코드를 업로드합니다.


5.1. 아두이노 IDE 설정 (라인트레이서와 동일)

5.2. 장애물 회피 로봇 기본 코드 (SG90 서보 모터 포함 예시)

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;


// 모터 속도 (0-255)

const int base_speed = 150; // 기본 전진 속도

const int turn_speed = 100; // 회전 시 모터 속도


// 장애물 감지 거리 임계값 (cm)

const int obstacle_threshold = 20; // 20cm 이내면 장애물로 간주


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() {

  long duration, distance;


  // 1. 초음파 센서로 전방 거리 측정

  digitalWrite(trigPin, LOW);

  delayMicroseconds(2);

  digitalWrite(trigPin, HIGH);

  delayMicroseconds(10);

  digitalWrite(trigPin, LOW);

  duration = pulseIn(echoPin, HIGH); // 에코 핀으로부터 돌아오는 시간 측정

  distance = duration * 0.034 / 2;    // 시간을 거리(cm)로 변환 (음속: 340m/s = 0.034cm/us)


  Serial.print("Distance: ");

  Serial.print(distance);

  Serial.println(" cm");


  // 2. 측정된 거리에 따른 로봇 행동 판단

  if (distance > obstacle_threshold) {

    moveForward(); // 장애물이 멀리 있으면 전진

  } else {

    stopRobot(); // 장애물이 가까우면 일단 정지

    delay(300); // 잠시 대기


    // 3. 좌우 거리 측정 (서보 모터가 있을 경우)

    int leftDistance = measureDistance(160); // 왼쪽으로 센서 돌려 측정

    delay(200);

    int rightDistance = measureDistance(20);  // 오른쪽으로 센서 돌려 측정

    delay(200);

    myservo.write(90); // 센서 다시 중앙으로


    Serial.print("Left Dist: ");

    Serial.print(leftDistance);

    Serial.print(" Right Dist: ");

    Serial.println(rightDistance);


    // 4. 장애물이 없는 방향으로 회전

    if (leftDistance > rightDistance) {

      turnLeft(); // 왼쪽이 더 멀면 왼쪽으로 회전

    } else {

      turnRight(); // 오른쪽이 더 멀면 오른쪽으로 회전 (같으면 기본값)

    }

    delay(500); // 충분히 회전

  }

}


// 거리 측정 함수 (서보 모터를 사용하여 특정 각도에서 측정)

int 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);

  return duration * 0.034 / 2;

}



// 로봇 제어 함수들 (라인트레이서와 동일)


void moveForward() {

  digitalWrite(motor1_in1, HIGH); digitalWrite(motor1_in2, LOW);

  analogWrite(motor1_ena, base_speed);


  digitalWrite(motor2_in1, HIGH); digitalWrite(motor2_in2, LOW);

  analogWrite(motor2_enb, base_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 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단계: 로봇 테스트 및 최적화

이제 똑똑한 로봇을 시험할 시간입니다!


테스트 환경 준비: 로봇이 자유롭게 움직일 수 있는 넓은 공간을 확보하고, 다양한 높이와 재질의 장애물(박스, 책 등)을 배치합니다.

시험 운행: 로봇에 전원을 켜고 작동을 시작합니다.

디버깅 및 조정:

장애물 감지 실패: 초음파 센서의 각도나 높이가 적절한지 확인합니다. 너무 높거나 낮으면 장애물을 감지하지 못할 수 있습니다.

거리 임계값: obstacle_threshold 값을 조절하여 로봇이 너무 일찍 멈추거나 너무 가까이 가서 부딪히지 않도록 최적의 거리를 찾습니다.

회전 동작: turn_speed와 delay 값을 조정하여 로봇이 충분히 회전하여 장애물을 피할 수 있도록 합니다.

모터 방향: 로봇이 회전할 때 예상한 방향으로 도는지 확인합니다. 만약 반대로 돌면 turnLeft()나 turnRight() 함수 내의 모터 제어 라인을 수정합니다.

모터 속도: base_speed와 turn_speed 값을 조정하여 로봇의 전반적인 움직임을 부드럽게 하거나 빠르게 만듭니다.

축하합니다! 이제 당신만의 장애물 회피 로봇이 완성되었습니다!


이 로봇은 로봇에게 '공간 인지' 능력을 부여하고 스스로 '생각'해서 위험을 '회피'하는 방법을 가르쳐주는 프로젝트입니다. 이 코드는 가장 기본적인 회피 로직이지만, 여기서 더 나아가 다양한 센서를 추가하거나, AI 알고리즘을 도입하여 더욱 똑똑하고 유연하게 움직이는 로봇을 만들 수 있습니다. 로봇 공학의 세계는 무궁무진합니다!

[이 게시물은 관리자님에 의해 2025-11-22 10:15:07 초보자를 위한 로봇 프로젝트에서 이동 됨]
[이 게시물은 관리자님에 의해 2025-11-29 13:01:12 18에서 이동 됨]

댓글목록

등록된 댓글이 없습니다.


회사소개 개인정보취급방침 서비스이용약관 모바일 버전으로 보기 상단으로

작크와콩나무
대표:이강복 등록번호:129-30-34337 개인정보관리책임자:이경영

Copyright © https://roboman.co.kr/ All rights reserved.