index
自作マイコンボードとAndroidスマートフォンの無線接続

最初に作成したTobaccoアプリケーションを改造して、Bluetoothによるデータ通信ができるようにします。

*Bluetoothの予備知識

Bluetoothは、よくこなれた技術なので、優れた解説がネットワークに多数掲載されています。詳しい説明は、検索して調べてください。ここでは、開発で必要な最低限の解説をします。

複数のデバイスとの無線ネットワークを作ることができます。ただし、ここでは、1対1の接続を前提としたアプリケーションを作ります。モジュール1台毎に割り当てられているBluetooth IDを使って、1対多通信に拡張することも可能です。

*実機デバッグの準備

アプリケーションソフトウエアやファームウエアのデバッグには、Bluetoothターミナルソフト(ASCIIとHEXが表示可能なもの)をインストールしておくと便利です。これらのソフトはGooglePlayで各種無料公開されています。例えば、S2 Terminal for Bluetooth (ターミナルソフト)(無料版)があると便利です。ただし、このターミナルソフトは、SPPのみに対応していますので、他のプロファイルを使う機器とは通信できません。

*ユーザインタフェースの変更

センサシステム用に Tobacco の activity_main.xml にテキストとボタンを追加します。

3. Androidアプリケーションの作成のところでは、on Click プロパティに実行するメソッドを設定していましたが、このやり方だと、Javaコードを見たときに、何のイベントに対するメソッドか読みにくいので、別の方法を使います。このため、on Click プロパティの設定は削除します。

また、editText(入力欄)は、数値だけ入力するように限定していましたが、コマンドには文字を使ったほうが、人間が分かり易いため、文字も入力できるように、Input Typeを変更します。Single Lineというのは文字数が多くなって、画面に表示しきれなくなっても、行を増やさないプロパティ、Ellipsizeは、文字オーバしたときの省略表示方法を決めるプロパティです。

Revised layout

下記のように、プロパティを変更します。
属性1行目左テキスト1行目右テキスト2行目中央エディットテキスト2行目右ボタン3行目右テキスト4行目左ボタン4行目右ボタン5行目ボタン6行目ボタン
idtextAddresstextAddressBoxeditTextInputBoxbutton5textOutputBoxbutton1button2button3button4
textMsg:no connection変更なし(空欄)CLR0ContunuousOne-shotCommandStop
textSize181818181818181818
textStyleBoldBoldBold変更なしBold変更なし変更なし変更なし変更なし
layout_width80dpmatch_parentwrap_content80match_parentmatch_parentmatch_parentmatch_parentmatch_parent
gravity変更なしleftleft変更なしright変更なし変更なし変更なし変更なし
paddingLeft変更なし6dp変更なし変更なし変更なし変更なし変更なし変更なし変更なし
paddingRight変更なし変更なし変更なし変更なし6dp変更なし変更なし変更なし変更なし
textColor変更なし#FFFFFF変更なし変更なし#00FFFF変更なし変更なし変更なし変更なし
background変更なし#000000変更なし変更なし#000000変更なし変更なし変更なし変更なし
maxLength変更なし変更なし32変更なし変更なし変更なし変更なし変更なし変更なし
inputType変更なし変更なしtext変更なし変更なし変更なし変更なし変更なし変更なし
onClick空欄空欄空欄空欄空欄空欄空欄空欄空欄
ellipsize変更なしmarquee変更なし変更なしmarquee変更なし変更なし変更なし変更なし
singleLine変更なしtrue変更なし変更なしtrue変更なし変更なし変更なし変更なし

*メニューの作成(XMLの入力)

