서보 모터 구동 장애물 회피 로봇: 아두이노 & HC-SR04로 제작하기
부품 및 소모품
| 부품 | 수량 |
| 아두이노 우노 (Arduino UNO) | 1 |
| SG90 마이크로 서보 모터 | 1 |
| HC-SR04 초음파 센서 (SparkFun) | 1 |
| 로봇 섀시 키트 - 2WD DC 모터 포함 | 1 |
| 점퍼 와이어 (일반) | 1세트 |
| 아두이노 모터 쉴드 Rev3 | 1 |
필요 도구 및 장비
앱 및 온라인 서비스
프로젝트 소개
말레이시아 사이버자야의 멀티미디어 대학교 미디어 아트 디자인 전공 학생입니다. 3학년 때 인터랙션 디자인 수업에서 아두이노 부품의 작동 원리를 배웠고, 최종 과제로 장애물 회피 로봇을 제작하게 되었습니다.
1단계: 로봇 섀시 조립
키트 구성품: 섀시, DC 모터 2개, 바퀴 2개, 전방 캐스터 휠, 배터리 홀더, 나사, 스위치, 점퍼 와이어.
2단계: 부품 사전 테스트 및 모터 납땜
납땜 전 모든 부품(DC 모터, 아두이노, 모터 쉴드, 서보 모터, 초음파 센서) 작동 테스트를 권장합니다. 이후 양쪽 모터에 빨간색/검은색 와이어를 납땜합니다.
3단계: 배터리 홀더 및 스위치 연결
배터리 홀더의 검은색 와이어를 절반 잘라 스위치 양단에 각각 납땜하여 전원 스위치를 만듭니다.
4단계: 아두이노와 모터 쉴드 적층
모터 쉴드를 아두이노 보드 위에 꽂아 적층합니다.
5단계: 모터 쉴드에 DC 모터 연결
모터 쉴드는 모터당 최대 600mA를 공급합니다. 모터 와이어가 충분히 길다면 직접 연결하고, 짧다면 점퍼 와이어를 연장하여 납땜합니다. 왼쪽 모터는 M1, 오른쪽 모터는 M3 커넥터에 연결합니다.
6단계: 배터리 스위치 및 센서용 점퍼 와이어 연결
배터리 스위치의 빨간색/검은색 와이어를 모터 쉴드 전원 단자에 연결합니다. 이후 5V, GND, A4, A5 핀용으로 색상별 수/암 점퍼 와이어를 반으로 잘라 납땜합니다(색상 통일로 배선 식별 용이).
7단계: 보드 고정
양면 테이프나 글루건으로 아두이노+모터 쉴드 조립체를 섀시에 고정합니다.
8단계: 초음파 센서 배선
준비된 점퍼 와이어를 초음파 센서에 연결: 흰색(5V)→VCC, 검은색(GND)→GND, 갈색(A4)→Echo, 주황색(A5)→Trig.
9단계: 서보 모터 연결
서보 모터를 모터 쉴드의 servo_2 슬롯에 꽂습니다(서보 종류별 핀 배열 확인 필요).
마지막 단계: 코드 업로드
필수 라이브러리 3개: AFMotor.h (모터 쉴드), Servo.h (서보), NewPing.h (초음파 센서). 아두이노 IDE에 라이브러리 설치 후 아래 코드 업로드.
소스 코드
#include <AFMotor.h>
#include <Servo.h>
#include <NewPing.h>
#define TRIG_PIN A4
#define ECHO_PIN A5
#define MAX_DISTANCE_POSSIBLE 1000
#define MAX_SPEED 150
#define COLL_DIST 20
#define TURN_DIST COLL_DIST+10
NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DISTANCE_POSSIBLE);
AF_DCMotor leftMotor(3, MOTOR12_8KHZ);
AF_DCMotor rightMotor(1, MOTOR12_8KHZ);
Servo neckControllerServoMotor;
int pos = 0;
int maxDist = 0;
int maxAngle = 0;
int maxRight = 0;
int maxLeft = 0;
int maxFront = 0;
int course = 0;
int curDist = 0;
String motorSet = "";
int speedSet = 0;
void setup() {
neckControllerServoMotor.attach(10);
neckControllerServoMotor.write(90);
delay(2000);
checkPath();
motorSet = "FORWARD";
neckControllerServoMotor.write(90);
moveForward();
}
void loop() {
checkForward();
checkPath();
}
void checkPath() {
int curLeft = 0, curFront = 0, curRight = 0, curDist = 0;
neckControllerServoMotor.write(144);
delay(120);
for(pos = 144; pos >= 36; pos-=18) {
neckControllerServoMotor.write(pos);
delay(90);
checkForward();
curDist = readPing();
if (curDist < COLL_DIST) { checkCourse(); break; }
if (curDist < TURN_DIST) { changePath(); }
if (curDist > curDist) { maxAngle = pos; }
if (pos > 90 && curDist > curLeft) { curLeft = curDist; }
if (pos == 90 && curDist > curFront) { curFront = curDist; }
if (pos < 90 && curDist > curRight) { curRight = curDist; }
}
maxLeft = curLeft; maxRight = curRight; maxFront = curFront;
}
void setCourse() {
if (maxAngle < 90) turnRight();
if (maxAngle > 90) turnLeft();
maxLeft = maxRight = maxFront = 0;
}
void checkCourse() {
moveBackward(); delay(500); moveStop(); setCourse();
}
void changePath() {
if (pos < 90) lookLeft();
if (pos > 90) lookRight();
}
int readPing() {
delay(70);
unsigned int uS = sonar.ping();
return uS / US_ROUNDTRIP_CM;
}
void checkForward() {
if (motorSet == "FORWARD") {
leftMotor.run(FORWARD); rightMotor.run(FORWARD);
}
}
void checkBackward() {
if (motorSet == "BACKWARD") {
leftMotor.run(BACKWARD); rightMotor.run(BACKWARD);
}
}
void moveStop() { leftMotor.run(RELEASE); rightMotor.run(RELEASE); }
void moveForward() {
motorSet = "FORWARD";
leftMotor.run(FORWARD); rightMotor.run(FORWARD);
for (speedSet = 0; speedSet < MAX_SPEED; speedSet += 2) {
leftMotor.setSpeed(speedSet); rightMotor.setSpeed(speedSet);
delay(5);
}
}
void moveBackward() {
motorSet = "BACKWARD";
leftMotor.run(BACKWARD); rightMotor.run(BACKWARD);
for (speedSet = 0; speedSet < MAX_SPEED; speedSet += 2) {
leftMotor.setSpeed(speedSet); rightMotor.setSpeed(speedSet);
delay(5);
}
}
void turnRight() {
motorSet = "RIGHT";
leftMotor.run(FORWARD); rightMotor.run(BACKWARD); delay(400);
motorSet = "FORWARD";
leftMotor.run(FORWARD); rightMotor.run(FORWARD);
}
void turnLeft() {
motorSet = "LEFT";
leftMotor.run(BACKWARD); rightMotor.run(FORWARD); delay(400);
motorSet = "FORWARD";
leftMotor.run(FORWARD); rightMotor.run(FORWARD);
}
void lookRight() { rightMotor.run(BACKWARD); delay(400); rightMotor.run(FORWARD); }
void lookLeft() { leftMotor.run(BACKWARD); delay(400); leftMotor.run(FORWARD); }
회로도