R + Java + Arduino를 사용하여 온도 측정 및 데이터 시각화 환경을 구성


Arduino는 온도센서를 이용하여 온도 데이터를 수집하여 Serial로 송신하고, Java에서 arduino에서 전송된 온도정보를 Serial로 수신하며, R에서는 Java에서 수신한 데이터를 가공하고 시각화하게 된다.


[Arduino 구성]

 온도센서(TMP 36)를 사용하여 온도 측정할 수 있는 회로를 구성 하였다.

  a. H/W 준비

    - Arduino UNO, USB cable, TMP 36, Wire *3, 

 

  b. 회로 구성


   c. 소스 구성

/* Original code from the Arduino Experimentation Kit Example Code             |

 * CIRC-10 .: Temperature :. (TMP36 Temperature Sensor) |

 * Amended to be used in Java/R

 */


//TMP36 Pin Variables

int temperaturePin = 0;


void setup()

{

  Serial.begin(9600);

}

 

void loop()                     // run over and over again

{

 float temperature = getVoltage(temperaturePin);  //getting the voltage reading from the temperature sensor

 temperature = (temperature - .5) * 100;          //converting from 10 mv per degree wit 500 mV offset

                                                  //to degrees ((volatge - 500mV) times 100)

 Serial.print("T");

 Serial.println(temperature);                     //printing the result

 delay(1000);                                     //waiting a second

}


float getVoltage(int pin){

 return (analogRead(pin) * .004882814); //converting from a 0 to 1023 digital range

                                        // to 0 to 5 volts (each 1 reading equals ~ 5 millivolts

}

  d. Arduino 프로그램 다운로드 및 실행

    위 소스를 Arduino 스케치에서 작성하고 USB케이블을 PC와 보드에 연결하여 

    다운로드하면 된다.


[Java 구성]

  R에서 디바이스간의 통신이 불가하여 R에서 Serial통신이 가능하도록 *.jar 라이버러리를 생성한다.

 본 소스에서는 Java에서 Serial 통신을 위하여 공개된 RXTX library를 활용하였다.

  a. RXTX library 준비

     사이트의 최신(rxtx-2.2pre2-bins.zip) library를 다운로드하여 압축을 풀고,

     OS환경에 맞는 파일을 Java 러이버러리 경로에 복사하여 사용한다.

      rxtx-2-2.2pre2-bins.zip

     

   Mac OSX 환경

    - 다운받은 *.zip파일의 압축을 풀고 rxtx-2.2pre2-bins폴더의 RXTXcomm.jar 파일과

    - 폴더 안에 mac-10.5폴더의 librxtxSerial.jnilib 파일을 복사하고,

    - /Library/Java/Extensions 폴더에 붙여 넣는다.


 b. Serial 통신 미들웨어 소스작성


import java.io.InputStream;

import gnu.io.CommPortIdentifier;

import gnu.io.SerialPort;

import gnu.io.SerialPortEvent;

import gnu.io.SerialPortEventListener;

import java.util.Enumeration;


public class SerialTemperature implements SerialPortEventListener {


    SerialPort serialPort;

    /** The port we're normally going to use. */

    private static final String PORT_NAMES[] = {

        "/dev/tty.usbmodem1431", // Linux

    };

    /** Buffered input stream from the port */

    private InputStream input;


    /** Milliseconds to block while waiting for port open */

    private static final int TIME_OUT = 2000;

    /** Default bits per second for COM port. */

    private static final int DATA_RATE = 9600;


    private String temperatureBuffer;