デバイスとの接続、通信エリア内のデバイスのブロードキャスト、接続の終了はいつも使うわけではないので、メニューに表示するようにします。これまでは、Design view画面(GUI)に、文字やボタンを配置してXMLファイルを作成していましたが、ここでは、XMLファイルを編集してみます。メニューを表示するためのメソッドは、MainActivity.javaの中で記述します。

  1. Project欄上部の表示モードのドロップダウンリストから Project を選択(他のモードの場合、以下の説明と微妙にファイルの表示配置が異なる)
  2. 左のProject欄で、app/src/main/res を選択
  3. resを右クリックして、ポップアップメニューから、New - Android resource directoryを選択
  4. New Resource Directoryフォームで、Directory name: = menu, Resource Type: = menu に設定してOKボタンをクリック
  5. Project欄に app/src/main/res/menu が作成される
  6. Project欄で、menu を選択
  7. 右クリックして、ポップアップメニューから、New - Menu resource fileを選択
  8. File name: 欄に option_menu を入力して(任意のファイル名でよい)、OKボタンをクリック
  9. app/src/main/res/menu の下に option_menu.xml が作成されるので、これをダブルクリックしてView欄に表示する
  10. View欄下のタブで、DesignからTextに切り替える
  11. XMLの内容が表示されるので、menuタグの中に、次のitemタグを入力
    文字列の内容が不明、といったエラーが表示されるが、後で、メッセージの内容を app/src/main/res/values の下の strings.xml というファイルの中で定義するので、このエラーは無視してよい。
    
        <item
            android:id="@+id/scan"
            android:title="@string/connected"
            android:icon = "@android:drawable/ic_menu_search"
            />
        <item
            android:id="@+id/discoverable"
            android:title="@string/discoverable"
            android:icon = "@android:drawable/ic_menu_mylocation"
            />
        <item
            android:id = "@+id/disconnect"
            android:title = "@string/disconnect"
            android:icon = "@android:drawable/ic_menu_close_clear_cancel"
            />
    
    
*接続先選択画面の作成(XMLファイルのコピー)

メニューと同様にして、app/src/main/res/layout の下に device_list.xml と device_name.xml を作成します。

  1. 左のProject欄で、app/src/main/res/layout を選択
  2. layoutを右クリックして、ポップアップメニューから、New - Layout resource file を選択
  3. File name: 欄に device_list を入力して(任意のファイル名でよい)、OKボタンをクリック
  4. app/src/main/res/layout の下に device_list.xml が作成される
  5. 同様にして、app/src/main/res/layout 野下に device_name.xml を作成する
  6. XMLを直接書いてもよいが、ここでは、予め用意されたサンプルXMLファイルをダウンロードして、下記の各場所にコピーする。コピーは、Project欄の app/src/main/res 配下の下記に示した位置に、ドラッグ&ドロップし、Overwrite を選択

    ファイル(ダウンロード)コピー先XMLの内容
    device_list.xmlapp/src/main/res/layout接続可能なデバイスリストを作成するための画面
    device_name.xmlapp/src/main/res/layout接続可能なデバイスを表示するための画面
    strings.xmlapp/src/main/res/valuesプログラム中で使用するメッセージやタイトルなどをXMLにまとめたもの

*Bluetoothパーミッションの設定

Bluetooth機能をアプリケーションで使用するためには、BLUETOOTHかBLUETOOTH_ADMINのパーミッションをアプリケーションに与える必要があります。アプリケーションが使用するパーミッションやリソースの管理は、マニフェストファイルで行います。

  1. 左側のProject欄で、app/src/main/res/AndroidManifest.xml をダブルクリックして開く
  2. manifestタグ内に、下記のパーミッションを追加
    uses-sdkでは、このアプリがインストールできるプラットフォーム(最小SDKバージョン)を指定しています。uses-permissionでは、Bluetoothとweb表示の使用に必要なパーミッションを追加しています。
    <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="18"/>
    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> 
    <uses-permission android:name="android.permission.INTERNET"/> 
    
*通信用プログラムの作成

