読者です 読者をやめる 読者になる 読者になる

熊小屋日誌

Windows 10 UWPやXamarin, Python、mbed/NetMF/Arduino/Edison, Azureなどぼちぼちと。たまにPCや勉強会、セミナーなどの話題も

BluetoothによるWindows Phoneとデバイスの連携

Windows Phoneとデバイスの連携 - mbed編

Windows Phone Advent Calendar 2013の10日目の記事です。

BluetoothによるWindows Phone 8とmbedと呼ばれるワンボードマイコンの連携について、備忘録を兼ねてまとめます。

mbed: 手軽なワンボードマイコンのプラットフォーム

最近、mbedと呼ばれるワンボードマイコンのプラットフォームに関心があって、ときどきいじっています。mbedはマイコンのチップと、その入出力につながったピン、プログラムのバイナリデータをUSBメモリのようにドラッグ&ドロップで書き込むための補助チップなどから構成されます。

mbedの特徴は以下が挙げられるかと思います。

  • オンラインIDEによるプログラムの開発(コード作成、コンパイル、バージョン管理など)。
  • C/C++によるプログラム作成。
  • 多くの公開ライブラリを利用可能。
  • マイコンボードへのプラグラムの転送が簡単。
  • USBにPCに接続するとメモリとして見えるので、モジュールをドラッグ&ドロップで書き込める。
  • ソースコードやWikiを公開できるコミュニティサイト。

mbedは、ボードに搭載された機能の異なる各種のプラットフォームが提供されていて、無線LANが搭載されていたり、またはLPC810やLPC1114Fn28のようなICそのものもあります。IC単体だと100円前後、評価ボードのものは4000-5000円もあれば買えます。なかでも、NXPから出ているLPC1768がお手軽で、情報も多いかと思います。

f:id:kumar:20151013114844p:plain

LPC1768のピン配列図を見るとわかるように、センサーなどを制御するSPI/I2C/Analog/PWM/CANなどの端子に加えて、シリアル通信やイーサネット、USBの端子も出ています。これらの端子にセンサーやコネクタを接続して、制御処理のプログラムを転送すれば、これらの機能を使うことができます。ただし、USBなどはドライバなどがmbedに組み込まれているわけではないので、そこはプログラムに含める必要があります。ただし、上にあげたように機器を制御するライブラリが有志によって公開されているので、それを使えば開発はそう難しくないかと思います。

mbedとセンサーなどの接続ははんだ付けをしなくてもできるため、組み込み機器のプロトタイプ開発を手軽に試すことができると思います。

さて、mbedを使ってデバイスを作ったとき、それを制御したり、それから情報を受け取るための方法が必要で、デバイスにLCDやボタンなどの部品を組み込み方法や、外部から制御する方法があります。後者の場合、無線(WiFi,Bluetooth,NFC,Zigbeeなど)やイーサネットでデバイスとPC・タブレット・スマートフォンを接続して通信することになります。

前置きが長くなりましたが、mbedを制御する方法として、Windows Phoneを使おうというのが今回の趣旨です。

Proximity API (近接通信API)

Windows Phone 8になって、Windows RTのAPIが利用できるようになったのはご存知かと思います。この新しく使えるようになったAPIにProximity API.aspx)があります。日本語でいうと近接通信API。これはNFCやBluetoothによるデバイスや端末との通信を提供するAPIです。

NFCとBluetoothはどちらも電波を使った非接触での通信技術ですが、端末と対象機器との距離に違いがあります。NFCは10㎝程度の近距離での通信のため、対象にかざすように使う必要があります。一方、Bluetoothはクラスにもよりますが10mから100mまでと離れていても利用可能です。

そこで、Bluetoothを使ってデバイスと連携する方法を見ていきます。

Bluetoothでのデバイス連携

Windows Phone 8でサポートされているBluetoothのプロファイルは以下の通りです(Windows Phone 8でのBluetooth.aspx)より)。

  • Advanced Audio Distribution Profile (A2DP 1.2)
  • Audio/Video Remote Control Profile (AVRCP 1.4)
  • Hands Free Profile (HFP 1.5)
  • Phone Book Access Profile (PBAP 1.1)
  • Object Push Profile (OPP 1.1)
  • Out of Band (OOB) および Near Field Communications (NFC)

