산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

MobBob: 아두이노 로봇 직접 만들기, 안드로이드 스마트폰으로 매끄럽게 제어

부품 및 소모품

부품 수량
아두이노 나노 R3 1
HC-05 블루투스 모듈 1
SG90 마이크로 서보 모터 4
4xAA 배터리 홀더 1
AA 배터리 4

필수 도구 및 장비

앱 및 온라인 서비스

프로젝트 개요

웹사이트 지침에 따라 이 로봇을 만들었습니다. 아두이노와 안드로이드의 공생을 위한 훌륭한 아이디어입니다.

MobBob은 스마트폰으로 제어되는 로봇입니다. 스마트폰의 성능을 활용해 음성 인식과 컴퓨터 비전을 갖춘 걷고 말하는 로봇이 됩니다.

코드에서 다음을 설정해야 합니다:

코드

코드 (아두이노)

/* 
 * =============================================================
 * MobBob 제어 프로그램 - 소프트웨어 시리얼 블루투스 버전
 * by Kevin Chan (aka Cevinius)
 * =============================================================
 * 
 * 이 프로그램은 시리얼 명령으로 MobBob을 제어합니다. 소프트웨어 시리얼 포트로 명령을 수신하며,
 * 상단의 #define으로 핀을 정의합니다. 모든 아두이노 호환 보드 사용 가능.
 * 
 * 주요 구성 요소: 부드러운 서보 애니메이션 프로그램, 시리얼 명령 파서.
 * 
 * 애니메이션 시스템: 키프레임 배열을 부드럽게 재생. 큐 크기 1 (실행 중 1개, 대기 1개).
 * 명령 파서: 시리얼로 수신한 명령 파싱 및 처리. 직접 서보 제어, 사전 정의 애니메이션/걷기 트리거.
 * 
 * 일반 명령:
 * - 준비/확인: <OK>
 * - 서보 설정: <SV, time, leftHip, leftFoot, rightHip, rightFoot>
 * - 정지/리셋: <ST>
 * - 즉시 정지: <SI>
 * 
 * 기본 걷기 명령:
 * - 전진: <FW, #Times>, -1=연속, 0/생략=1회
 * - 후진: <BW, #Times>
 * - 좌회전: <LT, #Times>
 * - 우회전: <RT, #Times>
 * 
 * 재미 애니메이션:
 * - 머리 흔들기: <SX, #Times>
 * - 바운스: <BX, #Times>
 * - 흔들기: <WX, #Times>, 좌/우: <WY>, <WZ>
 * - 발 탭: <TX, #Times>, 좌/우: <TY>, <TZ>
 * - 다리 흔들기: <LX, #Times>, 좌/우: <LY>, <LZ>
 * 
 * 명령 완료 시 응답 문자열 전송. 정상 완료: <FW>, 중단 시: <FW,-1>
 */

#include <Servo.h>
#include <SoftwareSerial.h>

//----------------------------------------------------------------------------------
// 시리얼 통신 속도 - 블루투스 카드에 맞게 설정
//----------------------------------------------------------------------------------
#define SERIAL_SPEED 115200
const int rxPin = 11;
const int txPin = 12;
SoftwareSerial softwareSerial(rxPin, txPin);

//----------------------------------------------------------------------------------
// 아두이노 핀 설정 - 로봇에 맞게 변경
//----------------------------------------------------------------------------------
const int SERVO_LEFT_HIP = 5;
const int SERVO_LEFT_FOOT = 2;
const int SERVO_RIGHT_HIP = 3;
const int SERVO_RIGHT_FOOT = 4;

// 엉덩이 서보 장착 방향: 1=MobBob 스타일(앞쪽), -1=Bob 스타일(뒤쪽)
#define FRONT_JOINT_HIPS 1

//----------------------------------------------------------------------------------
// 서보 최대/최소/중심 상수 - 로봇에 맞게 설정
//----------------------------------------------------------------------------------
const int LEFT_HIP_CENTRE = 1580;
const int LEFT_HIP_MIN = LEFT_HIP_CENTRE - 500;
const int LEFT_HIP_MAX = LEFT_HIP_CENTRE + 500;
const int LEFT_FOOT_CENTRE = 1410;
const int LEFT_FOOT_MIN = LEFT_FOOT_CENTRE - 500;
const int LEFT_FOOT_MAX = LEFT_FOOT_CENTRE + 500;
const int RIGHT_HIP_CENTRE = 1500;
const int RIGHT_HIP_MIN = RIGHT_HIP_CENTRE - 500;
const int RIGHT_HIP_MAX = RIGHT_HIP_CENTRE + 500;
const int RIGHT_FOOT_CENTRE = 1465;
const int RIGHT_FOOT_MIN = RIGHT_FOOT_CENTRE - 500;
const int RIGHT_FOOT_MAX = RIGHT_FOOT_CENTRE + 500;

