프로젝트

나도 메이커! 메이커스 여러분들의 작품/프로젝트를 공유하는 공간입니다.

DIY RC카 만들기

2014-09-15 11:10:44

개요


RC 카란 Radio Control의 약자로 무선조종이 가능한 자동차를 말합니다.
장난감으로 치부하기에는 굉장한 매니아 층을 형성하고 있습니다.


출처 : RC카 경주대회 - www.rcmodelswiz.co.uk

국내외 다양한 동호회에서 자신들만의 노하우를 공유하고,
실제 오프라인 공간에서 그랑프리가 열리기도 합니다.
하지만 이러한 RC카 세계에 입문하기에는
모터에 대한 전문지식이 필요하고, 많은 비용이 들기 마련입니다.




출처 : 다양한 전동 키트 - http://www.scoop.it/

하.지.만 아두이노를 이용하면, 
다양한 키트를 기반으로 자신만의 RC카를 만들수 있을 뿐만 아니라,


출처 : 초음파 센서를 장착한 RC카 - www.svenbluege.de

카메라, 초음파센서, LED등 다양한 기능을 추가할 수 있고,
제어방식 또한 원하는 방식으로 설정할 수 있습니다.

이번 프로젝트에서는 기존의 DC 모터 자동차 키트와 블루투스 모듈을 이용하여
스마트폰으로 제어하는 DIY RC카를 만들어 보겠습니다.

미리보기 동영상




필요한 사전지식


부품목록


NO 부품명 수량 상세설명
1 오렌지 보드 1 아두이노 호환보드
2 점퍼케이블 7 점퍼케이블
3 미니브레드보드 1 브레드보드
4 블루투스 모듈 1 HC-05
5 아두이노 모터 쉴드 1 모터 쉴드
6 2.1mm DC 잭 1 DC 잭 male
7 Amphibious vehicle kit (DC모터 내장) 1 타미야
8 서보모터 1 sg-90
9 9v 건전지 2 배터리
10 9v 어답터 2 어답터
11 케이블타이(선택) 5 케이블타이
12 글루건(필수) 1 글루건
13 커터칼 1
14 니퍼 1 니퍼
15 스크류 드라이버 1 +,- 혼합형
16 핸드드릴(선택) 1 핸드드릴
17 인두기 1 인두기
18 1
19 안드로이드 스마트폰 1 안드로이드

부품명 오렌지 보드 미니 브레드보드 점퍼케이블 블루투스 모듈 아두이노 모터 쉴드
파트 x1 x1 x7  x1
부품명 2.1mm DC 잭 Amphibious vehicle kit 서보모터 9v 건전지 9v 어답터
파트 x1 x1 x1  x1
부품명 글루건 커터칼 니퍼 스크류 드라이버 인두기
파트 x1 x1 x1  x1
부품명 안드로이드 스마트폰
파트 x1 x1

하드웨어 Making

RC CAR 만들기 - Amphibious vehicle kit 해킹하기
본 프로젝트에서는 타미야의 Amphibious vehicle kit 를 이용하여 진행하였습니다.
1. 본체 조립하기
- 키트에 포함된 메뉴얼에 따라 조립을 해주세요.
- 모터 부분을 조립하기 전에 DC 모터에 전선을 납땝하여 연장해 주세요.

2. 앞바퀴 축을 서보모터와 연결 합니다.
나사는 약1cm 이상의 못머리가 넓은 나사를 사용하였습니다.
글루건으로 벌어진 틈새를 보강하였습니다.

3. 서보모터와 키트 본체를 연결합니다.
키트에 들어있는 나사와 규격이 맞지않아 핸드 드릴로 구멍을 넓혀 주었습니다.

키트의 연결부쪽 둥그런 부분이 서보모터와 닿는 다면, 사포로 갈아 주세요

4. 아두이노 보드를 결합하기 위해 표시된 부분을 칼이나, 핸드드릴로 잘라줍니다.
주의: 단단한 플라스틱이기 때문에 가공시 베이지 않도록 주의하세요.

5. 모터쉴드를 사용하여 DC모터와 서보모터를 연결합니다.
아두이노 모터쉴드에 DC모터 (A채널)와
5번 핀을 사용하는 PWM 핀에 서보모터를 연결하였습니다. 
무선으로 구동하기 위해 9V 배터리를 모터쉴드와 아두이노 보드에 연결하였습니다.

미니 브레드보드에 HC-05 블루투스모듈을 연결하여 서보모터 위에 고정하였습니다.

6.연결된 하드웨어를 키트와 고정합니다.
글루건을 이용하여 보드와 본체를 고정하였습니다.
적당한 양을 사용해주세요.