PCなどのホストとデバイス間のBluetooth通信は、通常はシリアルポートを仮想化したSPP(Serial Port Profile)を使うのですが、このリストに入っていません。はじめは、Windows Phone 8ではデバイスとの連携が不可なのか…と思っていたのですが、Object Push ProfileはRC-232Cを仮想化したRFCOMMの上に構成されているので、RFCOMMを使ったシリアル通信ができるだろうと思って試してみました。

f:id:kumar:20151013114854j:plain (Object Push Profileから引用)

(後日談) Nokiaのドキュメント(Bluetooth Services for Windows Phone)を読むと、RFCOMMによる通信が可能って書いてありました…。

RFCOMMでの通信方法

Windows Phone 8

MSDNライブラリの"Windows Phone 8でのBluetooth.aspx)"の「デバイスへの接続」に、Bluetoothデバイスとの接続方法のコードが書かれています。

RFCOMMでのBluetoothデバイスとの通信は、このコードにおいて、接続対象の機器としてシリアル通信のサービスである"{00001101-0000-1000-8000-00805F9B34FB}"を指定するのがポイントです。

private async void AppToDevice()
{
   PeerFinder.AlternateIdentities["Bluetooth:SDP"] = "{00001101-0000-1000-8000-00805F9B34FB}";
   var pairedDevices = await PeerFinder.FindAllPeersAsync();

   if (pairedDevices.Count == 0)
   {
      // 機器が見つからなかった場合
   }
   else
   {
      PeerInformation selectedDevice = pairedDevices[0]; // ここでは1番目の機器と接続
      StreamSocket socket = new StreamSocket();
      await socket.ConnectAsync(selectedDevice.HostName, "1"); // RFCOMMのポート1
      DoSomethingUseful(socket); // socketを使って通信
   }
}

接続に成功したら取得したStreamSocketのInputStreamとOutputStreamを使って、デバイスとのシリアル通信を行います。このとき、何らかの手順をアプリとデバイスの間で決めておく必要があります。

注意点として、WMAppManifest.xmlで"ID_CAP_PROXIMITY"と"ID_CAP_NETWORKIN"を設定する必要があります。

切断する場合は、上記のsocketに対してDispose()を呼びます。

...
socket.Dispose();
...

簡単なサンプルプログラム"BTRFCommDevTest"をgithubに登録しました。画面に入力された文字列をBluetoothデバイスに送信して、Bluetoothデバイスから受信した応答を表示するものです。例外処理、画面遷移処理、多言語対応などは手抜きです。

mbed

mbedでの準備は以下の3ステップが必要です。

  1. Bluetoothドングルの接続
  2. Bluetoothスタックの実装
  3. シリアル通信のデータ処理プログラムの実装

それぞれ順に見ていきます。

(1) Bluetoothドングルの接続

BluetoothドングルはBuffaloのBSBT4D09BKを使いました。USBのAコネクタからPC内部のピンに接続するコネクタ(QIコネクタ)に変換するケーブルを使って、LPC1768を載せたブレッドボードに接続します。

f:id:kumar:20131209230359j:plain

USB端子の各ピンは、以下のようにLPC1768のピンと接続します。

f:id:kumar:20151013114851p:plain

なお、QIコネクタをブレッドボードに挿すための変換基盤は自作です。

f:id:kumar:20131210010235j:plain

(2) Bluetoothスタックの実装

Bluetoothスタックはmbed.orgのリポジトリで公開されているmyBlueUSBを利用します。これはSDPとRFCOMMを実装したスタックで、プログラムの形になっています。受信したシリアル通信データを処理する箇所を書き換えて利用します。

ただし、最新版では一部のファイルが削除されてコンパイルできないため、rev12からファイルを持ってきて追加しました。他にも複数のBluetooth機器があるときに接続がうまくできない問題へのパッチも当てています。この対策版をmyBlueUSB_localfixとして公開しています。

