Hatena::ブログ(Diary)

Imaginable Reality

2014-07-15

Processingでシリアルポートの設定が簡単になるライブラリ「SerialSelector」を作りました

f:id:kougaku-navi:20140715163342p:image:w600

ProcessingでArduinoやXBeeと通信するプログラムを作っているとたびたびシリアルポートがらみのエラーに出くわします。大抵の場合、ポート番号や通信速度が正しく設定されていないことが原因なのですが、プログラムでポート番号を「COM1」とか「/dev/tty.usbmodem1234」とか「Serial.list()[3]」みたいな感じで直接書いていたりするとこの問題が起こりがちです。

この問題に関して以前から「実行中にポート番号や通信速度を自由に変更できるUIがあるといいのに!」と思っていたので、ライブラリを作りました。


SerialSelectorライブラリ

SerialSelectorはProcessingにおいてシリアル通信の設定ダイアログを表示するためのライブラリです。WindowsでもMacでも動作します。


ダウンロード:

 こちらのページに置いてます: BACKYARD - 工学ナビ


使い方

使い方は簡単です。ダウンロードしたファイルを解凍すると中に「SerialSelector.pde」というファイルが入っています。このPDEファイルがライブラリ本体で、これを自分のスケッチに追加して使用します。Processingで編集中のコード領域にそのままpdeファイルをドラッグ&ドロップすればファイルが追加されて「SerialSelector」というタブが表示されます。

SerialSelectorではドロップダウンリストの表示にControlP5ライブラリを使っています。ProcessingにControlP5がインストールされていない場合は、ProcessingのSketchメニューから「Import Library...」→「Add Library...」とたどり、表示されたリストの中からControlP5を選択してインストールしてください。


以下に実際に使うときのサンプルコードを示します。

import processing.serial.*;

SerialSelector selector;

void setup() {
  size(400, 300);
  selector = new SerialSelector(this); // SerialSelectorの準備
  selector.show(); // 設定ダイアログの表示
}

void draw() {
  /* 描画処理 */
}

// マウスクリックで設定ダイアログを表示する
void mouseClicked() {
  selector.show();
}

// 受信イベント
void serialEvent(Serial port) {  
  Serial selected_port = selector.getSerial(); // 選択されているシリアルポートの取得

  // 受信イベントが発生したポートが選択中のポートだったらデータを取得
  if ( port == selected_port ) { 
    if ( port.available() > 0 ) {
      int recv_data = port.read();
      print(char(recv_data));
    }
  }
}

書き方について説明します。まずSerialSelector型の変数を宣言し、setup()のなかでnewします。newするときの引数はthis(PAppletのインスタンス)です。シリアルポート設定ダイアログを表示するにはshow()を使います。show()はいつでも使えて、ダイアログを閉じた後もshow()によって繰り返し表示できます。キーボードやマウスの操作によってshow()するようにしておくと良いでしょう。選択されているシリアルポートを取得したいときはgetSerial()を使います。シリアルポートに関する初期化はSerialSelectorの中で行われますので、自分でやる必要はありません。


複数のシリアルポートを同時に扱いたいときは

f:id:kougaku-navi:20140715163341p:image:h350


複数のシリアルポートを扱う場合の例を以下に示します。

import processing.serial.*;

SerialSelector selectror1;
SerialSelector selectror2;

void setup() {
  size(400, 300); 

  // シリアルポートが2個以上あるならば、SerialSelectorを2個作る
  if ( Serial.list().length >= 2 ) {    
    selectror1 = new SerialSelector(this, Serial.list()[0], 9600); // SerialSelectorの準備(初期値も指定)
    selectror1.setTitle("port1");  // タイトルの設定
    selectror1.show();                // 設定ダイアログの表示

    selectror2 = new SerialSelector(this, Serial.list()[1], 9600);
    selectror2.setTitle("port2");
    selectror2.show();
  }
}

void draw() {
  /* 描画処理 */
}

void serialEvent(Serial port) {  
  Serial port1 = selectror1.getSerial();  // 1個目のダイアログで選択されたポート1を取得

  // 受信イベントが発生したのがポート1ならば、受信データを表示する
  if ( port == port1 ) {
    if ( port.available() > 0 ) {
      int recv_data = port.read();
      print(char(recv_data));
    }
  }
}

複数の設定ダイアログがあるとどれがどれだかわからなくなるので、setTile()で個別にタイトルを変えると良いです。また、最初から別々のシリアルポートを選ぶようにしておいたほうが良いので、SerialSelectorをnewするときに初期値を設定しておきます。初期値を設定するにはthisに続いてシリアルポート名と通信速度を書きます。ここでは2個以上のシリアルポートがあるという前提で、Serial.list()[0]とSerial.list()[1]を指定しています。


というわけで

使ってみてバグとか見つけたら教えてくださいー。