로봇에게 앞을 보는 감각이 생긴다
모터가 로봇의 근육이라면 센서는 로봇의 감각기관이다. 앞에 벽이 있는지, 책상 끝이 가까워지는지, 사람 손이 다가오는지 알 수 있어야 로봇은 단순히 움직이는 장난감에서 스스로 반응하는 기계로 바뀐다.
거리 센서는 그중에서도 가장 먼저 다뤄볼 만한 센서다. 바퀴 로봇이 앞으로 달리다가 장애물을 만나면 멈추고, 로봇팔이 물체 가까이에서 속도를 줄이며, 작은 이동 로봇이 벽을 따라 주행할 수 있게 해준다. 카메라처럼 복잡한 영상 처리를 하지 않아도, 숫자 하나만으로 주변 상황을 판단할 수 있다는 점도 큰 장점이다.
거리 센서가 알려주는 값은 보통 이런 형태다.
앞쪽 장애물까지의 거리: 37 cm이 숫자 하나만 있어도 로봇은 다음과 같은 판단을 할 수 있다.
50cm보다 멀면 계속 전진한다.
20cm보다 가까우면 멈춘다.
왼쪽보다 오른쪽 거리가 더 넓으면 오른쪽으로 돈다.
이번 장에서는 로봇 제작에서 자주 쓰는 세 가지 거리 센서를 다룬다. 초음파 거리 센서, 적외선 거리 센서, ToF 거리 센서다. 모두 거리를 측정하지만 원리와 성격이 다르다. 어떤 센서는 싸고 다루기 쉽고, 어떤 센서는 빠르고 안정적이며, 어떤 센서는 주변 환경에 민감하다. 좋은 로봇을 만들려면 센서값을 읽는 것뿐 아니라, 그 숫자를 얼마나 믿어도 되는지 판단할 수 있어야 한다.