7.최종 완성된 모습입니다.


회로도


브레드보드 레이아웃




소프트웨어 Coding

#include <SoftwareSerial.h> // 블루투스 통신을 위한 SoftwareSerial 라이브러리
#include <Servo.h> // 서보모터를 제어하기 위한 라이브러리

SoftwareSerial BTSerial(6, 7); // SoftwareSerial(RX, TX)
byte buffer[1024]; // 데이터 수신 버퍼
int bufferPosition; // 버퍼에 기록할 위치

Servo servo;

int dcMotor = 12;
int dcSpeed = 3;
// DC모터의 움직임을 제어하는 핀(12)과 속도를 제어하는 핀(3) int motorAngle = 0; int motorSpeed = 0;
// 서보모터의 각도와, DC모터의 속도 void setup () { servo.attach(5); // 5번핀에 연결된 서보모터 pinMode(dcMotor, OUTPUT); BTSerial.begin(9600); Serial.begin(9600); bufferPosition = 0; } void loop () { if (BTSerial.available()) { // 블루투스 통신이 가능할 경우 byte data = BTSerial.read(); buffer[bufferPosition++] = data; // 블루투스에서 받아온 값을 byte data에 저장 Serial.println(data); switch(data){ // 블루투스에서 받아온 값에 따라 맞는 동작을 함 case 'q': // q일경우 프로그레스바에 값을 속도로 speedSet(); break; case 'w': // 스마트폰의 기울기(양수)에 따라 서보모터 각도 제어 angleSet(0); break; case 'e': // 스마트폰의 기울기(음수)에 따라 서보모터 각도 제어 angleSet(1); break; case 'j': // -60도 버튼을 눌렀을 경우 angleWrite(30); break; case 'i': // -30도 버튼을 눌렀을 경우 angleWrite(60); break; case 'k': // 0도 버튼을 눌렀을 경우 angleWrite(90); break; case 'o': // 30도 버튼을 눌렀을 경우 angleWrite(120); break; case 'l': // 60도 버튼을 눌렀을 경우 angleWrite(150); break; case 'F': // Forward 토글버튼을 눌렀을 경우(토글버튼에 불이 켜졌을 경우) 모터를 정방향으로 돌림 motorDirection(0, motorSpeed); break; case 'f': // Forward 토글버튼을 눌렀을 경우(토글버튼에 불이 꺼졌을 경우) 모터를 멈춤 motorDirection(0, 0); break; case 'B': // Back 버튼을 눌렀을 경우(토글버튼에 불이 켜졌을 경우) 모터를 역방향으로 돌림 motorDirection(1, motorSpeed); break; case 'b': // Back 버튼을 눌렀을 경우(토글버튼에 불이 꺼졌을 경우) 모터를 멈춤 motorDirection(1, 0); break; case '\n': // 문장이 끝낫을 경우 bufferPosition = 0; break; } } } void speedSet() { // 프로그레스바에 맞는 값을 읽어 모터의 속도를 조절하는 함수 if (bufferPosition == 4) { motorSpeed = (buffer[0]-48)*100 + (buffer[1]-48)*10 + (buffer[2]-48); } else if (bufferPosition == 3) { motorSpeed = (buffer[0]-48)*10 + (buffer[1]-48); } else if (bufferPosition == 2) { motorSpeed = buffer[0] - 48; } analogWrite(dcSpeed, motorSpeed); } void angleSet(boolean flag){ // 스마트폰에 기울기를 읽어 서보모터의 각도를 조절하는 함수 if(buffer[0] != 10){ if (bufferPosition == 4) { motorAngle = (buffer[0]-48)*100 + (buffer[1]-48)*10 + (buffer[2]-48); } else if (bufferPosition == 3) { motorAngle = (buffer[0]-48)*10 + (buffer[1]-48); } else if (bufferPosition == 2) { motorAngle = buffer[0] - 48; }
if(flag){ // flag가 0이면 왼쪽(기울기가 양수), flag가 1이면 오른쪽(기울기가 음수) motorAngle *= -1; } Serial.print("motorAngle = "); Serial.println(motorAngle); motorAngle = map(motorAngle, 150, -150, 30, 150); // 서보모터의 각도로 범위를 재지정 해줌 servo.write(motorAngle); } } void angleWrite(int angle){ // 서보모터의 각도 조절 servo.write(angle); } void motorDirection(boolean dir, int speedVal) { // Dc모터의 방향 및 속도 제어 motorSpeed = speedVal; if (dir == 0) { digitalWrite(dcMotor, HIGH); } else { digitalWrite(dcMotor, LOW); } analogWrite(dcSpeed, motorSpeed); }


소프트웨어 설명

RC카를 제어할 안드로이드 어플(rc_Test.apk)을 받으신 후, 실행 하면 밑의 사진처럼 화면이 나옵니다.


 switch(data){ // 블루투스에서 받아온 값에 따라 맞는 동작을 함
      case 'q':  // q일경우 프로그레스바에 값을 속도로 
        speedSet();
        break;
        
      case 'w': // 스마트폰의 기울기(양수)에 따라 서보모터 각도 제어
        angleSet(0);
        break;
       
      case 'e':  // 스마트폰의 기울기(음수)에 따라 서보모터 각도 제어
        angleSet(1);
        break;
        
      case 'j': // -60도 버튼을 눌렀을 경우
        angleWrite(30);
        break;
      
      case 'i': // -30도 버튼을 눌렀을 경우
        angleWrite(60);
        break;
        
      case 'k': // 0도 버튼을 눌렀을 경우
         angleWrite(90);
         break;
         
       case 'o': // 30도 버튼을 눌렀을 경우
         angleWrite(120);
         break;
         
       case 'l': // 60도 버튼을 눌렀을 경우
         angleWrite(150);
         break;
         
       case 'F': // Forward 토글버튼을 눌렀을 경우(토글버튼에 불이 켜졌을 경우) 모터를 정방향으로 돌림
         motorDirection(0, motorSpeed);
         break;
         
       case 'f': // Forward 토글버튼을 눌렀을 경우(토글버튼에 불이 꺼졌을 경우) 모터를 멈춤
         motorDirection(0, 0);
         break;

       case 'B': // Back 버튼을 눌렀을 경우(토글버튼에 불이 켜졌을 경우) 모터를 역방향으로 돌림
         motorDirection(1, motorSpeed);
         break;
         
       case 'b': // Back 버튼을 눌렀을 경우(토글버튼에 불이 꺼졌을 경우) 모터를 멈춤
         motorDirection(1, 0);
         break;
         
       case '\n': // 문장이 끝낫을 경우
         bufferPosition = 0;
         break;
   }
안드로이드 어플에서 각 동작마다 해당 동작에 대한 값을 블루투스로 보내줍니다.  각각 q, w, e, j, i, k, o, l, F, f, B, b(대문자 소문자 구분 합니다.) 값을 보내는 데, 

q는 프로그레스바, w와 e는 스마트폰의 기울기, j, i, k, o, l은 각각 기울기 버튼, F, f는 Forward버튼 B, b는 Back버튼 입니다.

void speedSet() { // 프로그레스바에 맞는 값을 읽어 모터의 속도를 조절하는 함수
  if (bufferPosition == 4) {
     motorSpeed = (buffer[0]-48)*100 + (buffer[1]-48)*10 + (buffer[2]-48);
  } else if (bufferPosition == 3) {
    motorSpeed = (buffer[0]-48)*10 + (buffer[1]-48);
  } else if (bufferPosition == 2) {
    motorSpeed = buffer[0] - 48;
  }

  analogWrite(dcSpeed, motorSpeed);
}
'q' 가 들어왔을 때 DC모터의 속도를 제어하는 함수입니다. 블루투스 통신은 byte단위 한글자씩 전송하므로 각 자리를 버퍼에 저장해 두었다가, 마지막 글자가 q일 경우 버퍼에 저장된 값을 읽어 프로그레스바의 숫자를 저장합니다. (제일 큰 자리의 수가 먼저 들어옵니다. buffer[0] 번 부터)

이렇게 읽은 값만큼 속도를 제어합니다. 

void angleSet(boolean flag){ // 스마트폰에 기울기를 읽어 서보모터의 각도를 조절하는 함수
  if(buffer[0] != 10){
    if (bufferPosition == 4) {
       motorAngle = (buffer[0]-48)*100 + (buffer[1]-48)*10 + (buffer[2]-48);
    } else if (bufferPosition == 3) {
      motorAngle = (buffer[0]-48)*10 + (buffer[1]-48);
    } else if (bufferPosition == 2) {
      motorAngle = buffer[0] - 48;
    }
if(flag){ // flag가 0이면 왼쪽(기울기가 양수), flag가 1이면 오른쪽(기울기가 음수) motorAngle *= -1; } Serial.print("motorAngle = "); Serial.println(motorAngle); motorAngle = map(motorAngle, 150, -150, 30, 150); // 서보모터의 각도로 범위를 재지정 해줌 servo.write(motorAngle); } }
'w', 'e'가 들어왔을 때 서보모터의 각도를 제어하는 함수 입니다. 'w'가 들어오면 기울기가 양수(flag == 0), 'e'가 들어오면 기울기는 음수(flag == -1)입니다.

위 프로그레스 막대바의 값을 읽는 것과 마찬가지로 숫자들을 버퍼에 저장한 후 'w'나 'e' 가 들어왔을 때 buffer 에 저장된 값을 읽어 기울기를 구합니다. 

그 후 읽은 값을 map 함수를 이용하여 서보모터 각도 제어 범위(0~180도 이지만 0, 180도로 꺽으면 rc카가 움직이지 못하므로 30~150도로 조정했습니다.)로 재설정 해 준 후 재설정된 값에 맞게 서보모터의 각도를 조정합니다.

void angleWrite(int angle){ // 서보모터의 각도 조절
  servo.write(angle); 
}

void motorDirection(boolean dir, int speedVal) { // Dc모터의 방향 및 속도 제어
  motorSpeed = speedVal;
  
  if (dir == 0) {
    digitalWrite(dcMotor, HIGH);
  } else {
    digitalWrite(dcMotor, LOW);
  }

  analogWrite(dcSpeed, motorSpeed);
}
나머지 서보모터의 각도 버튼(-60~60도)과 Forward 토글버튼, Back 토글버튼에 맞게 동작 합니다. 각도 버튼을 눌렀을 경우 그 버튼에 각도에 맞게 서보모터를 조정하고, Forward / Back 버튼에 맞게 DC모터의 방향을 조정합니다.(정방향은 모터 방향핀 High, 역방향은 모터 방향핀 Low로 해주시면 됩니다.)






hihyo

아두이노,모터쉴드,DC모터,서보모터,모터제어,블루투스,HC-05,스마트폰,안드로이드,무선통신,DIY,RC카,
profile

김수현 2015-03-05 10:14:00

포스팅 잘 봤습니다. 제가 이번에 고3이 되어서 블루투스를 이용한 RC카를 제작하고자 이 글을 보게 되었습니다만.. 블루투스 조종 어플리케이션이 꽤 많더라구요 ㅇㅅㅇ; 다른 글 돌아다니면서 보니 BluCar라는 어플이 있던데 그러면 어플끼리 대응하는 게 약간씩 다를거라서 걱정이 됩니다. ㅇㅅㅇ 글쓴이 님의 코딩을 이용하여 BluCar라는 어플에서 구동시키려면 어떤 부분을 바꾸면 좋을지 알려주시면 정말 감사하겠습니다.

profile

SaBo 2015-04-07 17:03:38

9V로도 은근히 속도가 빠르게 출력이 되네요~ 나중에 기회가 되면 초 경량화된 슈퍼카를 만들 계획인데 덕분에 많은 도움 될 것 같습니다.

profile

장재환 2015-04-07 22:28:43

저는 아트로봇이라는 곳에서 파는 BLE보드 인 bluno라는 아두이노 보드로 안드로이드와 연동하려합니다.
하지만 어플을 실행하고 블루노와 블루투스를 연결하기위해 누르면 렉이걸려 어플이 멈춥니다...
이해 해결방안을 혹시 알고 계신지 궁금합니다. 핸드폰은 갤럭시 노트3입니다.

profile

박지훈 2015-05-23 18:01:57

와 대단하시네요~ 저도 rc카 조종기앱을 만들었엇어요 ㅎㅎ 근데 질문이있는데 rc카에 센서를 장착해서 그 센서값을 조종기 앱 지정한 위치에 출력되도록 하고싶은데 어찌해야할까요....

profile

번개 2016-02-05 23:13:15

서브모터를 모터쉴드에 연결할 때 선의 순서가 다릅니다. 브레드보드 레이아웃의 서브모터 선의 색깔과 모터쉴드의 소켓에 연결된 선의 순서에 맞춰야 하는군요.

profile

번개 2016-02-05 23:18:32

서브모터와 모터쉴드의 선 연결 순서 문제로 시간을 많이 소모하였습니다.
몇가지 작동상의 문제가 있습니다.
1. 블루투스 페어링이 잘 떨어집니다.
2. 전후 조절 후 서브모터의 움직임이 비정상입니다.

profile

김수현 2016-02-16 02:36:35

참고하겠습니다~

profile

csm 2016-04-29 14:11:06

이 프로젝트를 참고해서 아두이노 RC카를 만들어보았습니다. 감사합니다.

profile

shield 2016-06-23 23:44:19

아두이노 오렌지보드 ble호환이면 어떻게 해야하나요?????