전방향 옴니 휠 로봇: 안전한 사람 추적 및 인사하기
부품 및 소모품
| 부품 | 수량 | 비고 |
| L298N 듀얼 스테퍼 모터 드라이버 | 2 | 모터 3개 제어용 (각 드라이버 2채널) |
| LM2596 DC-DC 강압 컨버터 | 1 | 12V 배터리 → 5V 레일 변환 |
| 리포 배터리 저전압 알람 | 1 | 배터리 과방전 방지 |
| 24RPM 12V 기어드 모터 (4mm 축) | 3 | 옴니 휠 3개 구동 |
| Arduino Nano R3 | 1 | 모터 제어 전담 |
| Microsoft LifeCam HD-3000 웹캠 | 1 | 얼굴 검출용 (타 웹캠 가능) |
| 점퍼 와이어 | 10+ | 전원/신호 배선용 |
| Creator Ci20 보드 | 1 | OpenCV 얼굴 검출 처리 (메인 브레인) |
| 11.1V 3셀 리포 배터리 | 1 | 전체 시스템 전원 |
필요 도구
- 3D 프린터 (차체 및 휠 출력용)
- 납땜 인두
소프트웨어
- OpenCV (Ci20 리눅스 환경에서 빌드/실행)
프로젝트 소개
"Hackster Terminate the Competition" 대회 출품작으로, 터미네이터처럼 사람을 찾아다니지만 해코지가 아닌 칭찬을 하는 로봇입니다. 이 옴니-방향(전방향) 로봇은 사람을 찾아내고, 얼굴을 감지해 다가가며, 가까이 오면 칭찬 멘트를 재생합니다.
설계 원칙
- 직접 제작 전자회로 없음: 모든 전자 부품은 기성품 모듈 구매 후 튜토리얼 따라 조립
- 3D 프린팅 차체: 직접 출력하거나 3D Hubs 등 출력 대행 이용
- 모듈형 구조: 전원부 / Ci20(두뇌) / 아두이노(모터 제어) 명확히 분리
시스템 구조도
네 가지 주요 블록으로 구성:
- 전원부: 리포 배터리 → 강압 컨버터(LM2596) → 5V 레일 / 12V 모터 직결 / 저전압 알람
- Ci20 (두뇌): 웹캠으로 OpenCV 얼굴 검출 → 시리얼로 아두이노에 이동 명령 전송
- 아두이노 나노: Ci20 명령 수신 → L298N 드라이버 2개로 3개 모터 제어 (전방향 이동)
- 기계부: 3D 프린팅 옴니 휠 3개 + 기어드 모터 3개로 전방향 이동 구현
전원부 배선
배터리 → 저전압 알람 → LM2596 입력. LM2596 출력은 5V로 조정해 Ci20, 아두이노, 웹캠, 로직 회로에 공급. 모터 드라이버는 배터리 12V 직결.
아두이노 ↔ L298N 연결
인스트럭터블 튜토리얼 참조. 3개 모터 제어를 위해 L298N 2개 사용 (총 4채널 중 3채널 사용).
3D 프린팅 차체
- 상/하판, 옴니 휠 3개, 모터 마운트 등 모두 3D 프린팅
- Ci20이 잘 보이도록 상판 디자인 (대회 취지 반영)
- M4 볼트로 모터 고정
- STL 파일: 프로젝트 페이지 'Custom Parts' 섹션에서 다운로드
Ci20에서 OpenCV 얼굴 검출 실행
- OpenCV 설치: 공식 리눅스 빌드 가이드 따라 빌드
- 얼굴 검출 코드 컴파일/실행:
g++ -I/usr/local/include/opencv -I/usr/local/include/opencv2 \
-L/usr/local/lib/ -g -o FaceTracking main.cpp \
-lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml \
-lopencv_video -lopencv_features2d -lopencv_calib3d \
-lopencv_objdetect -lopencv_contrib -lopencv_legacy -lopencv_stitching
- 실행 시 웹캠 영상 창 뜨고, 얼굴 중앙에 오면 로봇 전진 명령 전송
Ci20 ↔ 아두이노 통신 프로토콜
- USB 시리얼 연결 (/dev/ttyUSB0, 9600 bps)
- 명령 형식: `F X Y` (전방향 이동 벡터), `R 시간` (제자리 회전)
- 얼굴이 화면 중앙 1/3 영역에 있으면 `F 50 50` 전송, 없으면 `0 0` 전송
아두이노 코드 (모터 제어)
메인 스케치
// 모터 3개 핀 정의 (각각 DIR1, DIR2, PWM)
int dir1PinA=3, dir2PinA=2, speedPinA=9;
int dir1PinB=4, dir2PinB=5, speedPinB=8;
int dir1PinC=6, dir2PinC=7, speedPinC=10;
String rpiString;
int x=0, y=0;
unsigned long startTime=0;
void setup() {
Serial.begin(9600);
// 모든 핀 OUTPUT 설정...
startTime = millis();
}
void loop() {
readDataFromRPi();
// 수신 명령으로 모터 제어
if (rpiString.length() > 0) {
// 파싱: "F 50 50" 또는 "R 1000"
// driveInDirection(x,y) 또는 rotate(ms) 호출
}
delay(30);
}
// 시리얼 수신 파싱 로직...
모터 제어 라이브러리 (전방향 이동 수학)
void driveInDirection(float newX, float newY) {
// 옴니 휠 3개(120도 배치) 역기구학 계산
float theta = atan2(newY, newX);
float mag = sqrt(newX*newX + newY*newY);
float vx = mag * cos(theta);
float vy = mag * sin(theta);
// 각 휠 속도 계산
float w1 = -vx;
float w2 = 0.5*vx - sqrt(3)/2*vy;
float w3 = 0.5*vx + sqrt(3)/2*vy;
// 최대값으로 정규화 (150 스케일 → 0~255 PWM 매핑)
// 방향(CW/CCW) 결정 후 analogWrite/digitalWrite로 구동
}
void rotate(float ms) {
// 3개 휠 동일 속도/방향으로 제자리 회전
// ms 밀리초 후 정지
}
Ci20용 C++ 얼굴 검출 코드 (핵심)
#include "opencv2/objdetect.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include
#include , , // 시리얼 통신용
CascadeClassifier face_cascade;
VideoCapture cap(0);
int sendSerial(char* msg) {
int fd = open("/dev/ttyUSB0", O_RDWR);
// termios 설정 (9600 8N1)
write(fd, msg, strlen(msg));
return 0;
}
void detectFaces(Mat frame) {
vector faces;
cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
equalizeHist(frame_gray, frame_gray);
face_cascade.detectMultiScale(frame_gray, faces, 1.1, 3, 0|CASCADE_SCALE_IMAGE, Size(30,30));
for (each face) {
Point center(face.x+face.width/2, face.y+face.height/2);
ellipse(frame, center, Size(face.width/2, face.height/2), 0, 0, 360, Scalar(255,0,255), 4);
// 얼굴이 화면 중앙 1/3 영역에 있으면 전진 명령
if (center.x > frame.cols/3 && center.x < frame.cols*2/3) {
sendSerial("F 50 50");
} else {
sendSerial("0 0");
}
}
imshow("Face Detection", frame);
}
int main() {
sendSerial("0 0");
cap.set(CAP_PROP_FRAME_WIDTH, 480);
cap.set(CAP_PROP_FRAME_HEIGHT, 240);
face_cascade.load("haarcascade_frontalface_default.xml");
Mat frame;
while (cap.read(frame)) {
detectFaces(frame);
if (waitKey(30) >= 0) break;
}
return 0;
}
향후 개선 과제 (챌린지)
- 스피커 + 사운드 파일 추가: 얼굴 충분히 가까우면 칭찬 멘트 재생
- 얼굴 미검출 시 1~2분 후 제자리 회전(`R XX` 명령)으로 탐색 모드 진입
- 배터리 잔량 모니터링 및 자동 충전 스테이션 귀환
커스텀 파츠 (3D 프린팅)
- 로봇 베이스 (하판/상판)
- 옴니 휠 (Thingiverse 리믹스 버전, 모터 축 결합부 포함)
- 모터 마운트 및 커넥터
회로도
프로젝트 페이지 'Schematics' 섹션에서 시스템 전체 배선도 확인.