Bluetooth シールドを Android から制御する


20150408_bt_system

前回作成した Bluetooth シールド を Android から制御します。

機能
(1) デジタル出力
Android のボタンを押すと、Arduino の LED が点灯します。
(2) PWM出力
Android のスライドバーを移動すると、Arduino の LED の明るさが変わります。
(3) デジタル入力
Arduino のボタンを押すと、Android で状態を表示します。
(4) アナログ入力
Arduino の可変抵抗を回すと、Android で可変抵抗の値をグラフに表示します。

ソースコード
Arduino 側
Android から Arduino を制御する で作成したスケッチを使用します。

Android 側
Android から Arduino を制御する で作成したアプリをベースにします。
通信部分を USBシリアルから Bluetooth シリアルに変更します。
UI は以前のものを流用します。
20150408_bt_android

github で公開しています。
Arduino_SerialControl
Android_Bluetooth


Bluetooth シールドの基板を作る


概要
Eagle と Sevenmini を使って、Arduino の Bluetooth シールドの基板を作ります。
Bluetooth は、JY-MCU BT BOARD を使用します。
動作確認のために、LEDやスイッチや半固定抵抗も搭載します。
基板作成の手順は、Eagle と Sevenmini を使って電子基板を作る を参照してください。

データは GitHub で公開しています。

Eagle 側の作業
(1) 回路図 (sch) とボード図 (brd) を作成します。
20150408_bt_sch 20150408_bt_brd

(2) Mirror にして、ガーバーデータを出力します。
20150408_bt_gerber

FLASH 側の作業
(1) ガーバーデータを読み込みます。
ハンダ面データ (sol) を「フォト表」に、
ドリルデータ (drd) を「穴」に、
外形データ (out) を「外形表」にします。
(2) 輪郭線抽出を行います。
20150408_bt_flash

Sevenmini 側の作業
(1) 配線の加工
基板を両面テープで固定します。
ミリング用のエンドミルを取り付けます。
CAM-Circuit2 アプリから加工を指示します。
(2) 穴の加工
ドリル用のエンドミル 0.6mm に交換します。
CAM-Circuit2 アプリから加工を指示します。
(3) 外形の加工
今回は基板をそのまま使い、加工せず。
20150408_bt_sevenmini 20150408_bt_pcb

ハンダ付け
(1) 表面の配線を行います。
(2) 部品をつけて、裏面をハンダ付けします。
20150408_bt_front 20150408_bt_rear

動作確認
(1) Arduino にエコーバックのスケッチを書きます。
(2) 通信相手は Android の BT terminal を使用します。
(3) Androidで入力した文字がエコーバックすれば、OKです。

課題
(1) タクトスイッチが USBコネクタ の上にあり接触しそう。
(2) BT BOARD のピンソケットの足が長くなり、機械強度が心配。
こういう実装になったのは、BT BOARD がL型ピンヘッダを使っているため。


JY-MCU BT BOARD の動作確認 – 安定性


JY-MCU BT BOARD の動作確認 – Arduino にて、基本的な確認はできたので、
細かいところも確認します。

20150313_bt_arduino_stability

安定性
Android 端末から連続してデータを送信します。
Arduino に、BT BOARD から受信したデータをエコーバックするスケッチを書きます。
Android 端末で正しく受信したかを確認します。

電気的な接続
BT BOARD は 3.3V信号で、Arduino は 5V信号です。
直結でも動作しますが、レベル変換を行います。
5V -> 3.3V 方向は、過電圧が気になるので、抵抗分割を入れました。
3.3V -> 5V 方向は、スレッシュホールドが気になりますが、レベル変換を行わず、直結しました。

ボーレート
BT BOARD は、デフォルトは 9600 bps です。
ATコマンドでボーレートの変更ができます。
例:115200 bps を設定する

AT+BAUD8

Arduino のハードシリアルの最高速度である 115200 bps を試してみましたが、安定して動作しました。

ソフトシリアル
Arduino のソフトシリアルやAltSoftSerialを使用して、BT BOARD と接続して、安定して動作するか確認しました。
ソフトシリアルは、文字化けが多く、実用に耐えません。
AltSoftSerialは、9600bps では安定して動作しましたが、115200bps では文字化けが発生しました。

9600 115200
ハードシリアル
ソフトシリアル × ×
AltSoftSerial ×

参考
3.3V系-5V系デジタル回路の簡易レベルシフト回路
BluetoothChat の問題と対策
Arduino ソフトシリアルの検証
Arduino AtlSoftSerial の検証


JY-MCU BT BOARD の動作確認 – Arduino


JY-MCU BT BOARD
BT BOARD は、Bluetooth SPP をシリアル通信 (調歩同期) に変換するモジュールです。
端子は、VCC(3.6~6V)、GND、TXD(送信)、RXD(受信) の4本です。
詳細は Bluetoothシリアル変換モジュール(スレーブ) を参照ください。

