11

AndroidのUSBホスト機能でArduinoとシリアル通信する

超便利なライブラリ作ったのでこっち使うといいです → 橋本商会 » Android版ArduinoFirmataを作った

——-以下本文

なんか意外と簡単にできたし、まったくやってる人の情報が無いので書いておく。


Nexus7+Arduino(Seeduino)+サーボモータ を動かした


AndroidにArduino等のシリアルデバイスを直つなぎできる。
ADKやUSBホストシールドやIOIOと違って、むずかしい回路やプログラムはいらないし、電源もAndroid側から供給もできる。
マイコン側は単純にシリアル通信するだけ。Android側もUSBシリアルポートを探して接続するだけ。


Nexus7にはUSBポートとは別に充電ポートがあるのでそっちで充電させつつ、デバイス制御もできそう

必要な物は3つ

1. USBホスト機能に対応したAndroid端末
2. USBホストケーブル
3. Arduino等のUSBシリアルデバイス


USBホスト機能に対応したAndroid端末

Android 3.1(タブレット用)や4以上の端末はUSBホスト機能がある。
2012年夏ごろからの端末が該当していて、USBホストシールドやADKが必要なくなった。

Galaxy NexusやGalaxy S3以降でAndroid4以上の端末はokのはず。
Googleが各ベンダになるべくUSBホスト機能を持たせるように働きかけているってsonyの人が言ってた。
最近Nexus SにもAndroid4が配信されたけど、チップセットにUSBホストの機能が無いので無理。


USBホストケーブル

ようするに「AndroidにUSBキーボードやマウスを接続できる」と書いてあるケーブルのこと。
これをUSBポートに接続すると、AndroidはUSBホストモードになる。

USBケーブルは普通4ピンだ。VCC、GND、D+、D-ピンの4つ。
USB mini/microから、5ピンになった。IDピンが増えた。
USBホストケーブルを作るには、IDピンとGNDピンをショートさせるだけでいい。


これを買った。ぴったりで良い。


なお自作も可能。S2 » USBホストケーブルとUSBケーブルの違い にくわしく書いてある。
市販のUSB-マイクロUSB変換コネクタを分解して、IDピンを短絡させてる。


昔のArduinoと今後のArduino

Arduino UNO以降は、AVRマイコン内蔵のUSBシリアル機能を使うようになっている。
Arduino Duemillanove以前は、FTDI社のFT232というUSBシリアル変換ドライバICを使っている。
それぞれ違うデバイスドライバが必要だけど、両方対応できるようにAndroidアプリを実装可能。

このGoogle製ライブラリを使えばいい。勝手にデバイス判別してくれる。
ボーレートの設定とかも扱いやすい関数が揃ってて便利。
usb-serial-for-android – Android USB serial and Arduino device host support library. – Google Project Hosting

これを使わなくてもandroid.hardware.usb.UsbDeviceクラスを使えば自分で実装できるが、ソース見てみればわかるけどげんなりする処理が多いのでusb-serial-for-android.jarを使うのが良いと思います。

AndroidでArduinoとシリアル通信する


usb-serial-for-androidのDownloadsメニューからusb-serial-for-android-v010.jarをダウンロードして、Androidアプリのlibsディレクトリに入れる


AndroidManifest.xml のinternt-filterの中に追加
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />


さらにintent-filterと同列にmeta-dataを作る
<meta-data
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />


device_filter.xml を取得する。FTDIチップやArduinoのUSBベンダIDが書いてある。
wget http://usb-serial-for-android.googlecode.com/git/UsbSerialExamples/res/xml/device_filter.xml
mkdir res/xml
mv device_filter.xml res/xml/


接続する。
アクティビティ内で
import java.io.*;
import android.hardware.usb.*;
import com.hoho.android.usbserial.driver.*;

public void onCreate(Bundle savedInstanceState) {
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
UsbSerialDriver usb = UsbSerialProber.acquire(manager);
if (usb != null) {
try{
usb.open();
usb.setBaudRate(9600);
start_read_thread(); // シリアル通信を読むスレッドを起動
}
catch(IOException e){
e.printStackTrace();
}
}
}


