Funnel勉強中。まとめてみる。
写真はFIOv1.3+XBee(チップアンテナ型)+EIC-801+リチウムイオンポリマー電池(1000mAh)の組み合わせ
2009/04/24現在のバージョンは009です。
IAMASの小林茂先生が考案したフィジカル・コンピューティング・ツールキットがGainer。その無線版。
公式サイトはここ
開発状況はここ
名前の由来はここ
Funnel専用I/Oモジュール(Fio)だけなく、XBee, Gainer, ArdinoなどいろいろなI/Oモジュールを利用できる。基本的にどれもXBee経由。よって、
-XBee単体 -XBee+Fio
の2つでやってみた。
PC<-USB->(エクスプローラUSB(XBee)) ------ (XBee)
------
利点)fioなしで始められる。コンパクト
欠点)ポート数が少ない。電源を制作しなければならない。そのままではブレッドボードに刺さらない。
PC<-USB->(エクスプローラUSB(XBee)) ------ ((XBee)Fio)
------
利点)ポートが多い。電源がある。ブレッドボードに刺さる。
欠点)XIOより大きい。
※この情報は2009/04/24時点のものです。
※XBeeの抜き差しや配線の変更は必ず電源を切って行うこと。
※リチウムリチウムイオンポリマー電池の取り扱いには十分注意すること。間違えると発火・爆発します
http://funnel.cc/Hardware/FIO
をよく読んでそろえる。私が購入したものは以下のとおり
1.FIOは購入直後はピンソケットがないので用意して半田付けする。
2.FIO:電源スイッチ近くのはんだジャンパを閉じる。
3.XBee Explorer USBまたはXBee starter kit:RTSとD3の間をジャンパで接続する。
一晩待つ^^;
以下はWindows用。macの場合は公式サイトを参照のこと。ダウンロードしたら解凍する。40002637_c.exeはインストールする。
1.XBeeエクスプローラとUSBケーブルを使ってXBeeをUSBに接続。
2.差し込むだけとUSB Serial Portとして自動的に認識される。
3.コントロールパネル>システム>デバイスマネージャにてポート(COMとLPT)にUSB Serial Portが正常に表示されていることを確認。この場合はCOM7。
4.ついでにCOMポート設定を変更しておく。(Windowsのみ)
4.1. デバイスマネージャからCOMポートのプロパティを表示する
4.2. 「詳細設定」ボタンを押して設定画面を開く
4.3. 「その他のオプション」で「クローズ時のRTS設定」をチェックする
5.X-CTUを起動。
6.modem configurationのreadを押してXBeeの接続を確認。ここでファームウェアが1.0.C.Dではなかったらwriteしてファームウェアをアップデート。
7.hardware/fio/xbee/coordinator_auto_reset.proをloadしてコーディネータ(PCに接続した)側にアップロード
8.XBeeを交換。
9.modem configurationのreadを押してXBeeの接続を確認。ここでファームウェアが1.0.C.Dではなかったらwriteしてファームウェアをアップデート。
10.hardware/fio/xbee/enddevice.proをエンドデバイス(FIOに搭載した)側にアップロード
11.XBeeを交換。
※この設定ファイルではPAN IDは1234,コーディネータIDは0,エンドデバイスIDは1になっている。複数で勉強するときはこれらの値を必要に応じて変える。
1.FIOにエンドデバイス側に設定したXBeeを付ける。向きに注意!
2.XBeeエクスプローラとUSBケーブルを使ってコーディネータ側XBeeをUSBに接続。
3.Arduino-0015を起動
※vistaでrduino-0015が動かない場合はフォルダ内のjavaディレクトリを削除する。vistaにjavaが入っていれば起動する。入っていなければvista対応のjavaを別途入手する。
4.Tools/Board/Arduino Pro or Pro Mini (8MHz)を選択する
5.Tools/Serial Portで適切なシリアルポートを選択する
6.File/Sketchbook/Openからfunnel_009/hardware/fio/firmware/FioStandardFirmata?/FioStandardFirmata?.pdeを開く。
7.FIOの電源を入れる。
8.すぐにUploadボタンを押してファームウェアをアップロード
※結構失敗します。シリアルポートの速度(19200が適当のはず)などを確認してうまくいくまで何回も試してみる。
9.FIOの電源を切る。
1.funnel_009/serverのsettings.txtを以下のようにする。
server: port: 9000 io: type: Fio port: COM7 baudrate: 19200
※COM7は各自の環境によって変わります。
2.FIOの電源を入れる。
4.Funnel Server.exeを起動する。正常に起動していれば
Funnel 009 BETA (r588) I/Oモジュールと接続中です… baudrate: 19200 I/Oモジュールと接続が完了しました:COM7 API MODE: 2 FIRMWARE VERSION: 10CD (XBee 802.15.4) PAN ID: 1234 SOURCE ADDRESS: 00 コマンドポート:サーバの起動中… コマンドポート:サーバが起動しました:9000 Discovering nodes... NODE: MY=1, SH=13a200, SL=40526a6c, dB=45, NI='FIO #1' Firmata Protocol Version: 2.0 Discovering nodes...
と表示される。
※特にFirmata Protocol Version: 2.0が表示されているか確認。
1.Processing1.0.3を起動。ホームディレクトリにProcessingフォルダができていることを確認。
2.Processing/libraries/funnel/libraryを作成しfunnel_009/libraries/processing/libraryの中身をコピーする。
3.Processing/libraries/funnel/library/settings.fio.txtを
server: port: 9000 io: type: Fio port: COM7 baudrate: 19200
としてCOMポート番号を指定する。
※シリアルポートは各自の環境によって変わります。
1.可変抵抗を以下のように接続する。(わかりにくいけどA0ピン)
2.ホームディレクトリのProcessingフォルダに以下のディレクトリを作成し以下のソースを作成する。
SimpleScopeFIO/SimpleScopeFIO.pde
SimpleScopeFIO/Scope.pde
import processing.funnel.*; final int id = 1; // end device ID final int kChannles = 3; // the number of channels to display Fio fio; PFont myFont; Scope[] scope; void setup() { size(340, 35+150*kChannles); frameRate(30); myFont = createFont("CourierNewPSMT", 12); textFont(myFont); int[] moduleIDs = {id}; fio = new Fio(this, moduleIDs, Fio.FIRMATA); scope = new Scope[kChannles]; for (int channel = 0; channel < kChannles; channel++) { scope[channel] = new Scope(30, 35+150*channel, 200, 100, "A"+channel); } } void draw() { background(0); for (int channel = 0; channel < kChannles; channel++) { scope[channel].updateAndDraw(fio.iomodule(id).analogPin(channel)); } }
/** * A simple oscilloscope class */ import processing.funnel.*; class Scope { private int l; private int t; private int h; private float values[]; private int index = 0; private int points = 200; private String title; Scope(int l, int t, int w, int h, String title) { this.l = l; this.t = t; this.h = h; this.points = w; this.title = title; values = new float[this.points]; } public void updateAndDraw(IOModule.Pin pin) { values[index] = pin.value; smooth(); textSize(12); text(title, l - 24, t - 8); text("1.0", l - 24, t + 8); text("0.0", l - 24, t + h); text("val: " + pin.value, l + points + 8, t + 8); text("max: " + pin.maximum, l + points + 8, t + 20); text("min: " + pin.minimum, l + points + 8, t + 32); text("avg: " + pin.average, l + points + 8, t + 44); // draw outlines stroke(200); noFill(); beginShape(); vertex(l - 1, t - 1); vertex(l + points, t - 1); vertex(l + points, t + h); vertex(l - 1, t + h); endShape(CLOSE); // draw the signal stroke(255); beginShape(); for (int i = 1; i < points; i++) { vertex(l + i, t + h - values[(index + i) % points] * (float)h); } endShape(); index = (index + 1) % points; } }3.Processing1.0.3を起動。
※この情報は2008/09/18時点のものです。
※XBeeの抜き差しや配線の変更は必ず電源を切って行うこと。
http://funnel.googlecode.com/files/funnel_008b5.zip
processingはビルド0148(2008-09-11時点の最新安定板)を使用。
libraries/processing/library
の
funnel.jar
javaosc.jar
を
processing-0098/libraries/funnel/library
に入れる。(ディレクトリがなければ作成)
設定に関してほかのパラメータをいじったことがあればrestoreして初期設定に戻す。
1:1の通信を行う。
コーディネータ(ホスト)側 ATID 1111 <-PAN(グループ)ID ATDH 0000 ATDL 0002 <-相手のID ATMY 0001 <-自分のID ATAP 2 <-APIモードの設定 エンドデバイス(クライアント)側 ATID 1111 <-PAN(グループ)ID ATDH 0000 ATDL 0001 <-相手のID ATMY 0002 <-自分のID ATD0 2 <-ピン20をアナログ入力AD0に設定 ATIT 5 <-ここで指定したサンプル数ごとに送信 ATIR 64 <-サンプリング間隔(0x64 = 100ms)
レスポンスが悪い!と思ったら…
エンドデバイス(クライアント)側 ATIT 1 <-ここで指定したサンプル数ごとに送信 ATIR 0A <-サンプリング間隔(0x0A = 10ms)
settings.yamlを次のようにする
server: port: 9000 io: type: XBee com: COM3 <-ここはコーディネータをつなげているCOMポート番号を指定 baudrate: 9600
エンドデバイス側の回路を組む際の注意点
電源電圧は必ず2.8〜3.4Vの範囲で使用→5Vを加えるとモジュールが破壊!
Vref(14番ピン)はVCC(1番ピン)に接続→A/D変換のための基準電圧
以下のメッセージを確認
Funnel 008 BETA (r465) I/Oモジュールと接続中です… baudrate: 9600 I/Oモジュールと接続が完了しました:COM3 Configuring the XBee module... コマンドポート:サーバの起動中… コマンドポート:サーバが起動しました:9000 FIRMWARE VERSION: 10a5 (XBee 802.15.4) API MODE: 2 SOURCE ADDRESS: 01 PAN ID: 1111
以下のスケッチを作成。フォントはサンプルのものを流用する。
/* analog in */ import processing.funnel.*; XBee xbee; PFont myFont; void setup() { size(400,130); myFont = loadFont("CourierNewPSMT-24.vlw"); textFont(myFont, 24); int[] moduleIDs = {2}; xbee = new XBee(this,moduleIDs); } void draw() { background(0); text("analogInput[0]: " + xbee.iomodule(2).port(0).value,10,80); }
可変抵抗のつまみを回すと、値が0.0から1.0で変わる。ヤフー:-D
値が震えていたりしたらエンド・デバイスの電源を切って、14番ピンに基準電圧(+3.3V)をとっているか確認すること。
XBee単体をエンドデバイスにするとどうしても電源レギュレータも用意しないといけないので配線がややこしい。
IMU 5 DOFモジュール
http://www.sparkfun.com/commerce/product_info.php?products_id=741
ATID 1111 <-PAN(グループ)ID ATDH 0000 ATDL 0001 <-相手のID ATMY 0002 <-自分のID ATIT 1 <-ここで指定したサンプル数ごとに送信 ATIR 0A <-サンプリング間隔(0x0A = 10ms) ATD0 2 <-ピン20をアナログ入力AD0に設定 ATD1 2 <-ピン19をアナログ入力AD0に設定 ATD2 2 <-ピン18をアナログ入力AD0に設定 ATD3 2 <-ピン17をアナログ入力AD0に設定 ATD4 2 <-ピン11(注意!)をアナログ入力AD0に設定
XBee単体でやってみた。
以前に比べて3.3vレギュレータと電源スイッチそして配線を整理してある。
(そのうちここに回路図を入れる)
※XBeeなどの3.3vで動くモジュールには3.4v以上の電圧を与えないこと!
以下のスケッチを作成。フォントはサンプルのものを流用する。
/** * SimpleScope XBee */ import processing.funnel.*; final int kChannles = 5; // the number of channels to display final int kPoints = 200; // the number of points to display final int id = 2; // end device ID XBee xbee; PFont fixedWidthFont; float values[][]; int index = 0; void setup() { size(400, 700); frameRate(30); fixedWidthFont = loadFont("CourierNewPSMT-12.vlw"); values = new float[kChannles][kPoints]; for (int channel = 0; channel < kChannles; channel++) { for (int i=0; i < kPoints; i++) { values[channel][i] = 0; } } int[] moduleIDs = { id }; xbee = new XBee(this, moduleIDs); } final int kLeft = 35; final int kTop = 25; final int kHeight = 100; void draw() { background(0); smooth(); for (int channel = 0; channel < kChannles; channel ++) { int offset = channel * 130; textFont(fixedWidthFont); textSize(12); text("analogInput(" + channel + ")", kLeft - 24, kTop - 8 + offset); text("1.0", kLeft - 24, kTop + 8 + offset); text("0.0", kLeft - 24, kTop + kHeight + offset); text("val: " + xbee.iomodule(id).port(channel).value, kLeft + kPoints + 8, kTop + 8 + offset); text("max: " + xbee.iomodule(id).port(channel).maximum, kLeft + kPoints + 8, kTop + 20 + offset); text("min: " + xbee.iomodule(id).port(channel).minimum, kLeft + kPoints + 8, kTop + 32 + offset); text("avg: " + xbee.iomodule(id).port(channel).average, kLeft + kPoints + 8, kTop + 44 + offset); values[channel][index] = xbee.iomodule(id).port(channel).value; // draw outlines stroke(200); noFill(); beginShape(); vertex(kLeft - 1, kTop - 1 + offset); vertex(kLeft + kPoints, kTop - 1 + offset); vertex(kLeft + kPoints, kTop + kHeight + offset); vertex(kLeft - 1, kTop + kHeight + offset); endShape(CLOSE); // draw the signal stroke(255); beginShape(); for (int i = 1; i < kPoints; i++) { vertex(kLeft + i, kTop + kHeight - values[channel][(index + i) % kPoints] * (float)kHeight + offset); } endShape(); } index = (index + 1) % kPoints; }
ブレッドボードを大きく動かす(ここがポイント)と、それぞの値が変わる。実際に角度を出す時は得られた値を積分する(足し合わせる)ため、小さく動かしても値の変化はそれほどない。だから向きを変えたから値が変わるということではない。今回の場合は
0 -> x-accel 1 -> y-accel 2 -> z-accel 3 -> x-rate 4 -> y-rate
で、動作を確認してみた。