//------------------------------------------------------------------------------
// 관절 값 계산을 위한 헬퍼 함수
//------------------------------------------------------------------------------
int LeftHipCentre() { return LEFT_HIP_CENTRE; }
int LeftHipIn(int ms) { return LEFT_HIP_CENTRE + (FRONT_JOINT_HIPS * ms); }
int LeftHipOut(int ms) { return LEFT_HIP_CENTRE - (FRONT_JOINT_HIPS * ms); }
int RightHipCentre() { return RIGHT_HIP_CENTRE; }
int RightHipIn(int ms) { return RIGHT_HIP_CENTRE - (FRONT_JOINT_HIPS * ms); }
int RightHipOut(int ms) { return RIGHT_HIP_CENTRE + (FRONT_JOINT_HIPS * ms); }
int LeftFootFlat() { return LEFT_FOOT_CENTRE; }
int LeftFootUp(int ms) { return LEFT_FOOT_CENTRE - ms; }
int LeftFootDown(int ms) { return LEFT_FOOT_CENTRE + ms; }
int RightFootFlat() { return RIGHT_FOOT_CENTRE; }
int RightFootUp(int ms) { return RIGHT_FOOT_CENTRE + ms; }
int RightFootDown(int ms) { return RIGHT_FOOT_CENTRE - ms; }

//----------------------------------------------------------------------------------
// 키프레임 애니메이션 데이터 (걷기, 회전, 다양한 모션)
// 형식: {밀리초, leftHip, leftFoot, rightHip, rightFoot}
// -1 값은 해당 서보 위치를 유지하라는 의미
// 첫 번째 요소는 메타데이터: {프레임 수, 0, 0, 0, 0}
//----------------------------------------------------------------------------------
const int TWEEN_TIME_VALUE = 0;
const int LEFT_HIP_VALUE = 1;
const int LEFT_FOOT_VALUE = 2;
const int RIGHT_HIP_VALUE = 3;
const int RIGHT_FOOT_VALUE = 4;
const int FOOT_DELTA = 150;
const int HIP_DELTA = FRONT_JOINT_HIPS * 120;

// 기본 자세 (똑바로 서기)
int standStraightAnim[][5] = {
  { 1, 0, 0, 0, 0 },
  { 300, LeftHipCentre(), LeftFootFlat(), RightHipCentre(), RightFootFlat() }
};

