고급 예제

다양한 도구들을 가지고 마음껏 응용해보세요.

시리얼통신- 자바와 아두이노 연동

2016-03-08 11:44:57

개요

 

오래전에 C++와 아두이노간에 시리얼통신을 하는 튜토리얼을 올린적이 있었는데요.

(링크 : http://kocoafab.cc/tutorial/view/255)

 

시리얼통신은 오래된 통신 방법이지만 아두이노에서는 아직도 유용하게 쓰이고 있는 방법이기 때문에 여러 툴들과 시리얼통신으로 연동하는 방법만 익힌다면 그 확장성은 엄청나다고 볼 수 있습니다.

대표적으로 아두이노와 프로세싱간에 시리얼 통신을 들 수 있고, 지금 쓰고자 하는 자바와의 시리얼 통신 또한 많이 쓰일 수 있는 기능입니다.

 

<시리얼 통신 방법>

 

 

이번 글에서는 간단하게 시리얼 통신에 대해 알아보고 자바와 아두이노간에 시리얼통신(Serial Communication)을 하는 법에 대해 알아보겠습니다.

 

 

시리얼 통신에 대한 간단한 소개

 

시리얼 통신(Serial Communication)에서 시리얼(Serial)의 사전적 의미를 찾아보면 아래와 같습니다.

 

 

 

 

사전을 찾아보면 Serial은 순차적인, 연속되는 등의 뭔가 똑같은 일을 계속 반복한다는 의미를 가지고 있는 단어입니다.

통신에서의 시리얼 통신이란 패러럴 통신(병렬 통신)에 반대되는 말로써 한번의 통신의 한 비트의 데이터를 보내는 방식을 말합니다.

 

아래 사진은 패러럴(Parallel)통신에 관한 간략도 입니다.

사진을 보시면 알겠지만 여러개의 입출력 핀과 하나의 클럭핀을 사용하여 한번에 여러개의 데이터를 전송하는 것을 볼 수 있습니다.

 

 

 

 

위의 패러럴 통신에 반대되는 시리얼통신은 아래와 같은 방법으로 이루어집니다.

 

입출력핀이 각각 1개씩 필요한 대신에 데이터는 하나의 입출력핀에서 나와 일렬로 나란히 클럭에 따라 전송됩니다.

이렇게 한번에 하나의 데이터를 전송하는 일을 여러번 반복하기 때문에 시리얼 통신이라고 불립니다.

시리얼 통신을 다른 말로 부르면 병렬 통신에 반대되는 직렬 통신이라고 합니다. 아래 그림과 같이 시리얼 통신에서 데이터는 직렬로 전송되기 때문이죠.

 

 

 

 

위의 그림을 보더라도 한번에 클럭에 병렬통신은 다수의 데이터가 전송되는 반면에 시리얼통신은 오직 하나의 데이터만 전송되는 것을 볼 수 있습니다.

 

이렇게 시리얼통신은 병렬통신에 비해 속도는 느리지만 그 대신 적은 수의 입출력핀을 가지고 통신을 할 수 있다는 장점이 있습니다.

이러한 장점은 핀의 개수가 제한적인 아두이노에서 부각됩니다. 속도를 제한하더라도 핀의 개수를 살리는 방법을 택했기 때문에 아두이노에서는 시리얼 통신을 사용합니다.

 

 

시리얼통신은 크게 동기식비동기식으로 나눌 수 있습니다. 

위의 사진에서는 클럭(CLK)핀이 존재하여 클럭핀에 맞추어 데이터가 전송되는 것을 볼 수 있는데 이렇게 클럭핀에 맞춰서 데이터가 전송되는 방식을 동기식이라 합니다. 동기식의 대표적인 예를 들면 아두이노에서 쓰이는 I2C나 SPI통신을 들 수 있습니다.

 

동기식과 반대로 클럭핀이 없는 대신에 통신속도를 서로 맞추어서 데이터를 전송하는 방법이 있는데 이를 비동기식 통신이라 합니다. 대표적인 방식이 역시 아두이노에서 쓰이는 UART통신을 들 수 있습니다.

UART통신의 경우 CLK핀 없이 Tx핀과 Rx핀 2개만을 사용하며 아두이노UNO의 경우 1개의 UART가 통신하고 Mega의 경우 4개의 UART가 존재합니다.

 

 

 

자바 RxTx라이브러리 다운받기

 

자바에서 RxTx라이브러리를 사용하기 위해서는 역시 라이브러리를 웹에서 내려받아야 합니다.

RxTx라이브러리의 경우 RxTx위키에서 자세한 내용을 다루고 있고 이 곳에서 내려받을 수 있습니다.

 

RxTx WiFi페이지 : http://rxtx.qbang.org/wiki/index.php/Main_Page

RxTx라이브러리 내려받기 : http://rxtx.qbang.org/pub/rxtx/rxtx-2.2pre2-bins.zip​

 

 

 

 

TxRx라이브러리를 받고난 뒤 압축을 풀고

RXTXcomm.jar는 %JAVAHOME%lib에 넣어주시고

rxtxSerial.dll는 %JAVAHOME%bin에 넣어주시면 됩니다.

 

라이브러리 파일 이동 후에 Java프로젝트를 생성하고 프로젝트 클릭 - properties - Java Build Path - Libraries에서 추가하신 RXTXcomm.jar를 추가하면 됩니다.

 

 

 

 

소프트웨어 coding

 

 

자바 코드

import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;

import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class Serial
{
    public Serial()
    {
        super();
    }
    
    void connect ( String portName ) throws Exception
    {
        CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
        if ( portIdentifier.isCurrentlyOwned() )
        {
            System.out.println("Error: Port is currently in use");
        }
        else
        {
            //클래스 이름을 식별자로 사용하여 포트 오픈
            CommPort commPort = portIdentifier.open(this.getClass().getName(),2000);
            
            if ( commPort instanceof SerialPort )
            {
                //포트 설정(통신속도 설정. 기본 9600으로 사용)
                SerialPort serialPort = (SerialPort) commPort;
                serialPort.setSerialPortParams(9600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
                
                //Input,OutputStream 버퍼 생성 후 오픈
                InputStream in = serialPort.getInputStream();
                OutputStream out = serialPort.getOutputStream();
                
                 //읽기, 쓰기 쓰레드 작동
                (new Thread(new SerialReader(in))).start();
                (new Thread(new SerialWriter(out))).start();

            }
            else
            {
                System.out.println("Error: Only serial ports are handled by this example.");
            }
        }     
    }
    
    /** */
    //데이터 수신
    public static class SerialReader implements Runnable 
    {
        InputStream in;
        
        public SerialReader ( InputStream in )
        {
            this.in = in;
        }
        
        public void run ()
        {
            byte[] buffer = new byte[1024];
            int len = -1;
            try
            {
                while ( ( len = this.in.read(buffer)) > -1 )
                {
                    System.out.print(new String(buffer,0,len));
                }
            }
            catch ( IOException e )
            {
                e.printStackTrace();
            }            
        }
    }

    /** */
    //데이터 송신
    public static class SerialWriter implements Runnable 
    {
        OutputStream out;
        
        public SerialWriter ( OutputStream out )
        {
            this.out = out;
        }
        
        public void run ()
        {
            try
            {
                int c = 0;
                while ( ( c = System.in.read()) > -1 )
                {
                    this.out.write(c);
                }                
            }
            catch ( IOException e )
            {
                e.printStackTrace();
            }            
        }
    }
    
    public static void main ( String[] args )
    {
        try
        {
            (new Serial()).connect("COM3"); //입력한 포트로 연결
        }
        catch ( Exception e )
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

 

 

 

아두이노의 포트를 입력하고 아두이노와의 시리얼 통신속도를 맞춘 후 실행시키면 콘솔창에서 아두이노에서 보내는 값이 출력되는 것을 확인할 수 있습니다.

반대로 입력한 값 또한 아두이노로 전달되는것도 확인이 가능합니다.(아두이노의 값 전달의 경우 간단하게 LED 깜빡이기를 통해 확인해 볼 수 있습니다.)

 

 

 

kocoafabeditor

항상 진취적이고, 새로운 것을 추구하는 코코아팹 에디터입니다!

시리얼통신, 자바, 아두이노, 기타

장세현 2016-03-15 19:25:23

감사합니다.

kocoafab 2016-04-07 18:51:04

https://github.com/scream3r/java-simple-serial-connector/ 이런 라이브러리도 있다합니다. 참고하세요

김진만 2016-04-13 10:36:44

잘보았습니다. 감사합니다.

강상호 2016-09-12 14:13:53

감사합니다.

Kaze 2017-07-28 01:12:29

혹시 이거 무선으로도 가능한가요?

ninasimon 2018-11-12 11:53:35

과정에서 많이들 안되실거 같아서 가입하고 댓글 남깁니다. 현재 바로 다운로드 받는 링크는 막혔고,
http://rxtx.qbang.org/wiki/index.php/Download 에서 rxtx-2.2pre2-bins.zip​ 알집 파일을 다운로드 받습니다.

여기서 부터 조금 어렵습니다. 홈페이지에 계발자가 동작방법이라고 말씀하신 것을 토대로 eclipse에서 동작해서 성공했습니다 . 출처는 다음과 같습니다.

http://rxtx.qbang.org/wiki/index.php/Using_RXTX_In_Eclipse

1) 본문에서 설명하신거랑 약간은 다릅니다.
eclipse에 경우에 , project 상에 (JAVAHOME 이라고 본문에 말씀하셨습니다. ) lib폴더를 만듭니다. (eclipse 프로그램을 통해서 ) 그리고 나서 lib 폴더 안에 RXTXcomm.jar 과 rxtxSerial.dll 을 드래그 하여 eclipse를 통해 폴더에 넣습니다.
(여기서 본인 운영체제에 맞는 dll을 넣어주셔야 합니다. )

2)project -> Properties -> Java Build Path ->Libraries 에 들어갑니다.ㅏ

3) Add JARs 버튼을 클릭합니다.

4)lib directory 상에 있는 RXTXComm.jar 을 클릭하여 추가합니다.

