RN-42XVPを使ったmbedでのBluetooth連携(その5)

Posted by 技術ブログ by Strawhat.net on Monday, January 1, 0001

TOC

RN-42XVPを使ったBluetooth通信プログラミング

BluetoothモジュールRN-42XVPを接続したmbed側のプログラムを作成します。mbedからはRN-42XVPはシリアル通信を行うデバイスに見えるので、プログラムはとても単純です。

:::c
#include "mbed.h"
BusOut leds(LED1, LED2, LED3, LED4);
Serial xbee(p9, p10);    // RN-42XVP

int main()
{
    uint8_t rawData;
    xbee.baud(115200);

    while(1) {
    if (xbee.readable() == 1) {
        rawData = xbee.getc();
        pc.printf("rawData = %02x\n", rawData);
        if (rawData <= 0x0f) {
            leds = rawData;
        }
    }
}

RN-42XVPを接続したTX/RXポートを指定して、Serialクラスをインスタンス化します。このインスタンスのgetc()メソッドで受信した電文データから1バイトを取得します。 その後、受信データが0x00-0x0fに場合に、1-4ビット目に応じたLEDをButOutで一括して点灯・消灯してます。

一方、Windows Phone側はmbedにUSBドングルを接続した以前の記事と同じで、Proximity API(近接通信API)を使って、RN-42XVPと通信を行います。

探索ではPeerFinder.FindAllPeersAsyncメソッドでBluetooth機器の探索を行います。このとき、SPPをサポートした機器を見つけるように指定します。機器が見つかった場合は、StreamSocketを接続して、通信を行うソケットを取得します。

:::csharp
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を使って通信
   }
}

通信の部分ではLED1-4の点灯・消灯をBit1-4に設定して、その値をソケットに書き 込みます。今回は送信のみですが、RN-42XVPからデータを受信する場合もこのソケットのInputStreamを使って行います。

:::csharp
private async Task CommunicateViaRFCOMM(bool[] ledStatus)
{
    if (this.socket == null)
    {
        return;
    }

    byte value = (byte)(
        (ledStatus[0] ? 0x08 : 0)
        | (ledStatus[1] ? 0x04 : 0)
        | (ledStatus[2] ? 0x02 : 0)
        | (ledStatus[3] ? 0x01 : 0));
        
    try
    {
        DataWriter dw = new DataWriter(socket.OutputStream);
        dw.WriteBytes(new byte[] { value });
        var writeBytesSize = await dw.StoreAsync();
        await dw.FlushAsync();
    }
    catch (Exception)
    {
        Disconnect();
    }
    return;
}

動作状況

このようにRN-42XVPを使うと、mbed側のプログラミングが端末側との通信内容の処理に集中できてとても楽になります。また、mbedと通信する端末側も、通常のRFCOMMによる通信と同じ手順です。

Windows 8.1/Windows Phone 8.1と連携するガジェットの開発では、このような通信モジュールを利用していきたいです。

サンプルプログラムの公開

mbed側のサンプルプログラム"RN-42XVPsample"をmbedのユーザサイトで、Windows Phone側のサンプルプログラム"RN-42XVP Test"をGitHubでそれぞれ公開しています。

なお、今回はWindows Phone 8.0をターゲットにしたSilverlightプログラムです。Windows Phone 8.1をターゲットにすると正常に動作しないので、原因が分かったらその原因や対応方法を紹介したいと思います。