通常、通信機能を利用するアプリケーションは、接続/解除手続き、送信処理/受信処理、各種エラー処理を同時にこなすため、複雑な手順になります。Android SDKでは、簡単に開発ができるようになっていますが、それでも長いプログラムになるため、基本的な機能だけを記述したソースファイルをインポートして、必要に応じて手を加えることにしましょう。Javaファイルは新規作成して、コピペしてもかまいません。必要なファイルは、下記の3個です。前に作成した、MainActivity.java は削除してかまいません。尚、これらのソースコードの一部は、Android SDKのサンプルに含まれているBluetoothChatに手を加えたものなので、著作権表示は削除しないでください。(Copyright © 2009 The Android Open Source Project, and revised unnder Apache License 2.0)

[参考] ここでは、Android SDKを使用していますが、Bluetooth通信用のライブラリを公開しているサイトもあります。通信ライブラリを使用すると、非常に簡単に実装できる可能性があります。ただし、自作デバイスとの通信に都合の良い送受信メソッドがライブラリに用意されているとは限りません。

  1. 左側 Project 欄で、app/src/main/java/jp.merl.tobacco をクリックして選択
  2. 右クリックして、メニューより、New - Activity - Empty Activity を選択
  3. Activity Name:= DeviceListActivity, Generate Layout File のチェックを外して、Finishボタンをクリック
  4. 再度、app/src/main/java/jp.merl.tobacco を右クリックして、メニューより、New - Java Class を選択
  5. Class Name: = BluetoothService として、OKボタンをクリック
  6. 以上で、DeviceListActivity と BluetoothService が、Project欄に追加表示される
  7. DeviceListActivity と BluetoothService の内容は、以下のファイルをダウンロードして、各ファイルを、app/src/main/java/jp.merl.tobaccoにドラッグ&ドロップし、Overwrite を選択

    ファイル(ダウンロード)ファイルの内容
    MainActivity.java前に作成したメインアクティビティの内容にBluetooth通信による受信処理と画面操作に対する処理を追加。
    DeviceListActivity.java接続可能なデバイスリストを作成し、接続するまでの手続きを行うアクティビティ。
    BluetoothService.java接続手続きおよびサーバソケットを提供するスレッド。各アクティビティと並列に動作させる。

アクティビティは、マニフェスト(AndroidManifest.xml)に登録する必要があります。基本形は、<activity android:name=".アクティビティ名"/> となります。先頭にピリオドがあることに注意してください(正式なパッケージ名 jp.merl.tobacco.DeviceListActivity が省略されていることを示している)。
  1. app/src/main/res/AndroidManifest.xml を開き、DeviceListActivity に対応した方の <activity 〜 /> の記述を、下記のように修正
    ここでは、MainActivityとは異なるダイアログ向けのテーマを設定した。
    BluetoothService.javaのほうは、独立したアクティビティを持たないので、マニフェストに登録しなくてよい。
        <activity android:name=".DeviceListActivity"
                  android:theme="@android:style/Theme.Dialog" >
        </activity>
[参考] メインアクティビティの表示時に、アクションバーまたは画面が表示されない場合は、メインアクティビティクラスの宣言で、継承されているクラス(extends の後)が、app/src/main/res/values/styles.xml に設定されたテーマと整合しているか確認してみてください。また、マニフェストに登録したアクティビティ名が、エラーになる場合は、各アクティビティのjava記述の最初のほうに記述されているパッケージ名が正しいか確認してみてください。

*処理内容の概要

ソースプログラムは、時間のあるときに、全体をじっくり読んで理解してもらうことにして、ここでは、大まかな流れと、やや複雑なところに絞って説明します。

*変更の際のヒント