全体構成
Arduino + BT BOARD と Android 端末で動作確認をします。
JY-MCU BT BOARD の動作確認 – MAC での USB Serial アダプタを、Arduino に置き換えています。
Arduino のハードシリアル端子 (TX, RX) を USB 経由で MAC に接続します。
Arduino のIO端子 (D8, D9) を BT BOARD に接続し、ソフトシリアルを使用します。
BT BOARD は 3.3V信号で、Arduino は 5V信号ですが、短時間の確認なので、直結しています。
なお、ソフトシリアルは負荷が高いと 取りこぼし が発生します。
今回は、簡易的な疎通確認なので、使用しています。
20150304_bt_arduino

動作確認
(1) Arduino側
ハードシリアルとソフトシリアルを使用して、TX – D8, RX – D9 のように通信します。
スケッチは Bluetoothシリアル変換モジュール(スレーブ) を参照ください。

(2) Android 端末
(3) 相互通信
JY-MCU BT BOARD の動作確認 – MAC と同じです。


JY-MCU BT BOARD の動作確認 – MAC


20150304_bt_front

JY-MCU BT BOARD
BT BOARD は、Bluetooth SPP をシリアル通信 (調歩同期) に変換するモジュールです。
端子は、VCC(3.6~6V)、GND、TXD(送信)、RXD(受信) の4本です。
詳細は Bluetoothシリアル変換モジュール(スレーブ) を参照ください。

全体構成
MAC + BT BOARD と Android 端末で動作確認をします。
MAC と BT BOARD は FTDI USB Serial アダプタ を介して接続します。
BT BOARD の TXD、RXD は 3.3V信号で、USB Serial アダプタは 5V信号ですが、短時間の確認なので、直結しています。
20150304_bt_mac

動作確認
(1) MAC側
MAC と BT BOARD を USB Serial アダプタ を介して接続します。
(2) Android 端末
Android 端末に Bluetooth Terminal アプリ を入れる。
(3) 相互通信
Android と BT BOARD を Bluetooth ペアリングする。
キーは「1234」です。
Android から文字を送信して、MAC で受信する。
MAC から文字を送信して、Android で受信する。
相互に通信できることを、確認する。


BluetoothChat の問題と対策


多くの方は Bluetooth の通信には、BluetoothChat をベースにして使っていると思います。
Bluetooth の性能評価をしていたときに、通信抜けがあることに気がつきました。

問題と対策
BluetoothChatService から BluetoothChat に受信データを渡すときに、Handler を介していますが、この部分で、抜けが生じていています。
通常は、BluetoothChatService -> Handler -> BluetoothChat という流れで、受信データは直ちに処理されます。
受信データの到着する間隔に対して、BluetoothChat の処理が遅れると、Handler がキューイングされます。
このとき、BluetoothChatService で用意している受信バッファが1つしかないために、前のHandler のバッファの内容が、次の Handler のバッファの内容に上書きされます。
Handler のバッファは、値を保持するのではなく、アドレスポインタを保持しているようです。
対策としては、受信バッファを複数面にすればいいことになります。
20150310_bluetooth_problem

対策の効果
そこで、受信バッファの面数と、通信の誤り率を、測定してみました。
2台のAndroid端末を用意して、1台は受信したデータをそのまま送信するエコーバックに設定します。もう1台は、数字を1,2,3..と連続して送信して、受信したデータが1,2,3..と連続しているかを照合します。
20150310_bluetooth_system

送信する間隔を1msから100msまで変化させて、受信したデータの誤り率を測定します。
測定結果は、下図のようになりました。
送信間隔30ms以下では、受信バッファの面数により、顕著な違いがあることが分かります。
20150310_bluetooth_result

対策の考察
受信バッファの面数を増やす利点は、分かりましたが。
欠点はないでしょうか。
考えられのは、メモリの使用量です。
受信バッファ1面は、1024バイトなので、1KB強のメモリを使います。
Android 4.0以降では、アプリに使用できるメモリ量は 64MB です。
あまり気にしなくてよさそうです。

なお、実際の運用を考えると、通信で誤りを起こすのは、上記の部分だけではありません。
Bluetooth などの無線経路は不確かなものです。
誤りがあることを前提に、システム全体やアプリを設計すべきですね。

ソースコード
今回の検証に使用したアプリを Gitbhub に公開しています。

BluetoothChatService.java

