R + Java + Arduino를 사용하여 온도 측정 및 데이터 시각화 환경을 구성
Arduino는 온도센서를 이용하여 온도 데이터를 수집하여 Serial로 송신하고, Java에서 arduino에서 전송된 온도정보를 Serial로 수신하며, R에서는 Java에서 수신한 데이터를 가공하고 시각화하게 된다.
[Arduino 구성]
온도센서(TMP 36)를 사용하여 온도 측정할 수 있는 회로를 구성 하였다.
- Arduino 구성 참조 링크 : http://www.oomlout.com/oom.php/products/ardx/circ-10
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를 활용하였다.
- RXTX 공인 사이트 링크 : http://rxtx.qbang.org
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
- 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 통신 종료 코드 임.
[실행결과]
관련파일 :
참조 링크 : thermometer-R-using-Arduino-Java
'Big-Data > R Language' 카테고리의 다른 글
R 둘러보기 (0) | 2013.11.09 |
---|