各自のアプリケーションの合わせて、手をを加える必要があると予想される部分を抜粋して説明します。

  1. マイコンで実行するコマンド
    MCUに対して発行するコマンドは、MCUのファームウエアと一致させる必要があります。間違えないよう、MainActivityクラスの最初のほうで定数宣言してあります。command は、エディットテキスト入力欄に、入力出されたコマンドライン送信するためのバッファ減数

    MainActivity.java
        // PSoC Command Table
        private static final String Continuous = "meas\r";		// Continuous measurement
        private static final String OneShot	   = "sample\r";	// One-shot measurement
        private static final String Stop       = "stop\r";		// Stop measurement
        private static final String Reset      = "reset\r";		// Reset PSoC configuration
        private String command = null;				// Command Line string
    
  2. リクエストコード
    アクティビティ(画面)を増やした場合は、リクエストコードをまとめて定義しておきましょう。数値は、重ならなければ何でもかまいません。

    MainActivity.java
        // Intent request codes
        private static final int REQUEST_CONNECT_DEVICE = 1000;
        private static final int REQUEST_ENABLE_BT = 2000;
    
  3. イベントリスナの振り分け先
    Continuous() 以降は、イベントリスナが振り分けた処理内容のメソッドを集めてあります。

  4. 自機のデバイス名とプロファイルに対応するUUIDは、BluetoothServiceクラスの先頭にまとめてあります。

    BluetoothService.java
        // Name for the SDP record when creating server socket
        private static final String NAME = "AndroidNexus";
    
        // Unique UUID for SSP(Serial Port Profile)/RFCOMM
        private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    
  5. メニューのリスナ
    MainActivity.java のonOptionsItemSelected(MenuItem item)を参照

  6. データの送信
    MainActivity.java のsendMessage(String message)から送信します。送信バッファもイベントとして扱われているため、自動的に文字が表示されるようになっています。必要なければ、イベントハンドラ内のhandleMessageにおける MESSAGE_WRITE に対する処理を全てコメントアウトします。特に、MCU側から受信命令のエコーを返す場合は、送信データを表示しないようにしてください。

  7. データの受信
    受け取った文字列をそのまま表示しているため、数値化する場合は、イベントハンドラ内のhandleMessageにおける MESSAGE_READ に対する処理を追加する必要があります。String readMessageを数値に変換する例は、「データ処理とグラフ表示」の項で説明します。
*実機動作の手順

Bluetooth通信が使えるPCかスマートフォンがもう1台あれば、双方にターミナルソフトをインストールし、1byte文字か数字を送受信し正しく送れるかテストします。テスト用のPCかスマートフォンが無い場合は、友達にターミナルソフトをインストルしてもらって実験しましょう。

操作手順

  1. アプリケーションを起動
  2. BluetoothをONにしてよいか聞かれるので承認する
  3. メニューで、Make discoverableを選ぶ(自機を相手が検索できるようにする)
  4. メニューで、Connect a deviceを選ぶ(ペアリングしたことのあるデバイス情報を表示する)
  5. Scan for devices をタッチ(ペアリングしたことのないデバイスにブロードキャストする)
  6. 応答したBluetoothデバイス名とBluetooth IDがリストに表示される
  7. 相手のデバイスと思われるものをタッチ(RBT-001は、EasyBTというデバイス名になっている。デバイス名はコマンドモードで変更可能)
  8. しばらくすると接続が確立したというメッセージが表示される
  9. 通信開始
最初の接続(ペアリング)では、PINコード(パスキー)を聞かれるかもしれません。初期値のままだと、普通は、0000か1234となっています。うまく起動したら、製作したMCUボードで接続の実験をしてみてください。MCUボードは、まだ入力信号がありませんが、命令に対するエコーを帰すようになっていますので、送信した文字が文字化けせずに表示されれば成功です。

MCUボードとの接続が可能で、何らかの応答があるけれども、帰ってくる文字がおかしいという場合は、Bluetoothモジュールが壊れているか、バッテリーが消耗している可能性がありますので、チェックしてみてください。ただし、最初の接続時には、Bluetoothモジュールがマイコンに出力したバイナリメッセージがそのまま返信され、文字化けして表示される可能性があります。うんともすんとも言わないようでしたら。まず回路の配線間違いや半田付けの失敗をテスターの導通チェック機能を使ってチェックしてみてください。

Bluetooth search and connection


index

お問い合わせはこちらまで: kitagawa@is.t.kanazawa-u.ac.jp

© Kanazawa Univ., 2013