これをオンラインIDEに取り込んで、コンパイルして生成されたbinファイルをLPC1768に転送します。

(3) シリアル通信のデータ処理

上記のプログラムでは受信したシリアルデータをそのままエコーバックする処理になっています。もし独自の処理を加えたい場合は、TestShell.cppの285行目以降は修正します(まだ未検証ですが…)。

            state = 2;
            //comm = Socket_Listen(SOCKET_RFCOM, 1, echo, 0);  // エコーバック処理をやめる
            incoming = new btserial(1);
        }
        break;
        case 2:// main loop
                if (incoming->readable() > 0){
                    int c = incoming->getc();
                       // ここに処理を入れる(はず)
                    // putc(c, stderr);
                    // incoming->putc(c);
                }
                /*else if (incoming->readable()<0){
                   state = 3;
                   printf("end of session");
                   delete incoming;
                 }*/
            break;

実行結果

実際にmbed(LPC1768)とWindows Phone 8(Lumia 620)をBluetoothで接続してみました。上記の"myBlueUSB_localfix"と"BTRFCommDevTest"を使います。時間の都合でWP8から送信したデータをmbed側がエコーバックするだけです。

まずWP8でmbedとペアリングしておきます。PINは1234です。

f:id:kumar:20151013114901p:plain

f:id:kumar:20151013114903p:plain

f:id:kumar:20151013114906p:plain

接続済みになりますが、いったん切断しておきます。

次に、BTRFCommDevTestを起動して、接続ボタンを押します。Searchボタンを押すとシリアル通信で接続できるBluetoothデバイスを探索して、一覧に表示します。

f:id:kumar:20151013114908j:plain

mbedを選択してConnectボタンを押して接続を完了します。

f:id:kumar:20151013114910j:plain

バックキーで元の画面に戻って何か文字列を送信すると、mbedでエコーバックした文字列が表示されています。

f:id:kumar:20151013114911j:plain

このとき、mbed側のデバッグログには以下が出力されていて、実際に入力した文字列"Hello world"を受信しているのが判ります。

userData refers to rfcomm SocketHandler, state = 2
Calling RFCOMMManager::SerServer
SerServer:  16: 0B FF 17 00 48 65 6C 6C 6F 20 77 6F 72 6C 64 86
OnRfCommControl sock = 2, state = 2, length = 16
RFCOMM: EA=1, C/R=1, D=0, ch=1; control=FF (P/F=1); length=11
payload: 11: 48 65 6C 6C 6F 20 77 6F 72 6C 64
Got 0 credits
RX: address 0b, control ff: 0000 48 65 6C 6C 6F 20 77 6F 72 6C 64                Hello world
Echo: socket 1, state 2, len=11
echo back: len=11, data[0]=48
ACLSend: 23: 2A 20 13 00 0F 00 41 00 09 EF 17 48 65 6C 6C 6F 20 77 6F 72 6C 64 40
echo: 11: 48 65 6C 6C 6F 20 77 6F 72 6C 64

Windows Phoneから見たmbed

mbedを使ったデバイスの制御をWindows Phoneで行う方法を見てきましたが、逆に見るとmbedはWindows Phoneのセンサー/デバイスを拡張できる存在と言えます。

Windows Phoneに搭載されたセンサー/デバイスは限られたものしかなく、また搭載されているセンサー/デバイスの使える機能が限られていることがよくあります。そのようなWindows Phoneに新しいセンサー/デバイスを追加してその能力を拡張するために、mbedなどで作成したデバイスとBluetoothなどで連携する方法が使えると思います。

長々と書きましたが、この話はWindows 8.1やAndroid、またWindows Phone 8でもブログ記事など情報が出回っていて、それほど新鮮味はありませんね(汗)。でも、Windows Phone 8でも同じことができることを知っておいていただければ幸いです。

参考情報

mbedとのBluetooth通信は、以下のブログを参考にさせていただきました。

Windows 8.1ストアアプリでのBluetooth通信は以下が参考になります。