2016년 6월 22일 수요일

원격 센서 데이터 취득을 위한 무선 제어 기반 휠 타입 4WD 로버 개발

휠 타입 로버(wheel-based rover)는 캐터필러 타입에 비해, 빠른 진행 속도, 회전 속도, 토크, 적은 소음을 가진다. 이 글에서는 실외에서 바닥이 고르지 못해도 구동이 가능한 큰 바퀴 타입이 적용된 로버를 간단히 제작해 본다. 여기에 사용된 것은 다음 그림과 같은 4WD(4륜 구동) rover kit 이다. 이 프레임은 여러 가지 센서 등을 마운팅하기 쉽도록 되어 있다. 이를 기반으로 다양한 센서를 마운팅할 수 있고, 원격으로 데이터를 취득할 수 있다.
이 글은 다음 링크를 참고하였다.
개발 방법은 다음과 같다.

1. 모터 드라이버 준비 및 아두이노와 연결
모터 드라이버 칩을 직접 이용할 수도 있지만, 큰 전류를 큰 무리없이 지원하기 위해, L298N 을 사용한다. L298N은 아두이노와 연결해 좌, 우 모터의 속도 및 방향을 제어할 수 있는 신호선을 제공한다.


  • Double H bridge Drive Chip: L298N
  • Logical voltage: 5V Drive voltage: 5V-35V
  • Logical current: 0-36mA Drive current: 2A (MAX single bridge)
  • Max power: 25W
  • Dimensions: 43 x 43 x 26mm
  • Weight: 26g

모터 드라이버와 아두이노는 다음과 같이 연결한다. 차후, 배터리를 연결할 때는 드라이버보드의 GND핀과 12V핀을 각각 연결하도록 한다. 이때, 배터리 +, - 선이 서로 합선되지 않도록 조심한다. 용량이 큰 배터리의 경우 합선되면 위험하다.



2. 로버의 모터 속도 및 회전 방향을 제어하는 아두이노 코드 준비
다음 코드를 아두이노에 업로드한다.

3. 배터리 준비
배터리는 11.1V 전압을 지원하는 3셀 리튬이온 배터리를 준비한다. 아울러, 이를 충전할 수 있는 전용 충전기를 준비한다. 배터리를 연결할 때는 모터 드라이버의 외부 전원 입력 핀을 이용하고, 그라운드는 공통 접지 한다.


4. 무선 통신 기반 제어 준비
HC-06과 같은 블루투스 장치 등을 아두이노와 연결해 모터 드라이버 신호를 제어한다.
이와 관련된 것은 다음 링크를 참고한다.
간단히 무선 제어 동작을 테스트하기 위해, 키보드 값을 입력받아, 무선으로 모터 드라이버를 제어하였다. '1'은 전진, '2'는 정지, '3'은 후진, '4는 좌회전, '5'는 우회전이다.

#include <SoftwareSerial.h>

#define rxPin 6
#define txPin 7

SoftwareSerial SwSerial(txPin, rxPin);

// Motor 1
int dir1PinA = 2;
int dir2PinA = 3;
int speedPinA = 9; // Needs to be a PWM pin to be able to control motor speed

// Motor 2
int dir1PinB = 4;
int dir2PinB = 5;
int speedPinB = 10; // Needs to be a PWM pin to be able to control motor speed

void setup() {  // Setup runs once per reset
  // initialize serial communication @ 9600 baud:
  Serial.begin(9600);
  SwSerial.begin(115200);
    
  //Define L298N Dual H-Bridge Motor Controller Pins
  
  pinMode(dir1PinA,OUTPUT);
  pinMode(dir2PinA,OUTPUT);
  pinMode(speedPinA,OUTPUT);
  pinMode(dir1PinB,OUTPUT);
  pinMode(dir2PinB,OUTPUT);
  pinMode(speedPinB,OUTPUT);
}

