두 발 아두이노 로봇 만들기: 베이비 디노 DIY 가이드
필요한 부품 및 소모품
| 부품 |
수량 |
| 아두이노 메가 2560 (우노/나노도 가능) |
1 |
| 9V 배터리 |
1 |
| HC-SR04 초음파 센서 |
1 |
| SG90 마이크로 서보 모터 |
5 |
프로젝트 소개
베이비 디노는 아두이노 기반의 이족 보행 로봇입니다. 다리당 2개씩 총 4개 서보로 걷고, 머리용 서보 1개가 더 있습니다. 초음파 센서로 장애물을 감지해 피합니다. 제작 과정을 살펴보겠습니다.
1단계: 소개
- 아두이노 기반 DIY 로봇
- 골판지로 제작
- 장애물 발견 시 좌/우로 회피
2단계: 필요한 부품
- 아두이노 우노, 나노, 메가 중 1개
- 9g 서보 5개
- HC-SR04 초음파 센서 1개
- 리포 배터리(2S) 또는 9V 배터리
3단계: 서보 고정 및 보정
- 보정 프로그램(fix.ino) 다운로드 및 업로드
- 회로도대로 서보 연결
- 서보 혼(horn) 장착
- 모든 서보가 90° 위치에 오도록 확인
4단계: 설계 및 골판지 컷팅
- 설계 파일 다운로드
- A4 용지에 출력
- 골판지에 붙여 자르기
5단계: 최종 조립
- 서보를 골판지에 부착
- 메인 프로그램(uBipedino.ino) 업로드
- 서보와 초음파 센서 연결
- 케이블을 꼬리처럼 정리
- 배터리 연결
이것으로 완성입니다!
코드
fix.ino – 서보 보정용 (Arduino)
#include
Servo s1; Servo s2; Servo s3; Servo s4; Servo s5;
void setup() {
s1.attach(8); s2.attach(9); s3.attach(10); s4.attach(11); s5.attach(12);
}
void loop() {
s1.write(90); s2.write(90); s3.write(90); s4.write(90); s5.write(90);
}
biped – 메인 보행 및 회피 코드 (Arduino)
#include
#include
// 핀 설정 (자신의 연결에 맞게 수정)
#define IRsensorPin 13 // 초음파 대신 IR 센서 사용 시
#define TRIGGER_PIN 12 // 초음파 트리거 핀
#define ECHO_PIN 11 // 초음파 에코 핀
#define LEFTLEG 7
#define RIGHTLEG 10
#define LEFTFOOT 8
#define RIGHTFOOT 9
#define HEAD 6
#define MAX_DISTANCE 200 // 최대 측정 거리(cm)
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
Servo Lleg, Rleg, Lfoot, Rfoot, Head;
int Hcenter = 70;
int RLcenter = 100;
int RFcenter = 65;
int LLcenter = 90;
int LFcenter = 75;
int tAngle = 30; // 틸트 각도
int uAngle = 35; // 턴 각도
int sAngle = 35; // 스윙 각도
int hAngle = Hcenter;
// 전진 함수
void Forward(byte Steps, byte Speed) {
Serial.println("Forward");
TiltRightUp(tAngle, Speed);
for (byte j = 0; j < Steps; ++j) {
SwingRight(sAngle, Speed);
TiltRightDown(tAngle, Speed);
TiltLeftUp(tAngle, Speed);
SwingRcenter(sAngle, Speed);
SwingLeft(sAngle, Speed);
TiltLeftDown(tAngle, Speed);
TiltRightUp(tAngle, Speed);
SwingLcenter(sAngle, Speed);
}
TiltRightDown(tAngle, Speed);
}
// 좌회전
void TurnLeft(byte Steps, byte Speed) {
Serial.println("TurnLeft");
TiltLeftUp(uAngle, Speed);
delay(20);
for (byte j = 0; j < Steps; ++j) {
LeftLegIn(sAngle, Speed);
TiltLeftDown(uAngle, Speed);
TiltRightUp(uAngle, Speed);
delay(20);
LeftLegIcenter(sAngle, Speed);
RightLegOut(sAngle, Speed);
TiltRightDown(uAngle, Speed);
TiltLeftUp(uAngle, Speed);
delay(20);
RightLegOcenter(sAngle, Speed);
}
TiltLeftDown(uAngle, Speed);
}
// 우회전
void TurnRight(byte Stps, byte Speed) {
Serial.println("TurnRight");
TiltRightUp(uAngle, Speed);
delay(20);
for (byte f = 0; f <= Stps; ++f) {
RightLegIn(sAngle, Speed);
TiltRightDown(uAngle, Speed);
TiltLeftUp(uAngle, Speed);
delay(20);
RightLegIcenter(sAngle, Speed);
LeftLegOut(sAngle, Speed);
TiltLeftDown(uAngle, Speed);
TiltRightUp(uAngle, Speed);
delay(20);
LeftLegOcenter(sAngle, Speed);
}
TiltRightDown(uAngle, Speed);
}
// 머리 제어
void HeadRight() { Serial.println("HeadRight"); Head.write(Hcenter - 105); delay(1000); }
void HeadLeft() { Serial.println("HeadLeft"); Head.write(Hcenter + 105); delay(1000); }
void HeadCenter(){ Serial.println("HeadCenter"); Head.write(Hcenter); delay(1000); }
// 틸트/스윙/레그 세부 동작 함수들 (생략 가능, 원본 참조)
void TiltRightUp(byte ang, byte sp) { for (int i=0; i<=ang; i+=5){ Lfoot.write(LFcenter+i); Rfoot.write(RFcenter+i); delay(sp); } }
void TiltRightDown(byte ang, byte sp) { for (int i=ang; i>0; i-=5){ Lfoot.write(LFcenter+i); Rfoot.write(RFcenter+i); delay(sp); } }
void TiltLeftUp(byte ang, byte sp) { for (int i=0; i<=ang; i+=5){ Lfoot.write(LFcenter-i); Rfoot.write(RFcenter-i); delay(sp); } }
void TiltLeftDown(byte ang, byte sp) { for (int i=ang; i>0; i-=5){ Lfoot.write(LFcenter-i); Rfoot.write(RFcenter-i); delay(sp); } }
void SwingRight(byte ang, byte sp) { for (int i=0; i<=ang; i+=5){ Lleg.write(LLcenter-i); Rleg.write(RLcenter-i); delay(sp); } }
void SwingRcenter(byte ang, byte sp) { for (int i=ang; i>0; i-=5){ Lleg.write(LLcenter-i); Rleg.write(RLcenter-i); delay(sp); } }
void SwingLeft(byte ang, byte sp) { for (byte i=0; i<=ang; i+=5){ Lleg.write(LLcenter+i); Rleg.write(RLcenter+i); delay(sp); } }
void SwingLcenter(byte ang, byte sp) { for (byte i=ang; i>0; i-=5){ Lleg.write(LLcenter+i); Rleg.write(RLcenter+i); delay(sp); } }
void RightLegIn(byte ang, byte sp) { for (int i=0; i<=ang; i+=5){ Rleg.write(RLcenter-i); delay(sp); } }
void RightLegIcenter(byte ang, byte sp){ for (int i=ang; i>0; i-=5){ Rleg.write(RLcenter-i); delay(sp); } }
void RightLegOut(byte ang, byte sp) { for (int i=0; i<=ang; i+=5){ Rleg.write(RLcenter+i); delay(sp); } }
void RightLegOcenter(byte ang, byte sp){ for (int i=ang; i>0; i-=5){ Rleg.write(RLcenter+i); delay(sp); } }
void LeftLegIn(byte ang, byte sp) { for (byte i=0; i<=ang; i+=5){ Lleg.write(LLcenter+i); delay(sp); } }
void LeftLegIcenter(byte ang, byte sp){ for (byte i=ang; i>0; i-=5){ Lleg.write(LLcenter+i); delay(sp); } }
void LeftLegOut(byte ang, byte sp) { for (byte i=0; i<=ang; i+=5){ Lleg.write(LLcenter-i); delay(sp); } }
void LeftLegOcenter(byte ang, byte sp){ for (byte i=ang; i>0; i-=5){ Lleg.write(LLcenter-i); delay(sp); } }
void setup() {
Serial.begin(19200);
Serial.println("Bipedino setup is running.");
Lleg.attach(LEFTLEG); Rleg.attach(RIGHTLEG);
Lfoot.attach(LEFTFOOT); Rfoot.attach(RIGHTFOOT); Head.attach(HEAD);
CenterServos();
delay(500);
for (int i = 0; i < 5; ++i) { GetSonar(); delay(1000); }
Serial.println("Bipedino is ready.");
}
void loop() {
unsigned int cmCenter = MAX_DISTANCE, cmLeft = MAX_DISTANCE, cmRight = MAX_DISTANCE;
HeadCenter();
cmCenter = GetSonar();
if (cmCenter < 20) {
HeadRight(); cmRight = GetSonar(); HeadCenter();
if (cmRight > 20) { TurnRight(1, 30); }
else {
HeadLeft(); cmLeft = GetSonar(); HeadCenter();
if (cmLeft > 20) { TurnLeft(1, 30); }
}
} else {
int nSteps = cmCenter / 5;
if (nSteps > 5) nSteps = 5;
else nSteps = 1;
Serial.print("Steps <"); Serial.print(nSteps); Serial.println(">");
for (int n = 0; n < nSteps; n++) Forward(1, 30);
}
}
int GetSonar() {
unsigned int uS = sonar.ping();
Serial.print("Ping: "); Serial.print(uS / US_ROUNDTRIP_CM); Serial.println("cm");
return uS / US_ROUNDTRIP_CM;
}
void CenterServos() {
Lleg.write(LLcenter); Rleg.write(RLcenter);
Lfoot.write(LFcenter); Rfoot.write(RFcenter); Head.write(Hcenter);
delay(1000);
}
회로도
페이지 하단의 회로도 이미지 참고.