    public void initialize() {

        CommPortIdentifier portId = null;

        Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();


        // iterate through, looking for the port

        while (portEnum.hasMoreElements()) {

            CommPortIdentifier currPortId = (CommPortIdentifier) portEnum.nextElement();

            for (String portName : PORT_NAMES) {

                if (currPortId.getName().equals(portName)) {

                    portId = currPortId;

                    break;

                }

            }

        }


        if (portId == null) {

            System.out.println("Could not find COM port.");

            return;

        }


        try {

            // open serial port, and use class name for the appName.

            serialPort = (SerialPort) portId.open(this.getClass().getName(),

                                                  TIME_OUT);


            // set port parameters

            serialPort.setSerialPortParams(DATA_RATE,

                                           SerialPort.DATABITS_8,

                                           SerialPort.STOPBITS_1,

                                           SerialPort.PARITY_NONE);


            // open the streams                                                                                                                 

            input = serialPort.getInputStream();


            // add event listeners

            serialPort.addEventListener(this);

            serialPort.notifyOnDataAvailable(true);

        } catch (Exception e) {

            System.err.println(e.toString());

        }

    }



    /**

     * This should be called when you stop using the port.

     * This will prevent port locking on platforms like Linux.

     */

    public synchronized void close() {

        if (serialPort != null) {

            serialPort.removeEventListener();

            serialPort.close();

        }

    }


    /**

     * This will be used by R to retrieve the temperature value

     */

    public synchronized Float read() {

        return Float.valueOf(temperatureBuffer.substring(1)).floatValue();

    }


    /**                                                                                                                                         

     * Handle an event on the serial port. Read the data and save it to the buffer                                                              

     */

    public synchronized void serialEvent(SerialPortEvent oEvent) {

        if (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {

            try {

                int available = input.available();

                byte chunk[] = new byte[available];

                input.read(chunk, 0, available);


                String s = new String(chunk);

                if(s.contains("T")) {

                    temperatureBuffer = s;

                } else {

                    temperatureBuffer += s;

                }


            } catch (Exception e) {

                System.err.println(e.toString());

            }

        }

    }


}


  c. *.jar  파일 만들기

    소스를 컴파일하여 *.jar파일로 생성하여 R 프로그램 위치에 파일을 준비한다.

  • 소스 컴파일 : javac SerialTemperature.java
  • *.jar 파일 생성 : jar cf SerialTemperature.jar SerialTemperature.class
   Eclipse에서 생성시에는 RXTXcomm.jar를 Build path로 등록하고, 코드 구성 및 컴파일
   해야 하며, *.jar파일 생성은 export를 이용하여 간단하게 할 수 있다.

[R 작성]
  R에서는 *.jar 라이버러리를 사용하여 Arduino와 통신을 하고 온도 정보를 받아와서 
  데이터 처리 후 시각화 처리를 하게 된다.

  a. 준비하기 
    R 실행전에 아래의 패키지를 다운로드하여 설치하고, *.jar파일은 R 작업 경로에 
   복사하여 준비한다.
  • R 패키지 준비 : rJava, ggplot2
  • *.jar 파일 준비 : SerialTemperature.jar

 b. R 소스 작성


setwd('/Users/shinhyeongab/Documents/workspace/SerialTemperature/bin')

require(rJava)

require(ggplot2)


.jinit(classpath='SerialTemperature.jar')

ardJava <- .jnew('SerialTemperature')


.jcall(ardJava, returnSig='V', method='initialize')


tempCapture <- NULL

while(Sys.Date()<'2013-12-11') {

  system('sleep 5')

  try({

    ans <- .jsimplify(.jcall(ardJava, returnSig='Ljava/lang/Float;', method='read'))

    tempCapture <- rbind(tempCapture, data.frame(Time=Sys.time(), Temperature=ans))

    print(ggplot(tempCapture) + geom_line(aes(x=Time, y=Temperature)) + theme_bw())

  }, silent=T)

}                                


.jcall(ardJava, returnSig='V', method='close')



[실행하기]

a. Arduino 보드를 PC에 연결하면 온도정보를 송신함.

b. R의 실행을 맨 아래 앞까지 실행 함.

    * 마지막 줄은 Serial 통신 종료 코드 임.


[실행결과] 




 관련파일 : 

TemperatureRecorder.zip


참조 링크 : thermometer-R-using-Arduino-Java


'Big-Data > R Language' 카테고리의 다른 글

R 둘러보기  (0) 2013.11.09
Posted by 혀나미
,