2016년 6월 26일 일요일

아두이노 입출력 확장 보드

이 글은 아두이노 입출력 확장보드에 대한 글이다.
레퍼런스는 다음과 같다.
아두이노 확장보드는 다중 모터 구동, 통신 등 다양한 기능을 하나의 보드에 합쳐 놓고, 관련 센서나 액추에이터의 입출력을 손쉽게 하려는 목적에서 개발된 보드이다. 아두이노 확장보드는 몇가지 변종이 있다. 여기서는 많은 센서와 모터가 필요한 로봇, 로버 개발에 편리한 아두이노 입출력 확장 보드를 다룬다.

1. IO Expansion Shield For Arduino (V5) (SKU: DFR0088)
이 보드는 DFRobot IO expansion board로 알려져 있다. XBee를 지원한다. 아울러, SD카드를 제공해 기능적 확장이 가능하다. 이 보드 다음과 같은 기능을 가진다.
  • Motor driver
  • Digital input / output
  • Analog PWM
  • RS485
  • Xbee
  • Bluetooth
  • APC220(쉬운 무선 통신 지원 장치. UART/TTL 인터페이스 지원. 1km 장거리 통신)
  • SD card read/write
다음 그림은 DFR0088의 다이어그램이다 (XBee 혹은 Bluetooth 장치가 중간에 마운팅되어 있다). 오른쪽 위에 디지털 핀(GND, VCC, D) 13쌍, 오른쪽 아래에는 아날로그 핀(GND, VCC, S) 6쌍을 지원한다. 이외에 중앙에 통신 지원 핀, 우측에 RS485 핀, 왼쪽 위/아래에 서버 파워 팀을 지원하고 있다.

다음 다이어그램은 쉴드 기능을 좀 더 상세히 보여주는 그림이다.

다음은 블루투스 장치를 이용해, 간단히 Serial 로 데이터를 입력받는 블루투스 입력 코드 예 이다. 이를 위해, HC-05, HC-06과 같은 블루투스 장치를 앞의 그림에 보이는 APC220 Bluetooth 단자의 RX, TX, GND, VDD에 연결해야 한다. 연결하면, 시리얼 포트 연결은 안되므로, 먼저 다음 코드를 아두이노 보드에 전송한 후, 블루투스를 연결하자. 

int ledPin = 13;

void setup()
{
  Serial.begin(115200);              // start serial communication for Bluetooth
}
  
void loop() {
  if( Serial.available() )           // if data is available to read
  
     val = Serial.read();            // read it and store it in 'val'
   digitalWrite(ledPin, HIGH);
   delay(500);
   digitalWrite(ledPin, LOW);

   delay(500);
     Serial.println("Data received") // Send info back
  }
}

당연히, 블루투스 통신을 위해서는, 블루투스를 페어링할 수 있는 안드로이드 스마트 폰이나 패드가 있어야 한다 (보통, 암호는 1234이다). 제대로 페어링 된 후, Bluetooth Terminal과 같은 프로그램으로 글자하나를 보내 보면, 13번 핀에 연결된 LED가 한번 점멸할 것이다.

다음은 RS485 송신 코드이다.

int EN = 2; //RS485 has a enable/disable pin to transmit or receive data. Arduino Digital Pin 2 = Rx/Tx 'Enable'; High to Transmit, Low to Receive
void setup()
{
  pinMode(EN, OUTPUT);
  Serial.begin(19200);
}
void loop()
{
// send data
  digitalWrite(EN, HIGH);//Enable data transmit
  Serial.print('A');
  delay(1000);
}

다음은 RS485 수신 코드이다.

int ledPin = 13;
int EN = 2;
int val;
void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(EN, OUTPUT);
  Serial.begin(19200);
}
void loop()
{
  // receive data
 digitalWrite(EN, LOW);//Enable Receiving Data
 val = Serial.read();
  if (-1 != val) {
    if ('A' == val) {
      digitalWrite(ledPin, HIGH);
      delay(500);
      digitalWrite(ledPin, LOW);
      delay(500);
    }
 }
}

2. Nexus duino I/O expansion 60008
이 글에서는 지난 시간에 언급한 Nexus 4WD Mecanum Wheel Kit 로버 (rover)에 사용한 IO Expansion Shield V1.2 for Arduino 아두이노 확장보드에 대해 다루도록 한다.


이 보드는 다음과 같은 특징이 있다.
  • XBee header
  • 1 servo external power supply terminal
  • 8 analog IO port and power
  • PWM interface
  • RS485 interface
  • Wireless data-transmission interface
  • Module size 53 x 70mm
  • Weight 33.5g
이 보드는 센서, 서보, RS485 디바이스를 연결하는 것이 쉽다. 이 보드는 아두이노 메가, 아두이노 두에밀라노베(Arduino Duemilanove) 등과 호환된다.

3. 마무리
이 글에서는 아두이노 확장 보드를 간단히 다루어 보았다. 이 확장보드는 로봇, 로버 등을 개발하기 용이하도록 되어 있어, 개발 생상성과 품질을 높여준다. 

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