// 追加
private static final int NUM_PLANE = 32;
// ここまで
...
private class ConnectedThread extends Thread {
    ...
    public void run() {
        // 追加
        byte[][] buffers = new byte[ NUM_PLANE ][ 1024 ];
        int plane = 0;
        // ここまで
        byte[] buffer = new byte[1024];
        int bytes;
        while (true) {
            try {
                // 追加
                buffer = buffers[ plane ];
                if ( plane >= NUM_PLANE ) {
                    plane = 0;
                }
                // ここまで
                bytes = mmInStream.read(buffer);
                mHandler.obtainMessage(
                    BluetoothChat.MESSAGE_READ, bytes, -1, buffer)
                    .sendToTarget();
            }
            ... 

20150310_bluetooth_screenshot_2


Android と Wii リモコンを接続する


20140303wii

Android と Wii リモコンを接続する方法を調べてみた。

概要

Android は、フレームワークとして Bluetooth HID をサポートしており、Bluetooth キーボードやマウスが使用できる。
Bluetooth API では、HID はサポートされていないので、InputManager を経由してキー入力を検出する。
なお、Bluetooth API では、RFCOMM をサポートしており、シリアル通信が可能である。

Wii リモコンは、Bluetooth HID を使っている。
HID といっても、一般的なキーボードやマウスとは異なる、独自の仕様である。

Linux レイヤの変更

CWiid という Linux 用のドライバーがある。
CWiid とは、C言語で記述された Wii の Driver の意味らしい。
BeagleBoard Android に移植した例

ルート化

ルート化して、HID をサポートする。
androhid がソースコードを公開している。

リフレクション

公式の API では、L2CAP をサポートしていないが、内部的には用意されている。

BluetoothSocket.java

static final int TYPE_L2CAP = 3;
BluetoothSocket(int type, int fd, boolean auth, boolean encrypt,
	BluetoothDevice device, int port, ParcelUuid uuid) throws IOException {

これをリフレクションで利用して、Wii リモコンと接続する。

Constructor<BluetoothSocket> construct = BluetoothSocket.class.getDeclaredConstructor( int.class, int.class, boolean.class, boolean.class, BluetoothDevice.class, int.class, ParcelUuid.class );
construct.setAccessible(true);
construct.newInstance( TYPE_L2CAP, -1, false, false, dev, port, null );

BluezIMEFitScales がソースコードを公開している。

Android 4.2

Android 4.2 からリフレクションが使えなくなった。
btif_sock.c で UNSUPPORTED になった。

btif_sock.c

case BTSOCK_L2CAP:
	BTIF_TRACE_ERROR1("bt l2cap socket type not supported, type:%d", type);
	status = BT_STATUS_UNSUPPORTED;
	break;

Connecting to a bluetooth HID device (mouse) using L2CAP


BluetoothLeGatt – Android 4.3


20130729bluetooth

Android 4.3 から Bluetooth 4.0 がサポートされました。

サンプルコードが公開されています。
BluetoothLeGatt.java

試してみました。
残念ながら BLE is not supported で終了します。
エミュレータでは Bluetooth がサポートされれていなので、仕方ないですね。

サンプルコードの簡単な説明

Android 4.3 から追加された BluetoothGatt を使っています。
Gatt とは、Generic Attribute Profile らしい。
Bluetooth 3.0 までを Classic プロトコル、4.0 を Gatt プロトコル と称するようです。

4つのファイルがあります。
(1) BluetoothLeService.java (サービス)
(2) DeviceControlActivity.java (メイン)
(3) DeviceScanActivity.java (デバイス一覧)
(4) SampleGattAttributes.java (属性)

BluetoothChatと同じような構成です。
– BluetoothChat.java (メイン)
– BluetoothChatService.java (サービス)
– DeviceListActivity.java (デバイス一覧)

動画による解説
DevBytes: Bluetooth Low Energy API in Android 4.3
YouTube Preview Image

関連
Android 4.3 のサンプルコード

参考
Bluetooth – wikipedia
GENERIC ATTRIBUTE PROFILE (GATT) – bluetooth.org
Bluetooth Low Energy – android developers


Arduino をはじめよう – FabLab Kannai


20130608fablab_1

2013年6月8日(土)に さくらWORKS<関内> で開催された Arduino をはじめよう にスタッフとして参加しました。
今回は、FabLab Kannai日本Androidの会 横浜支部 ロボット部 の共催で、電子工作の入門編として企画したものです。

Arduino は、電子工作の入門に適したマイコンボードです。
「テクノ手芸」といわれる、ぬいぐるみの目が光るようなクラフトワークから、家電の制御や屋内の環境モニタリングまで、できちゃいます。

内容は。
(1) Arduino 開発環境の説明
(2) 実習:Arduino を使って LED をチカチカさせる。
(3) 実習:Arduino と PC とUSBケーブルを使って通信させる。
(4) Arduino でラジコンカーを作る方法の説明
資料:Arduino でラジコンカーを作ろう
(5) Arduino 以外のマイコンボードの紹介
資料:Arduino だけじゃない

初めて Arduino を使うという人たちが、10名ほど参加しました。
全員 LEDチカチカは成功して、満足して頂けたようです。

20130608fablab_3

20130608fablab_2


キーボードが接続されたことを検出する


0130606input_manager_sample_2

Android 4.1 (API 16) から InputDeviceListener が追加されました。
キーボードなどの入力デバイスが接続されると、InputDeviceListener#onInputDeviceAdded に デバイスID が通知されます。

留意点
キーボードが接続されると、Activity が再起動されます。
これを抑止するには、AndroidManifest.xml の activity に下記を追加します。

android:configChanges="keyboard|keyboardHidden" 

ソースコードは code.google にて公開しています。

参考
JBで追加されたFrameworkの機能InputManagerについて
AndroidManifest.xml − ソフトウェア技術ドキュメントを勝手に翻訳