5)(jar file이 이제는 꼭 path 상에 있어야 합니다. -> 프로젝트 폴더 안에 jar 파일에 존재해야 한다는 뜻 같습니다. )

6)RXTXComm.jar 을 확장시키면 Native Library Location 이 있습니다. 보면 아마 path설정 가능한 부분이 있을겁니다. 이걸 project lib 가 있는 path 로 설정을 해줍니다.
(이것 역시 project -> Properties -> Java Build Path ->Libraries 에서 합니다. )


여기까지 완료하고, 위 코드를 이클립스에 붙여넣으면 인식을 합니다. 생각보다 어렵습니다. 여기서 추가적으로 아두이노에서 시리얼 통신을 설정해주고, 시리얼 통신을 통해 write를 해야 신호가 옵니다.

2018.11.12 기준으로 구동은 확인됬습니다. 초보 계발자 분들 힘내세요!

유지상 2018-12-10 14:01:27

안녕하세요 질문이 있어 글을 올립니다
센서에서 값을 받아와서 인식하는 거리을 숫자로 받아오는데 까지 성공했는데요 일단 단위가 cm가 아닌것같고 10이상
일경우 십의 자리와 일의 자리를 따로 받아오는것 같습니다
단위를 변경하는 방법과 십의자리,일의 자리 구분없이 한번에 받아오는 경우는 없나요???