Androidでシリアル通信を利用する


はじめに

Androidでシリアル通信をする方法があまり紹介されていないので記載します。

対象機器

Android
REX-USB60MB (USB-シリアル変換)

対象環境

Android6.0
AndroidStudio
Kotlin

ダウンロード

FTDI社のホームページからJava D2XX Update including FT4222H supportの項目にあるhereをクリックしてライブラリをダウンロードします。
FTDI社のホームページ

ダウンロードした圧縮ファイルを解凍します

ルートフォルダにあるd2xx.jarファイルのみ使用します。
res/xml/フォルダにあるdevice_filter.xmlは中身が古いので使わずに作ります。

d2xx.jarをライブラリに追加

プロジェクトツリーの1番上Androidと表示されている右の▼をクリックして表示される一覧からプロジェクトを選択します。
するとこれまでとは異なるツリー表示になります。

app/libs にd2xx.jarをドラッグアンドドロップで追加します。追加したd2xx.jarを右クリックしてライブラリに追加を実行します。
追加操作と言ってもbuild.grade(app)にimplementation files('libs/j2xx.jar')が追加されるだけです。
ライブラリが不用になればこの1行を消して、libs/j2xx.jarを削除すれば元に戻ります。

d2xx.jarをライブラリに追加し終えたらプロジェクトツリーの1番上プロジェクトになっているのを右の▼をクリックしてAndroidに戻しましょう。

USBデバイスを使用する準備

Androidmanifest.xmlに

manifest.xml
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
            </intent-filter>
            <meta-data
                android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
                android:resource="@xml/device_filter" />
        </activity>

このようにしてUSBデバイスを使用するよう設定します。
@xml/device_filterは使っていませんが念のためです。

認識されているか確認

sample.kt
        var mFTDIManager = D2xxManager.getInstance(this.context)
        var deviceCount = mFTDIManager?.createDeviceInfoList(this.context) ?: 0

この2行で認識出来ているか確認します。
deviceCountが認識したデバイス数なので1以上が入っていれば成功です。

REX-USB60MBが認識されない

サンプルを動作させた人はわかるかと思いますが、実はサンプルではREX-USB60MBを認識しません。
認識しない理由はさきほど古くて使うのを断念したdevice_filter.xmlファイルにあります。

device-filter.xml
    <usb-device vendor-id="1412" product-id="45088" /> <!-- REX-USB60F -->

コメント通りREX-USB60Fは登録されていますがREX-USB60MBはありません。
ではここにREX-USB60MBを定義すれば良いのでは?と思いましたがそれだとさらに上位の機種RS-USB60FCやタブレット用REX-USB60MIを使う時にまた変更が必要など使い勝手が悪くなります。

なので接続されているシリアル通信用デバイスを認識してそれを使うようにしようと思います。

comm.kt
    var usbDevice = mutableMapOf<String,Any>()
    var usbDeviceList : MutableList<MutableMap<String,Any>> = mutableListOf()
        val manager = getSystemService<UsbManager>(context, UsbManager::class.java)
        usbDeviceList.clear()
        if (manager == null) return
        for(item in manager.deviceList) {
            val device: UsbDevice = item.value
            val str : String = device.manufacturerName ?: ""
            val vid = device.vendorId
            val pid = device.productId
            usbDevice = mutableMapOf("vid" to vid,"pid" to pid ,"key" to item.key,"name" to  str)
            usbDeviceList.add(usbDevice)
            mFTDIManager?.setVIDPID(vid,pid)
        }

USBのデバイスはVendorIDProductIDがわかれば動作するようですのでそれさえ得られれば大丈夫なのですが、そのデバイスが何なのかわからないと不安なのでmanufacturerNameも取得出来るようにしています。

使用するデバイスを登録する

使いたいデバイスが認識されないので手動で登録させます。

sample.kt
        var mFTDIManager = D2xxManager.getInstance(this.context)
        mFTDIManager?.setVIDPID(1412,45115)
        var deviceCount = mFTDIManager?.createDeviceInfoList(this.context) ?: 0

setVIDPIDの引数でVendorIDProductIDを渡すと強制的に認識させることができます。
deviceCountの値が1以上であれば成功です。
※1412,45115はREX-USB60MBの値です

参考サイト

参考サイト