최종 프로젝트: 장애물을 피하는 로봇
로드맵에서 배운 모든 것이 여기서 하나로 모여요. 거리를 재는 센서, 판단하는 마이크로컨트롤러, 전력을 주는 드라이버, 그리고 모터 두 개예요. 먼저 화면에서 움직이는 걸 보고, 그다음에 직접 만들어 보세요.
Lab 01에서 작동하는 모습 보기
Lab 01에서는 같은 종류의 로봇을 조립하고 테스트해요. 주의할 점: TB6612FNG 대신 L298N을 쓰고 핀도 달라요(TRIG는 D9, ECHO는 D10). 그래서 코드가 아래 코드와 달라요.
Lab 01 열기필요한 것
가격은 적지 않았어요. 가게와 나라마다 다르거든요. "2륜 로봇" 키트 중에는 섀시, 모터, 바퀴, 건전지 홀더가 이미 들어 있는 것이 많아요.
| 수량 | 부품 | 용도 |
|---|---|---|
| 1 | Arduino Uno(또는 호환 보드)와 USB 케이블 | 두뇌예요. 코드를 실행해요. |
| 1 | TB6612FNG 드라이버(또는 L298N) | 모터에 전력을 줘요. |
| 2 | 바퀴가 달린 TT 기어 모터 | 로봇을 움직여요. 양쪽에 하나씩이에요. |
| 1 | 캐스터 | 뒤쪽을 받쳐 줘요. |
| 1 | 아크릴 섀시 | 모든 것을 올리는 바닥판이에요. |
| 1 | HC-SR04 센서 | 앞에 있는 물체까지의 거리를 재요. |
| 1 | 스위치가 있는 AA 건전지 4개 홀더(6 V) | 모터에만 전원을 줘요. |
| 1 | USB 보조 배터리 | 모터와 따로 Arduino에 전원을 줘요. |
| 1 | 미니 브레드보드와 점퍼 와이어 | 납땜 없이 연결하기 위해서예요. |
배선
| 출발 | 도착 | 이유 |
|---|---|---|
| HC-SR04 VCC / GND | Arduino 5V / GND | 센서에 전원을 줘요. |
| HC-SR04 Trig | Arduino 핀 7 | Arduino가 측정하라고 시켜요. |
| HC-SR04 Echo | Arduino 핀 8 | 센서가 에코 시간을 돌려줘요. |
| TB6612FNG VCC | Arduino 5V | 드라이버의 로직용이에요. |
| TB6612FNG VM | 건전지 홀더의 + | 모터의 전력이에요. |
| TB6612FNG GND | Arduino의 GND와 건전지 홀더의 − | 공통 GND: 이게 없으면 신호가 제대로 전달되지 않아요. |
| AIN1, AIN2, PWMA | 핀 2, 4, 5 | 왼쪽 모터의 방향과 속도예요. |
| BIN1, BIN2, PWMB | 핀 10, 11, 6 | 오른쪽 모터의 방향과 속도예요. |
| STBY | 핀 12 | HIGH일 때 드라이버가 작동해요. |
| AO1 / AO2 와 BO1 / BO2 | 왼쪽 모터와 오른쪽 모터 | 각 모터로 나가는 전력 출력이에요. |
코드
// 장애물을 피하는 로봇: Arduino Uno + TB6612FNG + HC-SR04
const int TRIG = 7, ECHO = 8;
const int AIN1 = 2, AIN2 = 4, PWMA = 5; // 왼쪽 모터
const int BIN1 = 10, BIN2 = 11, PWMB = 6; // 오른쪽 모터
const int STBY = 12; // 드라이버 스탠바이
void setup() {
pinMode(TRIG, OUTPUT);
pinMode(ECHO, INPUT);
int pins[] = {AIN1, AIN2, PWMA, BIN1, BIN2, PWMB, STBY};
for (int p : pins) pinMode(p, OUTPUT);
digitalWrite(STBY, HIGH); // 드라이버를 대기 모드에서 깨운다
Serial.begin(9600);
}
long distanceCm() {
digitalWrite(TRIG, LOW);
delayMicroseconds(2);
digitalWrite(TRIG, HIGH); // 10 µs 펄스: "측정해"
delayMicroseconds(10);
digitalWrite(TRIG, LOW);
long us = pulseIn(ECHO, HIGH, 30000); // 에코를 최대 30 ms 기다린다
if (us == 0) return 400; // 에코 없음: 길이 비어 있다
return us / 58; // µs / 58 = cm
}
// speed는 -255(후진)부터 255(전진)까지
void motor(int in1, int in2, int pwm, int speed) {
digitalWrite(in1, speed > 0);
digitalWrite(in2, speed < 0);
analogWrite(pwm, abs(speed));
}
void drive(int left, int right) {
motor(AIN1, AIN2, PWMA, left);
motor(BIN1, BIN2, PWMB, right);
}
void loop() {
long d = distanceCm();
Serial.println(d);
if (d < 20) {
drive(-150, -150); // 후진
delay(300);
drive(150, -150); // 제자리에서 회전
delay(350);
} else {
drive(180, 180); // 전진
}
delay(50);
}- distanceCm()는 HC-SR04 Lab과 똑같이 동작해요. 10 µs 펄스를 보내고, 에코를 기다렸다가, 58로 나눠요.
- motor()는 드라이버의 H 브리지를 써요. 방향마다 핀 하나, 속도는 PWM으로 정해요.
- 모터가 거꾸로 돌면 코드를 바꾸지 말고, 드라이버에서 그 모터의 두 선을 서로 바꿔 꽂으세요.
뭔가 안 될 때
- 모터가 돌기 시작하면 Arduino가 재시작돼요
- 모터와 Arduino가 같은 건전지를 쓰고 있어서예요. Arduino는 USB로, 모터는 건전지 홀더로 전원을 주세요.
- 모터가 안 움직여요
- STBY가 HIGH인지, 건전지 홀더의 스위치가 켜져 있는지, GND가 연결되어 있는지 확인하세요.
- 센서 값이 항상 0 또는 400이에요
- Trig와 Echo가 바뀌어 꽂혀 있거나, 센서가 부드럽거나 비스듬한 물체를 향하고 있을 수 있어요.
- 로봇이 제자리에서 빙빙 돌아요
- 한쪽 모터가 다른 쪽보다 빨라서예요. drive()에서 빠른 쪽의 속도를 조금 낮추세요.
- 앞으로 가야 하는데 뒤로 가요
- 드라이버에서 그 모터의 두 선을 서로 바꿔 꽂으세요.
건전지를 연결하기 전에 안전 섹션을 확인하세요. 안전과 자주 생기는 문제 보기.