2011年11月2日水曜日

【使い方編】AndroidのUSBホストを使ってArduinoとシリアル通信 その2

この投稿へのリンク
前回ここで紹介されているAndroidとArduinoをUSB Host APIを使ってシリアル通信させるソースの動作テストをしました。

今回はメーリングリストでリクエストがあったので、それの使い方編をやろうかと思います。

紹介しているサイトを拙い英語力で読んでいると
http://www.intra2net.com/en/developer/libftdi/
ここで、libftdiのソースやバイナリがあり、
FTDIのドライバの動作について詳しくしりたいならソース読めって感じだった。

あと、rootedな端末であれば
http://android.serverbox.ch/?p=285
ここにドライバをカーネルに入れる方法が書かれてた。


それでは本題。

必要なもの
・Android 3.1以上のタブレット(自分はOptimus Padを使った)
・マイクロUSBからホストAへ変換するコネクタ
自分はOptimusPadに付いてきたものを使用
また、動作確認はしてないですが、Amazonでも売ってる様子
ELECOM Micro-USB(Aメス-MicroA)アダプタ 延長 0.15m ブラック MPA-EMA015BK
USB2.0ホストケーブル Micro-USB(Aメス-MicroB)アダプタ
・FTDI製のUSBシリアル変換チップを使った製品
動作確認したもの
・Arduino Duemilanove
Arduino pro mini 3.3VFT232RL搭載小型USB-シリアルアダプタ
動かないもの
・Arduino Uno
※Arduino UnoはUSBシリアル変換のチップがFTDIのものから変更されているのでそのままでは動きません

ソースのダウンロード
USBシリアル通信の方法はまず紹介しているサイト
Download the Android source
からソースをダウンロードしてきます。

適当に解凍して、Eclipseにプロジェクトをインポート。

FTDI_USBActivity.javaがソースで、こいつがほぼすべて。
private static final String VID_PIDを必要があれば書き換える。
でもおそらくFTDI製のチップであればそのままでも動くはず。

デバイスのVID、PIDの確認
念の為にPCにデバイスを接続して確認してみる。

自分のUbuntu 11.10ではコマンドで、
$ usb-devices
と打てば接続されているUSBデバイスの詳細情報一覧が取得できたので、

## デバイスを接続していない状態
$ usb-devices > usb_none.txt
## デバイスを接続した状態
$ usb-devices > usb_connect.txt
$ diff usb_none.txt usb_connect.txt

を行って差分を見て新しく接続されたデバイスを見つけて
Driver=ftdi_sio
になっているものを探した。

そうすると

< T:  Bus=02 Lev=02 Prnt=02 Port=01 Cnt=01 Dev#= 12 Spd=12  MxCh= 0
< D:  Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
< P:  Vendor=0403 ProdID=6001 Rev=06.00
< S:  Manufacturer=FTDI
< S:  Product=FT232R USB UART
< S:  SerialNumber=A700eYen
< C:  #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=90mA
< I:  If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=ftdi_sio
こんなのが見つかったので、VIDはVendor、PIDはProdIDが一致してたので問題ない。

もし、これでDriverはftdi_sioなんだけどVendorとProdIDが違う製品であれば
FTDI_USBActivity.javaのVID_PIDを変更する必要があります。

アプリの実行
インポートしたプロジェクトを実行

[2011-10-31 23:53:26 - FTDI_USB] ------------------------------
[2011-10-31 23:53:26 - FTDI_USB] Android Launch!
[2011-10-31 23:53:26 - FTDI_USB] adb is running normally.
[2011-10-31 23:53:26 - FTDI_USB] No Launcher activity found!
[2011-10-31 23:53:26 - FTDI_USB] The launch will only sync the application package on the device!
[2011-10-31 23:53:26 - FTDI_USB] Performing sync
[2011-10-31 23:53:26 - FTDI_USB] Automatic Target Mode: using device '192.168.11.3:8000'
[2011-10-31 23:53:26 - FTDI_USB] Uploading FTDI_USB.apk onto device '192.168.11.3:8000'
[2011-10-31 23:53:27 - FTDI_USB] Installing FTDI_USB.apk...
[2011-10-31 23:53:31 - FTDI_USB] Success!
[2011-10-31 23:53:31 - FTDI_USB] /FTDI_USB/bin/FTDI_USB.apk installed on device
[2011-10-31 23:53:31 - FTDI_USB] Done!

実行すると普通のアプリと違いDone!となりそのまま起動しません。
なのでアプリ一覧から起動します。
ちなみにUSBポートはシリアル通信用のデバイスとつないでしまってDDMSからログが見れなくなるので、無線LAN経由でADBが使用できるようにしておくとデバッグが便利です。
やり方としてはPCとAndroidをつないだ状態で
adb tcpip <ポート番号>
と実行し、PCからAndroidを接続を切った状態で(繋がってても問題は無い)
adb connect :<ポート番号>
と実行すればつながるはず。2.X系だとrootedじゃないとダメかも。

なにもAndroidタブレットにつないでいない状態だとlogcatに

11-02 21:34:49.952: D/FTDI_USB(11875): >==< no more devices found >==<

と出力される。
ただ、自分の環境だと変換ケーブルが悪いのかよく認識しなかった。
抜き差ししたりするとたまに治る。

うまいこと認識すると次の画面が出るのでOKを押す


ここで注意!
OpenAccessoryでは接続した瞬間にブロードキャストのIntentが飛んでブロードキャストレシーバーがそれを捕まえることでアプリが自動で立ち上がる仕組みができてましたが、なぜかこのアプリはそれが動きません。Optimus Padが悪いのかサンプルが悪いのかまだ詳しく追っていないのでよくわかりません。
なので、接続する際は次の手順がうまく行きます
USBデバイスを接続 → アプリ起動
この順番を守らないと上記の画面が出てきてくれません。


アプリは1秒間隔で0〜15までを順にカウントアップしています。
なので、今回はテスト用にArduinoに次のようなスケッチを書き込みました。

void setup() {
  Serial.begin(9600);
  pinMode(13, OUTPUT);
}

void loop() {
  int buf;
  
  if (Serial.available()) {
    buf = Serial.read();
    if (buf % 2 == 1) {
      digitalWrite(13, HIGH);
    } else {
      digitalWrite(13, LOW);
    }
  }
 
}

単純に受信したデータを2で割り、あまりが1だったら基盤に実装されているLEDをつけるだけです。
なので、1秒間隔でオンオフを繰り返すようになっています。



こんな感じで比較的簡単に準備は出来ました。
今後はこのサンプルソースを改良してライブラリをちゃちゃっと作っちゃおうかと思います。


#以下アフィリエイト用の広告です