2012年10月30日火曜日

[Java][AVR]MacのJavaでAVRとシリアル通信したい

AVRで作ってるI/Oボードで取得したセンサーのデータを扱うのは、現状JavaでやりたいのでMac上のJavaでシリアル通信出来るようにする。

Javaでシリアル通信を行うライブラリにRxTxという物があるのでこれを使います。GNUライセンスです。

まず、古い方の公式サイトからrxtx-2.1-7-bins-r2.zip (Final)をダウンロードしてきます。
さらっと少し上にダウンロードサイトが移動した旨が書いてありましたが気づきませんでした。
新しい方のサイトも見てみましたが、書いている時点で安定版のバージョンは同じ様です。

ダウンロードしたzipファイルを解凍して出来たディレクトリの中のINSTALLの内容の

Mac OS X (x86 and ppc) (there is an Installer with the source)
RXTXcomm.jar goes in /Library/Java/Extensions
librxtxSerial.jnilib goes in /Library/Java/Extensions
Run fixperm.sh thats in the directory. Fix perms is in the Mac_OS_X
subdirectory.

に従って、
解凍したディレクトリの中にあるRXTXcomm.jarと、Mac_OS_Xディレクトリの中にあるlibrxtxSerial.jnilibを、
/Library/Java/Extensionsにコピーします。
最後のfixperm.shを実行するよう言ってますが、無いので飛ばします。

とりあえず前準備は終わったので、Eclipseでサンプルプロジェクトを作ってみます。
適当なプロジェクトを作成し、プロジェクトのプロパティの Javaのビルドパス-ライブラリー外部Jarの追加で先程コピーしたRXTXcomm.jarを指定してあげます。

ポートを開き、受信した文字を出力するだけのプログラムを書いてみます。
AVRのプログラムは、ただHello World!!を出力し続けるだけです。
import java.io.IOException;
import java.io.InputStream;
import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.UnsupportedCommOperationException;


public class Sample {
 
 public static final void main(String[] args){
  try{
   
   CommPortIdentifier portID = CommPortIdentifier.getPortIdentifier("/dev/tty.usbserial-A400FMPJ");
   SerialPort port = (SerialPort)portID.open("Sample", 5000); //waiting5000ms
      
   port.setSerialPortParams(19200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
   port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
   
   InputStream is = port.getInputStream();
   
   int c;
   while((c = is.read()) != -1){
      Calendar cal = Calendar.getInstance();
      System.out.print(cal.get(Calendar.SECOND) + "." + cal.get(Calendar.MILLISECOND));
      System.out.println("->" + (char)c);
   }
   is.close();
   port.close();
  }catch(NoSuchPortException e){
   System.err.println("Can Not Find Device");
   e.printStackTrace();
  }catch(PortInUseException e){
   System.err.println("Can Not Open Device");
   e.printStackTrace();
  }catch(UnsupportedCommOperationException e){
   System.err.println("Invalid Parameter");
   e.printStackTrace();
  }catch(IOException e){
   e.printStackTrace();
  }catch(Exception e){
   e.printStackTrace();
  }
 }
}


簡単に説明を行うと
15行目
CommPortIdentifier portID = CommPortIdentifier.getPortIdentifier("/dev/tty.usbserial-A400FMPJ");
getPortIdentifierの引数には下の画像にあるように、開きたいデバイスのパスを与えます。



16行目
SerialPort port = (SerialPort)portID.open("Sample", 5000);
第一引数にはポートを開くアプリケーション名, 第二引数にはポートが他のアプリケーションに使用されていた場合にポートが解放されるのを待つ待ち時間(ms)です。

18行目
port.setSerialPortParams(19200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
第一引数から、ボーレート, データビット数, ストップビット数, パリティの種類です。

19行目
port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
フロー制御の設定を行います。

あとは、通常のJavaの通常の入出力プログラムです。 それぞれの例外は、エラーメッセージの通りだと思います。

実行してみると、
java.lang.UnsatisfiedLinkError: /Library/Java/Extensions/librxtxSerial.jnilib:  no suitable image found.  Did find:  /Library/Java/Extensions/librxtxSerial.jnilib: no matching architecture in universal wrapper thrown while loading gnu.io.RXTXCommDriver
Exception in thread "main" java.lang.UnsatisfiedLinkError: /Library/Java/Extensions/librxtxSerial.jnilib:  no suitable image found.  Did find:  /Library/Java/Extensions/librxtxSerial.jnilib: no matching architecture in universal wrapper
ってエラーを吐きました。
調べてみると、先程ダウンロードしたlibrxtxSerial.jnilibは32bit用でJavaは64bitで実行される事によるエラーのようです。
なので、実行の構成からVM引数-d32を与えて32bitで実行してあげると解決します。
また、根本的な解決として64bit対応のライブラリに置き換える方法もあります。
arduinoのgoogle codeに、64bit用のライブラリがありましたのでダウンロードし置き換えてあげて下さい。

先程のエラーは解決できましたが、
gnu.io.PortInUseException: Unknown Application
 というエラーが出ました。
調べるとRxTxの排他制御の為のディレクトリが必要という情報がありましたので、ターミナルで
sudo mkdir /var/lock
sudo chmod 777 /var/lock
でディレクトリを作成してあげて、再度実行すると


無事、データの受信を確認しました。


Java Communications APIの使い方

0 件のコメント:

コメントを投稿