초음파 거리 센서의 원리
초음파 거리 센서는 이름 그대로 사람이 듣기 어려운 높은 주파수의 소리를 사용한다. 센서가 앞쪽으로 짧은 초음파를 쏘고, 그 소리가 물체에 부딪혀 다시 돌아오는 시간을 측정한다. 소리가 빨리 돌아오면 가까운 곳에 물체가 있고, 늦게 돌아오면 멀리 있는 것이다.
박쥐가 어두운 동굴에서 날아다니는 방식을 떠올리면 쉽다. 박쥐는 소리를 내고, 돌아오는 메아리를 듣고, 주변의 형태를 파악한다. 초음파 거리 센서도 같은 방식으로 거리를 계산한다.
가장 흔히 볼 수 있는 초음파 센서는 HC-SR04 계열이다. 보통 네 개의 핀이 있다.
| 핀 | 역할 |
|---|---|
| VCC | 센서 전원 |
| Trig | 초음파를 쏘라는 시작 신호 입력 |
| Echo | 돌아온 초음파 시간을 펄스 길이로 출력 |
| GND | 기준 전압, 접지 |
동작 흐름은 단순하다. 제어 보드가 Trig 핀에 아주 짧은 신호를 보낸다. 그러면 센서는 초음파를 발사한다. 초음파가 물체에 부딪혀 돌아오면 Echo 핀에서 일정 시간 동안 HIGH 신호가 나온다. 이 HIGH 시간이 바로 소리가 왕복한 시간이다.
거리 계산식은 다음과 같다.
거리 = 소리가 이동한 시간 × 소리의 속도 ÷ 2왜 2로 나눌까? 센서에서 물체까지 한 번 간 시간이 아니라, 물체에 부딪혀 다시 센서로 돌아온 왕복 시간을 측정하기 때문이다.
상온에서 소리의 속도는 대략 초속 343m 정도로 볼 수 있다. 이를 마이크로초와 센티미터 단위로 바꾸면 다음처럼 자주 사용한다.
거리 cm = Echo 시간 us × 0.0343 ÷ 2예를 들어 Echo 시간이 2000마이크로초라면 다음과 같이 계산한다.
거리 = 2000 × 0.0343 ÷ 2 = 34.3 cm즉, 초음파가 왕복하는 데 2밀리초가 걸렸다면 물체는 약 34cm 앞에 있다는 뜻이다.
초음파 센서 연결하기
아두이노 우노에서는 HC-SR04를 비교적 쉽게 연결할 수 있다. 센서 VCC를 5V에 연결하고, GND를 GND에 연결한다. Trig와 Echo는 디지털 핀에 연결한다.
| HC-SR04 | 아두이노 우노 예시 |
|---|---|
| VCC | 5V |
| GND | GND |
| Trig | D9 |
| Echo | D10 |
ESP32에 연결할 때는 조금 더 조심해야 한다. ESP32의 GPIO는 보통 3.3V 신호를 사용한다. 그런데 HC-SR04의 Echo 핀은 5V HIGH를 출력하는 모듈이 많다. 이 5V 신호를 ESP32 입력 핀에 바로 넣으면 보드가 손상될 수 있다. 따라서 Echo 신호는 저항 두 개로 전압을 낮추는 전압 분배 회로를 거치거나, 3.3V 호환 초음파 센서 모듈을 사용하는 편이 안전하다.
초음파 센서를 처음 연결할 때 가장 중요한 것은 역시 공통 GND다. 센서 전원과 제어 보드의 GND가 이어져 있어야 Trig와 Echo 신호의 기준이 같아진다. 전원은 연결했는데 값이 계속 이상하다면, 가장 먼저 GND가 제대로 연결되어 있는지 확인해야 한다.
초음파 거리 측정 코드
다음 코드는 Trig 핀으로 초음파 발사 신호를 보내고, Echo 핀의 HIGH 시간을 측정한 뒤 센티미터 단위 거리로 바꾼다.
const int TRIG_PIN = 9;
const int ECHO_PIN = 10;
void setup() {
Serial.begin(115200);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
}
void loop() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH, 30000);
if (duration == 0) {
Serial.println(-1);
} else {
float distanceCm = duration * 0.0343 / 2.0;
Serial.println(distanceCm);
}
delay(100);
}pulseIn 함수는 입력 핀이 특정 상태를 유지한 시간을 마이크로초 단위로 측정한다. 여기서는 Echo 핀이 HIGH인 시간을 측정한다. 세 번째 인자인 30000은 최대 대기 시간이다. 약 30밀리초 동안 신호가 돌아오지 않으면 측정을 포기한다. 이렇게 제한을 두지 않으면 장애물이 없을 때 코드가 오래 멈춰 있는 것처럼 보일 수 있다.
값이 정상적으로 들어오면 시리얼 모니터에 10, 25, 80 같은 숫자가 출력된다. 손을 센서 앞에 가까이 가져가면 값이 작아지고, 멀리하면 값이 커진다. 바로 이 순간 로봇은 앞쪽 공간을 숫자로 느끼기 시작한다.
초음파 센서가 틀리는 순간
초음파 센서는 싸고 사용하기 쉽지만 만능은 아니다. 실제 로봇에 달아보면 값이 갑자기 튀거나, 앞에 물체가 있는데도 못 보는 경우가 있다. 고장이라기보다 초음파라는 방식의 특성 때문이다.
먼저 너무 가까운 물체는 잘 측정하지 못한다. 센서가 초음파를 쏘고 바로 수신 준비를 해야 하는데, 물체가 지나치게 가까우면 반사파가 너무 빨리 돌아온다. 많은 초음파 센서는 대략 몇 cm 이내에서 값이 불안정하다.
비스듬한 벽도 문제가 된다. 초음파는 공처럼 튕겨 나간다. 정면 벽에 부딪히면 센서 쪽으로 돌아오지만, 비스듬한 표면에 부딪히면 옆으로 반사되어 돌아오지 않을 수 있다. 부드러운 천, 스펀지, 커튼처럼 소리를 흡수하는 물체도 감지하기 어렵다.
또 하나 중요한 점은 초음파 센서의 시야가 카메라처럼 네모난 화면이 아니라는 것이다. 초음파는 원뿔 모양으로 퍼져 나간다. 그래서 센서 정중앙이 아닌 옆쪽 장애물을 감지할 수도 있고, 작은 물체는 빔 사이에서 놓칠 수도 있다.
로봇을 만들 때는 이 특성을 받아들여야 한다. 센서값 하나를 절대적인 진실로 믿기보다, 여러 번 측정하고 이상한 값을 걸러내고, 필요한 경우 센서를 여러 방향에 배치하는 방식으로 안정성을 높인다.
적외선 거리 센서의 원리
적외선 거리 센서는 눈에 보이지 않는 적외선 빛을 사용한다. 센서에서 적외선을 내보내고, 물체에 반사되어 돌아오는 빛을 감지한다. 가까운 물체는 강하게 반사되고, 멀리 있는 물체는 약하게 반사된다. 일부 센서는 반사된 빛의 위치 변화를 이용해 거리를 추정하기도 한다.
적외선 거리 센서는 초음파 센서보다 빠르게 반응하는 경우가 많고, 작은 물체에도 비교적 민감하다. 그래서 라인트레이서, 벽 감지 로봇, 손 감지 장치 등에 자주 쓰인다. 하지만 빛을 사용하는 만큼 물체의 색상, 표면 재질, 주변 조명에 영향을 받는다.
검은색 종이는 빛을 많이 흡수한다. 흰색 종이는 빛을 많이 반사한다. 거울처럼 반짝이는 표면은 빛을 엉뚱한 방향으로 튕겨 보낼 수 있다. 햇빛이나 강한 조명에는 적외선 성분이 포함되어 있어 센서가 혼란스러워질 수도 있다.
따라서 적외선 거리 센서를 사용할 때는 단순히 데이터시트의 측정 범위만 믿으면 안 된다. 내 로봇이 실제로 달릴 바닥, 벽, 물체에서 어떻게 반응하는지 직접 확인해야 한다.
적외선 센서 오차 실험
적외선 거리 센서를 제대로 이해하는 가장 좋은 방법은 일부러 곤란한 상황을 만들어보는 것이다. 실험은 간단하다. 센서를 고정하고, 같은 거리에서 서로 다른 물체를 앞에 둔 뒤 값을 비교한다.
다음 조건을 바꿔가며 측정해보자.
흰 종이, 검은 종이, 회색 박스처럼 색상이 다른 물체
무광 플라스틱, 금속 캔, 투명 아크릴처럼 표면 재질이 다른 물체
정면, 30도 기울어진 면, 45도 기울어진 면처럼 각도가 다른 물체
실내 조명, 책상 스탠드, 창가 햇빛처럼 주변광이 다른 환경
센서가 아날로그 값을 출력한다면 아두이노의 analogRead로 값을 읽을 수 있다. 아날로그 거리 센서의 출력은 대개 거리와 완벽한 직선 관계가 아니다. 가까워질수록 값이 커지다가 특정 구간에서 급격히 변하고, 먼 거리에서는 변화가 둔해질 수 있다.
const int IR_PIN = A0;
void setup() {
Serial.begin(115200);
}
void loop() {
int value = analogRead(IR_PIN);
Serial.println(value);
delay(100);
}센서 앞에 흰 종이를 10cm, 20cm, 30cm 간격으로 놓고 값을 기록해보자. 그다음 같은 거리에 검은 종이를 놓고 다시 기록한다. 두 표를 비교하면 적외선 센서가 색상과 반사율에 얼마나 영향을 받는지 금방 알 수 있다.
| 거리 | 흰 종이 측정값 | 검은 종이 측정값 |
|---|---|---|
| 10cm | 직접 기록 | 직접 기록 |
| 20cm | 직접 기록 | 직접 기록 |
| 30cm | 직접 기록 | 직접 기록 |
이 실험을 해보면 거리 센서가 단순히 물리적인 거리만 보는 것이 아니라는 사실을 체감하게 된다. 센서는 언제나 자기 방식으로 세상을 본다. 로봇 제작자는 그 방식의 장단점을 알고 있어야 한다.
적외선 장애물 센서와 거리 센서의 차이
작은 로봇 키트에는 적외선 장애물 감지 센서가 자주 들어 있다. 이 센서는 보통 가변저항이 달려 있고, 물체가 가까이 오면 디지털 출력이 HIGH 또는 LOW로 바뀐다. 사용하기는 쉽지만 정확한 거리값을 알려주는 센서라고 보기는 어렵다.
장애물 감지 센서는 질문이 단순하다.
앞에 물체가 있는가, 없는가?반면 거리 센서는 조금 더 구체적인 질문에 답한다.
앞의 물체가 몇 cm 떨어져 있는가?장애물 회피 로봇을 아주 단순하게 만들 때는 디지털 장애물 센서도 충분하다. 하지만 가까워질수록 속도를 줄이거나, 벽과 15cm 거리를 유지하며 이동하거나, 로봇팔이 물체 앞에서 부드럽게 멈추게 하려면 거리값이 필요하다.
즉, 디지털 적외선 센서는 스위치처럼 쓰고, 아날로그 또는 거리 계산형 센서는 자처럼 쓴다고 생각하면 쉽다.
ToF 센서의 원리
ToF는 Time of Flight의 줄임말이다. 우리말로 하면 비행 시간 방식이다. ToF 거리 센서는 빛을 쏘고, 그 빛이 물체에 반사되어 돌아오는 데 걸린 시간을 이용해 거리를 측정한다.
초음파 센서가 소리의 왕복 시간을 잰다면, ToF 센서는 빛의 왕복 시간을 재는 셈이다. 빛은 소리보다 훨씬 빠르기 때문에 측정이 매우 어렵지만, ToF 센서 모듈 안에는 이 짧은 시간을 처리하기 위한 회로와 알고리즘이 들어 있다. 사용자는 보통 I2C 통신으로 거리값만 읽으면 된다.
대표적인 소형 ToF 센서 모듈은 VL53L0X, VL53L1X 계열이다. 이런 센서는 적외선 레이저 또는 적외선 광원을 사용하고, 반사되어 돌아온 신호를 분석해 거리값을 제공한다. 센서 내부에서 많은 계산을 처리해주기 때문에, 제어 보드 입장에서는 비교적 안정적인 숫자를 받는 느낌에 가깝다.
ToF 센서는 초음파 센서보다 크기가 작고, 측정 각도가 비교적 좁은 편이며, 가까운 거리에서 반응이 좋다. 또 소리를 쓰지 않기 때문에 부드러운 천이나 비스듬한 표면에서 초음파와 다른 결과를 보여준다. 다만 ToF도 완벽하지는 않다. 아주 검은 표면, 반짝이는 표면, 투명한 물체, 강한 외부 광원에서는 값이 흔들릴 수 있다.
ToF 센서 연결하기
대부분의 소형 ToF 모듈은 I2C 통신을 사용한다. I2C는 두 개의 신호선만으로 여러 센서를 연결할 수 있는 통신 방식이다. 자세한 내용은 뒤에서 따로 다루지만, 지금은 SDA와 SCL 두 선을 통해 보드와 센서가 데이터를 주고받는다고 이해하면 충분하다.
| ToF 모듈 핀 | 역할 |
|---|---|
| VIN 또는 VCC | 전원 입력 |
| GND | 접지 |
| SDA | I2C 데이터 선 |
| SCL | I2C 클록 선 |
아두이노 우노에서는 보통 A4가 SDA, A5가 SCL이다. ESP32에서는 보드 설정에 따라 다르지만 흔히 GPIO 21을 SDA, GPIO 22를 SCL로 사용한다. 모듈에 따라 3.3V 전용인 경우도 있고, 전압 변환 회로가 들어 있어 5V 보드와 함께 사용할 수 있는 경우도 있다. 연결 전에 모듈의 전원 전압을 꼭 확인해야 한다.
ToF 센서는 라이브러리를 사용하면 비교적 쉽게 값을 읽을 수 있다. 라이브러리마다 코드 형태는 조금씩 다르지만 흐름은 비슷하다.
#include <Wire.h>
void setup() {
Serial.begin(115200);
Wire.begin();
// 센서 초기화
}
void loop() {
// 센서에서 거리 읽기
// mm 단위 값을 cm로 바꾸어 출력
delay(50);
}처음에는 라이브러리 예제를 그대로 실행해 센서가 정상적으로 인식되는지 확인하는 것이 좋다. I2C 센서는 배선이 하나만 잘못되어도 전혀 응답하지 않는다. 값이 나오지 않으면 전원, GND, SDA, SCL 순서로 차분히 확인하자.
세 거리 센서 비교하기
초음파, 적외선, ToF는 모두 거리를 측정하지만 잘하는 일이 조금씩 다르다. 어떤 센서가 최고라고 말하기보다, 로봇의 목적과 환경에 맞는 센서를 고르는 것이 중요하다.
| 센서 종류 | 장점 | 주의할 점 | 어울리는 용도 |
|---|---|---|---|
| 초음파 센서 | 저렴하고 원리가 직관적이며 긴 거리 측정에 유리 | 비스듬한 표면, 천, 좁은 물체에 약함 | 기본 장애물 회피, 전방 거리 측정 |
| 적외선 거리 센서 | 반응이 빠르고 작은 물체 감지에 유리 | 색상, 반사율, 주변광에 민감 | 근거리 감지, 벽 감지, 손 감지 |
| ToF 센서 | 작고 값이 비교적 안정적이며 I2C로 읽기 쉬움 | 투명체, 검은 물체, 강한 빛에서 오차 가능 | 소형 로봇, 정밀 근거리 측정, 다중 센서 구성 |
예를 들어 넓은 방에서 앞쪽 벽을 감지하며 달리는 간단한 자동차라면 초음파 센서 하나로 시작해도 좋다. 책상 위에서 작은 물체와의 거리를 빠르게 감지해야 한다면 적외선 센서가 편할 수 있다. 작고 깔끔한 로봇에 여러 방향 거리 센서를 달고 싶다면 ToF 센서가 좋은 선택이 된다.
실전에서는 센서를 섞어 쓰기도 한다. 초음파 센서로 큰 장애물을 보고, 적외선 센서로 가까운 바닥이나 벽을 감지하고, ToF 센서로 짧은 거리의 정밀한 값을 읽는 식이다. 로봇은 하나의 감각만으로 세상을 이해하기 어렵다. 여러 감각을 조합할수록 더 튼튼한 판단을 할 수 있다.
센서값은 왜 흔들릴까
시리얼 모니터에 거리값을 출력해보면 한 가지 이상한 점을 발견한다. 센서와 물체를 가만히 두었는데도 값이 완전히 고정되지 않는다.
29.8
30.1
30.0
31.4
29.9
30.2물체는 움직이지 않았는데 숫자는 조금씩 흔들린다. 이것은 자연스러운 현상이다. 전기적 노이즈, 센서 내부 계산 오차, 표면 반사 상태, 주변 빛, 공기 흐름, 전원 상태 등 여러 요인이 측정값에 영향을 준다.
로봇 제어에서 중요한 것은 센서값이 조금 흔들린다는 사실 자체가 아니다. 흔들리는 값을 그대로 믿고 모터를 제어하면 로봇도 같이 흔들린다는 점이 문제다.
예를 들어 장애물이 20cm보다 가까우면 멈추도록 만들었다고 해보자. 실제 거리가 거의 20cm 근처라면 센서값이 19.8, 20.2, 19.9, 20.1처럼 왔다 갔다 할 수 있다. 그러면 로봇은 멈췄다 출발했다를 빠르게 반복한다. 사람이 보면 로봇이 망설이며 떨고 있는 것처럼 보인다.
이 문제를 줄이기 위해 센서값을 안정화하는 방법을 사용한다. 대표적인 방법이 평균 필터, 중앙값 필터, 임계값 조정이다.
평균 필터로 부드럽게 만들기
평균 필터는 여러 번 측정한 값을 더한 뒤 개수로 나누는 방법이다. 예를 들어 거리값을 다섯 번 읽어 평균을 내면 순간적으로 튀는 값의 영향이 줄어든다.
float readDistanceAverage() {
float sum = 0;
int count = 5;
for (int i = 0; i < count; i++) {
float d = readDistanceCm();
sum += d;
delay(10);
}
return sum / count;
}평균 필터는 이해하기 쉽고 구현도 간단하다. 센서값이 조금씩 흔들릴 때 효과가 좋다. 하지만 단점도 있다. 측정 횟수를 많이 늘리면 반응이 느려진다. 로봇이 빠르게 달리고 있는데 센서값을 열 번, 스무 번 읽느라 시간을 쓰면 장애물에 늦게 반응할 수 있다.
또 하나의 문제는 아주 크게 튀는 값이다. 대부분 30cm 근처인데 한 번 200cm가 들어오면 평균값이 끌려 올라간다. 이럴 때는 중앙값 필터가 더 좋은 선택이 될 수 있다.
중앙값 필터로 튀는 값 걸러내기
중앙값 필터는 여러 측정값을 크기순으로 정렬한 뒤 가운데 값을 선택한다. 예를 들어 다음 다섯 개 값이 있다고 하자.
30, 31, 200, 29, 30크기순으로 정렬하면 다음과 같다.
29, 30, 30, 31, 200가운데 값은 30이다. 200이라는 이상한 값이 하나 섞여 있어도 결과는 크게 흔들리지 않는다. 그래서 중앙값 필터는 초음파 센서처럼 가끔 엉뚱한 값이 튀는 센서에 특히 유용하다.
간단한 중앙값 필터 코드는 다음과 같이 만들 수 있다.
float median5(float a, float b, float c, float d, float e) {
float values[5] = {a, b, c, d, e};
for (int i = 0; i < 4; i++) {
for (int j = i + 1; j < 5; j++) {
if (values[j] < values[i]) {
float temp = values[i];
values[i] = values[j];
values[j] = temp;
}
}
}
return values[2];
}실제 프로젝트에서는 거리값을 다섯 번 읽고 median5 함수에 넣으면 된다. 측정값이 매우 빠르게 필요하지 않은 장애물 회피 로봇이라면 다섯 번 정도의 중앙값 필터만으로도 움직임이 훨씬 차분해진다.
임계값과 히스테리시스
필터를 적용해도 로봇이 경계선 근처에서 덜덜 떨 수 있다. 이때는 임계값을 하나만 쓰지 말고 두 개로 나누는 방법이 효과적이다. 이를 히스테리시스라고 한다. 이름은 조금 어렵지만 원리는 쉽다.
로봇이 전진 중일 때는 18cm보다 가까워지면 멈춘다. 하지만 멈춘 뒤에는 거리가 25cm보다 멀어져야 다시 출발한다.
전진 중: 18cm 미만이면 정지
정지 중: 25cm 초과이면 다시 전진멈추는 기준과 다시 출발하는 기준 사이에 여유 공간을 두는 것이다. 그러면 센서값이 19cm, 20cm 근처에서 조금 흔들려도 로봇이 계속 켜졌다 꺼졌다 하지 않는다.
bool stopped = false;
void updateRobot(float distanceCm) {
if (!stopped && distanceCm < 18) {
stopMotors();
stopped = true;
}
if (stopped && distanceCm > 25) {
moveForward();
stopped = false;
}
}이 방식은 거리 센서뿐 아니라 온도 제어, 배터리 경고, 라인트레이서 판단에도 자주 쓰인다. 로봇이 안정적으로 행동하게 만드는 작은 요령이다.
가까워지면 멈추는 로봇 판단 만들기
이제 거리값을 실제 행동으로 연결해보자. 모터 드라이버와 DC 모터를 이미 연결해두었다고 가정하자. 로봇의 전방에 거리 센서를 달고, 센서값에 따라 전진 또는 정지를 결정한다.
가장 단순한 판단은 다음과 같다.
거리값이 유효하지 않으면 정지한다.
거리값이 20cm보다 작으면 정지한다.
그렇지 않으면 전진한다.여기서 유효하지 않은 값도 중요하다. 초음파 센서에서 duration이 0이거나, ToF 센서에서 측정 실패가 나왔거나, 적외선 센서 값이 말이 안 되는 범위에 있다면 어떻게 해야 할까? 안전한 선택은 일단 멈추는 것이다. 로봇이 앞을 못 보는 상태에서 계속 달리는 것보다, 잠시 멈추는 쪽이 낫다.
void loop() {
float distanceCm = readDistanceCm();
if (distanceCm < 0) {
stopMotors();
return;
}
if (distanceCm < 20) {
stopMotors();
} else {
moveForward();
}
delay(50);
}처음에는 이 정도만으로도 충분하다. 로봇을 바닥에 놓고 손을 앞에 가져가 보자. 손이 멀리 있으면 앞으로 가고, 가까워지면 멈춘다. 아주 단순하지만 중요한 순간이다. 이제 로봇은 명령받은 대로만 움직이는 장치가 아니라, 자기 앞의 상황에 반응하는 장치가 되었다.
그다음에는 조금씩 개선할 수 있다. 거리값이 50cm 이상이면 빠르게 달리고, 20cm에서 50cm 사이면 천천히 가고, 20cm 이하에서는 멈추게 만들 수 있다. 이때 앞에서 배운 PWM 속도 제어가 다시 등장한다. 센서는 현재 상황을 알려주고, PWM은 모터 출력을 조절한다. 감각과 근육이 연결되는 것이다.
거리 50cm 이상: 속도 180
거리 20cm 이상 50cm 미만: 속도 90
거리 20cm 미만: 정지이 간단한 규칙만으로도 로봇의 움직임은 훨씬 자연스러워진다. 장애물을 보고 급정거하는 대신 가까워질수록 속도를 줄이는 로봇이 된다.
센서 배치도 성능이다
같은 센서라도 어디에 어떻게 달았는지에 따라 로봇의 성능이 크게 달라진다. 센서를 너무 낮게 달면 바닥의 작은 요철이나 카펫을 장애물로 오해할 수 있다. 너무 높게 달면 낮은 장애물을 보지 못한다. 바퀴 로봇이라면 센서를 로봇이 실제로 부딪힐 높이에 맞춰 다는 것이 좋다.
초음파 센서는 앞쪽이 막히지 않도록 배치해야 한다. 프레임이나 배터리 케이스가 센서 앞을 조금이라도 가리면 이상한 반사가 생길 수 있다. ToF와 적외선 센서도 마찬가지다. 투명 커버를 씌우면 빛이 반사되어 오차가 커질 수 있다.
여러 개의 초음파 센서를 동시에 사용할 때는 서로 간섭할 수 있다. 한 센서가 쏜 초음파를 다른 센서가 받아버리면 잘못된 거리값이 나온다. 이럴 때는 센서들을 동시에 측정하지 말고, 앞쪽 센서 측정 후 잠깐 기다리고, 왼쪽 센서를 측정하고, 다시 기다린 뒤 오른쪽 센서를 측정하는 식으로 순서를 나누면 된다.
로봇 제작에서 배치는 회로도만큼 중요하다. 센서가 세상을 바라보는 위치가 곧 로봇이 세상을 이해하는 방식이 된다.
거리 센서 디버깅 체크리스트
거리 센서가 예상대로 동작하지 않을 때는 무작정 코드를 고치기보다 하나씩 확인하는 편이 빠르다.
전원 전압이 센서 모듈에 맞는지 확인한다.
제어 보드와 센서의 GND가 연결되어 있는지 확인한다.
ESP32 같은 3.3V 보드에 5V Echo 신호를 직접 넣고 있지 않은지 확인한다.
Trig와 Echo, SDA와 SCL처럼 신호선이 서로 바뀌지 않았는지 확인한다.
센서 앞에 너무 가까운 물체를 두고 측정하고 있지 않은지 확인한다.
반짝이는 물체, 검은 물체, 비스듬한 벽에서만 문제가 생기는지 확인한다.
모터가 돌 때만 값이 흔들린다면 전원 노이즈와 배선 상태를 확인한다.
특히 모터가 돌기 시작하는 순간 센서값이 이상해지는 경우가 많다. 모터는 많은 전류를 사용하고 전기적 노이즈도 만든다. 이때 보드 전원과 센서 전원이 흔들리면 거리값도 흔들린다. 이전에 다룬 것처럼 모터 전원과 보드 전원을 적절히 분리하고, GND는 공통으로 묶고, 전원선이 너무 가늘거나 길지 않게 구성하는 것이 중요하다.
센서 문제처럼 보이는 일이 사실은 전원 문제인 경우가 많다. 로봇 하드웨어에서는 이런 일이 아주 흔하다.
거리값에서 행동으로
거리 센서를 배우는 목적은 숫자를 예쁘게 출력하는 데 있지 않다. 그 숫자를 바탕으로 로봇이 더 나은 행동을 하게 만드는 것이 목적이다. 초음파 센서는 소리의 왕복 시간으로 넓은 공간의 장애물을 감지한다. 적외선 센서는 반사된 빛을 이용해 빠르게 근거리 변화를 포착한다. ToF 센서는 빛의 비행 시간을 바탕으로 작고 안정적인 거리값을 제공한다.
하지만 어떤 센서든 값은 흔들린다. 그래서 평균 필터와 중앙값 필터로 값을 다듬고, 임계값과 히스테리시스로 판단을 안정화해야 한다. 이 과정을 거치면 로봇은 조금 더 침착해진다. 앞에 물체가 있다고 갑자기 허둥대지 않고, 거리 변화에 맞춰 부드럽게 반응한다.
이제 로봇은 앞을 볼 수 있다. 다음 단계는 바퀴가 실제로 얼마나 돌았는지 아는 것이다. 거리 센서가 로봇 바깥세상을 보는 감각이라면, 엔코더는 로봇 자신의 움직임을 느끼는 감각이다. 바깥을 보고, 자신을 알고, 그 차이를 줄여가는 순간 로봇 제어는 훨씬 흥미로워진다.
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.