// 전진 걷기
int walkForwardAnim[][5] = {
  { 8, 0, 0, 0, 0 },
  { 300, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipCentre(), RightFootDown(FOOT_DELTA) },
  { 300, LeftHipIn(HIP_DELTA), LeftFootUp(FOOT_DELTA), RightHipOut(HIP_DELTA), RightFootDown(FOOT_DELTA) },
  { 300, LeftHipIn(HIP_DELTA), LeftFootFlat(), RightHipOut(HIP_DELTA), RightFootFlat() },
  { 300, LeftHipIn(HIP_DELTA), LeftFootDown(FOOT_DELTA), RightHipOut(HIP_DELTA), RightFootUp(FOOT_DELTA) },
  { 300, LeftHipCentre(), LeftFootDown(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 300, LeftHipOut(HIP_DELTA), LeftFootDown(FOOT_DELTA), RightHipIn(HIP_DELTA), RightFootUp(FOOT_DELTA) },
  { 300, LeftHipOut(HIP_DELTA), LeftFootFlat(), RightHipIn(HIP_DELTA), RightFootFlat() },
  { 300, LeftHipOut(HIP_DELTA), LeftFootUp(FOOT_DELTA), RightHipIn(HIP_DELTA), RightFootDown(FOOT_DELTA) }
};

// 후진 걷기
int walkBackwardAnim[][5] = {
  { 8, 0, 0, 0, 0 },
  { 300, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipCentre(), RightFootDown(FOOT_DELTA) },
  { 300, LeftHipOut(HIP_DELTA), LeftFootUp(FOOT_DELTA), RightHipIn(HIP_DELTA), RightFootDown(FOOT_DELTA) },
  { 300, LeftHipOut(HIP_DELTA), LeftFootFlat(), RightHipIn(HIP_DELTA), RightFootFlat() },
  { 300, LeftHipOut(HIP_DELTA), LeftFootDown(FOOT_DELTA), RightHipIn(HIP_DELTA), RightFootUp(FOOT_DELTA) },
  { 300, LeftHipCentre(), LeftFootDown(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 300, LeftHipIn(HIP_DELTA), LeftFootDown(FOOT_DELTA), RightHipOut(HIP_DELTA), RightFootUp(FOOT_DELTA) },
  { 300, LeftHipIn(HIP_DELTA), LeftFootFlat(), RightHipOut(HIP_DELTA), RightFootFlat() },
  { 300, LeftHipIn(HIP_DELTA), LeftFootUp(FOOT_DELTA), RightHipOut(HIP_DELTA), RightFootDown(FOOT_DELTA) }
};

// 걷기 마무리 애니메이션 (기본 자세로 복귀)
int walkEndAnim[][5] = {
  { 2, 0, 0, 0, 0 },
  { 300, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipCentre(), RightFootDown(FOOT_DELTA) },
  { 300, LeftHipCentre(), LeftFootFlat(), RightHipCentre(), RightFootFlat() }
};

// 좌회전
int turnLeftAnim[][5] = {
  { 6, 0, 0, 0, 0 },
  { 300, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipCentre(), RightFootDown(FOOT_DELTA) },
  { 300, LeftHipIn(HIP_DELTA), LeftFootUp(FOOT_DELTA), RightHipIn(HIP_DELTA), RightFootDown(FOOT_DELTA) },
  { 300, LeftHipIn(HIP_DELTA), LeftFootFlat(), RightHipIn(HIP_DELTA), RightFootFlat() },
  { 300, LeftHipIn(HIP_DELTA), LeftFootDown(FOOT_DELTA), RightHipIn(HIP_DELTA), RightFootUp(FOOT_DELTA) },
  { 300, LeftHipCentre(), LeftFootDown(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 300, LeftHipCentre(), LeftFootFlat(), RightHipCentre(), RightFootFlat() }
};

// 우회전
int turnRightAnim[][5] = {
  { 6, 0, 0, 0, 0 },
  { 300, LeftHipCentre(), LeftFootDown(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 300, LeftHipIn(HIP_DELTA), LeftFootDown(FOOT_DELTA), RightHipIn(HIP_DELTA), RightFootUp(FOOT_DELTA) },
  { 300, LeftHipIn(HIP_DELTA), LeftFootFlat(), RightHipIn(HIP_DELTA), RightFootFlat() },
  { 300, LeftHipIn(HIP_DELTA), LeftFootUp(FOOT_DELTA), RightHipIn(HIP_DELTA), RightFootDown(FOOT_DELTA) },
  { 300, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipCentre(), RightFootDown(FOOT_DELTA) },
  { 300, LeftHipCentre(), LeftFootFlat(), RightHipCentre(), RightFootFlat() }
};

// 머리 흔들기
int shakeHeadAnim[][5] = {
  { 4, 0, 0, 0, 0 },
  { 150, LeftHipOut(HIP_DELTA), LeftFootFlat(), RightHipIn(HIP_DELTA), RightFootFlat() },
  { 150, LeftHipCentre(), LeftFootFlat(), RightHipCentre(), RightFootFlat() },
  { 150, LeftHipIn(HIP_DELTA), LeftFootFlat(), RightHipOut(HIP_DELTA), RightFootFlat() },
  { 150, LeftHipCentre(), LeftFootFlat(), RightHipCentre(), RightFootFlat() }
};

// 흔들기 (Wobble)
int wobbleAnim[][5] = {
  { 4, 0, 0, 0, 0 },
  { 300, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipCentre(), RightFootDown(FOOT_DELTA) },
  { 300, LeftHipCentre(), LeftFootFlat(), RightHipCentre(), RightFootFlat() },
  { 300, LeftHipCentre(), LeftFootDown(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 300, LeftHipCentre(), LeftFootFlat(), RightHipCentre(), RightFootFlat() }
};

// 좌측 흔들기
int wobbleLeftAnim[][5] = {
  { 2, 0, 0, 0, 0 },
  { 300, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipCentre(), RightFootDown(FOOT_DELTA) },
  { 300, LeftHipCentre(), LeftFootFlat(), RightHipCentre(), RightFootFlat() }
};

// 우측 흔들기
int wobbleRightAnim[][5] = {
  { 2, 0, 0, 0, 0 },
  { 300, LeftHipCentre(), LeftFootDown(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 300, LeftHipCentre(), LeftFootFlat(), RightHipCentre(), RightFootFlat() }
};

// 양발 탭
int tapFeetAnim[][5] = {
  { 2, 0, 0, 0, 0 },
  { 500, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 500, LeftHipCentre(), LeftFootFlat(), RightHipCentre(), RightFootFlat() }
};

// 좌측 발 탭
int tapLeftFootAnim[][5] = {
  { 2, 0, 0, 0, 0 },
  { 500, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipCentre(), RightFootFlat() },
  { 500, LeftHipCentre(), LeftFootFlat(), RightHipCentre(), RightFootFlat() }
};

// 우측 발 탭
int tapRightFootAnim[][5] = {
  { 2, 0, 0, 0, 0 },
  { 500, LeftHipCentre(), LeftFootFlat(), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 500, LeftHipCentre(), LeftFootFlat(), RightHipCentre(), RightFootFlat() }
};

// 바운스
int bounceAnim[][5] = {
  { 2, 0, 0, 0, 0 },
  { 500, LeftHipCentre(), LeftFootDown(300), RightHipCentre(), RightFootDown(300) },
  { 500, LeftHipCentre(), LeftFootFlat(), RightHipCentre(), RightFootFlat() }
};

// 다리 흔들기
int shakeLegsAnim[][5] = {
  { 14, 0, 0, 0, 0 },
  { 300, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipCentre(), RightFootDown(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipIn(HIP_DELTA), RightFootDown(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipCentre(), RightFootDown(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipOut(HIP_DELTA), RightFootDown(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipCentre(), RightFootDown(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipIn(HIP_DELTA), RightFootDown(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipCentre(), RightFootDown(FOOT_DELTA) },
  { 300, LeftHipCentre(), LeftFootFlat(), RightHipCentre(), RightFootFlat() },
  { 300, LeftHipCentre(), LeftFootDown(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 100, LeftHipIn(HIP_DELTA), LeftFootDown(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootDown(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 100, LeftHipOut(HIP_DELTA), LeftFootDown(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootDown(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 300, LeftHipCentre(), LeftFootFlat(), RightHipCentre(), RightFootFlat() }
};

// 좌측 다리 흔들기
int shakeLeftLegAnim[][5] = {
  { 12, 0, 0, 0, 0 },
  { 300, LeftHipCentre(), LeftFootDown(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 100, LeftHipIn(HIP_DELTA), LeftFootDown(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootDown(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 100, LeftHipOut(HIP_DELTA), LeftFootDown(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootDown(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 100, LeftHipIn(HIP_DELTA), LeftFootDown(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootDown(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 100, LeftHipOut(HIP_DELTA), LeftFootDown(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootDown(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 100, LeftHipIn(HIP_DELTA), LeftFootDown(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootDown(FOOT_DELTA), RightHipCentre(), RightFootUp(FOOT_DELTA) },
  { 300, LeftHipCentre(), LeftFootFlat(), RightHipCentre(), RightFootFlat() }
};

// 우측 다리 흔들기
int shakeRightLegAnim[][5] = {
  { 12, 0, 0, 0, 0 },
  { 300, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipCentre(), RightFootDown(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipIn(HIP_DELTA), RightFootDown(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipCentre(), RightFootDown(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipOut(HIP_DELTA), RightFootDown(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipCentre(), RightFootDown(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipIn(HIP_DELTA), RightFootDown(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipCentre(), RightFootDown(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipOut(HIP_DELTA), RightFootDown(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipCentre(), RightFootDown(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipIn(HIP_DELTA), RightFootDown(FOOT_DELTA) },
  { 100, LeftHipCentre(), LeftFootUp(FOOT_DELTA), RightHipCentre(), RightFootDown(FOOT_DELTA) },
  { 300, LeftHipCentre(), LeftFootFlat(), RightHipCentre(), RightFootFlat() }
};

//----------------------------------------------------------------------------------
// 서보 직접 제어용 동적 애니메이션 데이터
//----------------------------------------------------------------------------------
int setServosAnim1[][5] = {
  { 1, 0, 0, 0, 0 },
  { 0, LeftHipCentre(), LeftFootFlat(), RightHipCentre(), RightFootFlat() }
};
int setServosAnim2[][5] = {
  { 1, 0, 0, 0, 0 },
  { 0, LeftHipCentre(), LeftFootFlat(), RightHipCentre(), RightFootFlat() }
};

//----------------------------------------------------------------------------------
// 서보 변수 및 상태 변수
//----------------------------------------------------------------------------------
Servo servoLeftHip;
Servo servoLeftFoot;
Servo servoRightHip;
Servo servoRightFoot;

const int millisBetweenAnimUpdate = 20;
long timeAtLastAnimUpdate;
int (*currAnim)[5];
int (*finishAnim)[5];
long timeAtStartOfFrame;
int targetFrame;
int animNumLoops;
char animCompleteStr[3] = "--";
bool animInProgress;
int (*nextAnim)[5];
int (*nextFinishAnim)[5];
int nextAnimNumLoops;
char nextAnimCompleteStr[3] = "--";
bool interruptInProgressAnim;

int currLeftHip, currLeftFoot, currRightHip, currRightFoot;
int startLeftHip, startLeftFoot, startRightHip, startRightFoot;

//===============================================================================
// 파서 관련
//===============================================================================
const char START_CHAR = '<';
const char END_CHAR = '>';
const char SEP_CHAR = ',';
const int PARSER_WAITING = 0;
const int PARSER_COMMAND = 1;
const int PARSER_PARAM1 = 2;
const int PARSER_PARAM2 = 3;
const int PARSER_PARAM3 = 4;
const int PARSER_PARAM4 = 5;
const int PARSER_PARAM5 = 6;
const int PARSER_EXECUTE = 7;

int currParserState = PARSER_WAITING;
char currCmd[3] = "--";
int currCmdIndex;
const int CMD_LENGTH = 2;
int currParam1Val, currParam2Val, currParam3Val, currParam4Val, currParam5Val;
int currParamIndex;
boolean currParamNegative;
const int MAX_PARAM_LENGTH = 6;

//===============================================================================
// Arduino setup() and loop()
//===============================================================================
void setup() {
  softwareSerial.begin(SERIAL_SPEED);
  servoLeftHip.attach(SERVO_LEFT_HIP, LEFT_HIP_MIN, LEFT_HIP_MAX);
  servoLeftFoot.attach(SERVO_LEFT_FOOT, LEFT_FOOT_MIN, LEFT_FOOT_MAX);
  servoRightHip.attach(SERVO_RIGHT_HIP, RIGHT_HIP_MIN, RIGHT_HIP_MAX);
  servoRightFoot.attach(SERVO_RIGHT_FOOT, RIGHT_FOOT_MIN, RIGHT_FOOT_MAX);
  setup_Parser();
  setup_Animation();
}

void loop() {
  loop_Parser();
  loop_Animation();
}

// 파서 설정 및 루프, 애니메이션 처리 함수들 생략 (원문 참조)
// 전체 코드는 원문 길이 관계로 핵심 부분만 표시했습니다.
// 완전한 코드는 원본 프로젝트 페이지 또는 깃허브에서 확인하세요.

회로도

MobBob: 아두이노 로봇 직접 만들기, 안드로이드 스마트폰으로 매끄럽게 제어

제조공정

  1. 블루투스 제어 라즈베리 파이 로봇 만들기 - 오디오 피드백 포함
  2. 나만의 LUMAZOID 만들기: DIY 아두이노 음악 비주얼라이저
  3. 아두이노 디지털 주사위: LCD 기반 랜덤 넘버 제너레이터 만들기
  4. 아두이노 나노로 37개 LED 룰렛 게임 만들기
  5. 아두이노와 스마트폰으로 만드는 스마트 전압계 – 초간단 DIY 프로젝트
  6. 아두이노 나노로 만드는 음성 제어 로봇 - 블루투스와 안드로이드 앱 활용
  7. 피봇(PiBot): 아두이노 기반 88건반 피아노 연주 로봇
  8. 아두이노 나노와 네오픽셀 매트릭스로 만드는 네온 퐁 게임
  9. DIY 손동작 제어 아두이노 로봇 팔 - 단계별 제작 가이드
  10. 다블(Dabble) 앱으로 제어하는 4륜 아두이노 로봇 만들기