void loop() 
{  
  // Initialize the Serial interface: 
  if (SwSerial.available() > 0) 
  {
    int inByte = SwSerial.read();
    int speed; // Local variable
    
    switch (inByte) 
    {
      case '1': // Motor 1 / 2 Forward
        analogWrite(speedPinA, 255);//Sets speed variable via PWM 
        digitalWrite(dir1PinA, LOW);
        digitalWrite(dir2PinA, HIGH);
        Serial.println("Motor 1 Forward"); // Prints out “Motor 1 Forward” on the serial monitor

        analogWrite(speedPinB, 255);
        digitalWrite(dir1PinB, LOW);
        digitalWrite(dir2PinB, HIGH);
        Serial.println("Motor 2 Forward");

        break;
        
      case '2': // Motor 1 / 2 Stop (Freespin)
        analogWrite(speedPinA, 0);
        digitalWrite(dir1PinA, LOW);
        digitalWrite(dir2PinA, HIGH);
        Serial.println("Motor 1 Stop");

        analogWrite(speedPinB, 0);
        digitalWrite(dir1PinB, LOW);
        digitalWrite(dir2PinB, HIGH);
        Serial.println("Motor 2 Stop");
        
        break;
        
      case '3': // Motor 1 / 2 Reverse
        analogWrite(speedPinA, 255);
        digitalWrite(dir1PinA, HIGH);
        digitalWrite(dir2PinA, LOW);
        Serial.println("Motor 1 Reverse");

        analogWrite(speedPinB, 255);
        digitalWrite(dir1PinB, HIGH);
        digitalWrite(dir2PinB, LOW);
        Serial.println("Motor 2 Reverse");

        break;
        
      case '4': // Left
        analogWrite(speedPinA, 255);//Sets speed variable via PWM 
        digitalWrite(dir1PinA, LOW);
        digitalWrite(dir2PinA, HIGH);
        Serial.println("Motor 1 Forward"); // Prints out “Motor 1 Forward” on the serial monitor

        analogWrite(speedPinB, 255);
        digitalWrite(dir1PinB, HIGH);
        digitalWrite(dir2PinB, LOW);
        Serial.println("Motor 2 Reverse");
        break;
        
      case '5': // Right
        analogWrite(speedPinA, 255);
        digitalWrite(dir1PinA, HIGH);
        digitalWrite(dir2PinA, LOW);
        Serial.println("Motor 1 Reverse");

        analogWrite(speedPinB, 255);
        digitalWrite(dir1PinB, LOW);
        digitalWrite(dir2PinB, HIGH);
        Serial.println("Motor 2 Forward");
        break;                
    }

    switch (inByte)
    {
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
        delay(1000);
        // turn all the connections off if an unmapped key is pressed:
        for (int thisPin = 2; thisPin < 11; thisPin++) {
          digitalWrite(thisPin, LOW);
        }
    }
  }
}

5. 로버 프레임 및 모터 준비
로버 프레임과 모터를 준비하고, 배터리와 연결할 모터 선들을 정리한다. 다음은 정리한 후 동작을 테스트해 본 것이다.

모터 동작 테스트 모습

6. 모터 드라이버와 모터 연결 및 로버 테스트
모터를 모터 드라이버와 연결하고, 블루투스 터미널 앱을 띄워서, 무선으로 로버를 테스트해본다. 다음과 같이 정상 동작하다.


이제 실제 사람이 들어가기 복잡한 환경에서 센싱 데스트를 해 보자. 사람이 들어가기 어려운 특정 공간에 로버를 진입시켜, 센서 데이터를 원격으로 취득하고, 그 결과를 확인해 본다. 로버는 무선으로 데이터를 취득하고, 제어하기 위해, 간단하게 TK1, RGBD 센서 등을 사용하였다. 로버와 마운트는 개발 시간이 별로 없는 관계로, 플라스틱 박스를 약간 가공해 사용하였다.


다음은 3차원 이미지 센서를 마운팅하여, 테스트한 모습이다. 사람이 진입하기 어려운 복잡한 설비 등을 대상으로 하여, 무선으로 로버를 진입시켜 센서의 3차원 이미지 스캔 데이터를 취득해 보았다.


다음은 취득한 센서 데이터 영상이다. 바닥에서 천장으로 보았을 때 많은 파이프 MEP를 확인할 수 있다.


7. 마무리
휠 타입 로버는 빠른 직진 및 회전 속도를 가진다. 로버에 응용 목적에 맞게 센서나 로봇암을 마운팅하여, 데이터를 취득하는 데 편리하게 활용할 수 있을 것이다.

댓글 3개:

  1. 안녕하세요.
    4WD(4륜 구동) rover kit
    혹시 프레임 어디서 구입하셨는지 알수있을까요?

    답글삭제
    답글
    1. 사이트가 정확히 기억안나네요. DAGU robot, DIY robot 4WD rover 구글링하시면 나올것 같습니다.

      삭제