Arduino → Android
シリアル通信で受信したデータを読む。ArduinoでSerial.println(“文字列”)したデータがAndroid側で読める。
public void start_read_thread(){
new Thread(new Runnable(){
public void run(){
try{
while(true){
byte buf[] = new byte[256];
int num = usb.read(buf, buf.length);
if(num > 0) Log.v("arduino", new String(buf, 0, num)); // Arduinoから受信した値をlogcat出力
Thread.sleep(10);
}
}
catch(IOException e){
e.printStackTrace();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}


adb logcat | grep arduino
して見てみましょう。受信できているはず。


Android → Arduino
AndroidからArduinoに文字列「o」や「x」送信する。
while(true){
usb.write("o".getBytes("UTF-8"),1);
Thread.sleep(1000);
usb.write("x".getBytes("UTF-8"),1);
Thread.sleep(1000);
}


接続を閉じる。
try{
usb.close();
}
catch(IOException e){
e.printStackTrace();
}


Arduinoにはこんなのを書いておくと、シリアル通信でoとxが来たらLEDを点灯消灯させたりサーボモータを回したりできる。
char led_pin = 13;
char serial_recv;

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

void loop(){
Serial.println(analogRead(0)); // アナログセンサの値をAndroidに送る
while(Serial.available() > 0){
serial_recv = Serial.read(); // シリアル通信を受信
switch(serial_recv){
case 'o':
digitalWrite(led_pin, true); // 基板上のLEDを点灯
analogWrite(11, 200); // サーボ回す
break;
case 'x':
digitalWrite(led_pin, false); // 消灯
analogWrite(11, 20); // サーボ回す
break;
}
Serial.println(serial_recv);
}
delay(10);
}


WiFiでAndroidアプリ開発

ArduinoをAndroidに接続しているとUSBケーブルがさせない。MacからWiFi経由でAndroidにプログラムを書くといい。
Nexus7が同じ無線LAN内の192.168.1.121にあるとする。
設定→タブレット情報→端末の状態 にIPアドレスが書いてある。
AndroidをMacにUSB接続してから
adb tcpip 5555
adb connect 192.168.1.121:5555
adb logcat
USBケーブルを抜く。

あとはもう、adb installもEclipseからのDebug Runも、logcatもWiFiでできるようになってる。


元に戻すには、USBケーブルを接続して
adb usb
これで戻る。


その他の作例

こういうのを作ってる人がいて、参考になった

Android USB Host + Arduino: How to communicate without rooting your Android Tablet or Phone | Using Android in Industrial Automation
android.hardware.usb.UsbDeviceを使ってArduino UNOとシリアル通信している

Android Host – Arduino間シリアル通信の実現 – アトリエのどか
FTDIドライバを使ってArduino Duemillanove以前とシリアル通信してる

0

FT232RLのUSB要求電流量を最大にする

石澤さんに教えてもらったのだが、USBデバイスはホストに「自分が必要な電流量」を申告するようになっているらしい。
ArduinoやGainerやmoxaにも使われていているFT232RLというUSBシリアル変換チップもその設定ができるようになっている。
俺も秋月のFT232RL 基盤実装済みキットを使う事が多い。


■電流量の設定をする
まずFTDIのサイトからMProg(Windows用のみ)をダウンロードしてきてインストールする。
FT232シリーズのドライバももちろんインストールして、仮想COMポートとして認識しているのを確認。


MProgを起動して、
[Device]→[Scan]
[Tools]→[Read and Parse]
で接続しているFT232のデバイス設定が読み込める。
これを一旦ファイルとして保存してから、[File]→[Edit]して編集。
右上のMax Bus PowerをUSBの最大電流量である500mAに設定し、ファイルに保存。最後に[Device]→[Program]で書き込む。
FT232RLでUSB要求電力を最大にする


これでUSBケーブルを刺し直すとドライバが再インストールされ、デバイスとしての要求電流量が増えている。

0

USBカメラフラットモジュール(WR-UC32)のケーブルを作った

先日買ったUSBカメラのケーブルが変なケーブルで気に入らなかったので作った。


市販のUSBケーブルをバラして、赤・黒・白・緑の4本を同じ色同士接続したら動いた。紫は無視していい。
R0010554
この状態だとまずいので後で絶縁するべき。あと今回はこれの中に埋め込むので、もっと短い(10cm弱ぐらいの)ケーブルにする。


カメラ側はコネクタを買いに行くのが面倒だったので付属のケーブルから切断
R0010545


USBは4芯のはずだけど、裏を見ると5芯になっている。テスターで調べてみたら黒と紫は基盤内で両方GNDに通電していた
R0010544


なので、紫はとりあえず接続する必要無し。
赤・黒・白・緑の4つだけ接続した
R0010547