WiimoteLibでWii Balance Boardを使ってみたり

長期休暇(現在進行形)中に自堕落な生活をしていたら、体重がヒィィィ(((゚皿゚;)な事に。
っというわけで、バランスWiiボードを使ってGoogle Earth上を歩いていたりしたんですが。
PCでバランスWiiボードを使うのって面白いですねということで、ちょっと自分でもバランスWiiボードの入力を拾ってみました(・∀・)


BluetoothやHID周りを自分でホゲホゲするのも面倒だったので、WiimoteLibを改造してやってみまっしょいという方針で*1
WiimoteLibに関してはにもチョコっと書いていますが(´∀`)
まずはCodePlexからWiimoteLib_1.2_src.zipをダウンロード。
修正内容についてはhttp://wlog.flatlib.jp/バランスWiiボードの解析メモを参考にして。
で、WiimoteLibのソースに手を入れるのは以下の辺り。


まずは、キャリブレーション値の保存領域のため、DataTypes.csへの構造体の追加から。

[DataContract()]
public struct BalanceBoardCalibrationInfo
{
    [DataMember]
    public int A0, A1, A2;
    [DataMember]
    public int B0, B1, B2;
    [DataMember]
    public int C0, C1, C2;
    [DataMember]
    public int D0, D1, D2;
}

[DataContract()]    
public struct BalanceBoardState
{
    [DataMember]
    public BalanceBoardCalibrationInfo CalibrationInfo;
}

ソースにこの2つの構造体を追加して、WiimoteStateクラスのメンバにこの構造体の領域を追加。

[DataContract()]
public class WiimoteState
{
...
    [DataMember]
    public BalanceBoardState BalanceBoardState = new BalanceBoardState();
}

あと、定数定義としてenum ExtensionTypeにBalanceBoardを追加。
他にも宣言しておいた方が良い値があったりしますが、とりあえずベタ値を使うことで(´д`)


で、次はWii Balance BoardとやりとりをするWiimote.csへの修正点。
まずは、接続されたデバイスをWii Balance Boardとして認識するところと、キャリブレーションの値を取るところ。

private void InitializeExtension()
{
...
    else if(buff[0] == (byte)ExtensionType.ClassicController && buff[1] == (byte)ExtensionType.ClassicController)
        mWiimoteState.ExtensionType = ExtensionType.ClassicController;
    else if( buff[ 0 ] == 0x04 && buff[ 1 ] == 0x02 ) // バランスボード追加
        mWiimoteState.ExtensionType = ExtensionType.BalanceBoard;
    else if( buff[ 0 ] == 0xff )    // partially inserted case...reset back to nothing inserted
...
    switch(mWiimoteState.ExtensionType)
    {
        case ExtensionType.BalanceBoard:
            buff = ReadData( REGISTER_EXTENSION_CALIBRATION + 4, 12 );
            mWiimoteState.BalanceBoardState.CalibrationInfo.A0 = ( buff[ 0 ] << 8 ) + buff[ 1 ];
            mWiimoteState.BalanceBoardState.CalibrationInfo.B0 = ( buff[ 2 ] << 8 ) + buff[ 3 ];
            mWiimoteState.BalanceBoardState.CalibrationInfo.C0 = ( buff[ 4 ] << 8 ) + buff[ 5 ];
            mWiimoteState.BalanceBoardState.CalibrationInfo.D0 = ( buff[ 6 ] << 8 ) + buff[ 7 ];
            buff = ReadData( REGISTER_EXTENSION_CALIBRATION + 12, 12 );
            mWiimoteState.BalanceBoardState.CalibrationInfo.A1 = ( buff[ 0 ] << 8 ) + buff[ 1 ];
            mWiimoteState.BalanceBoardState.CalibrationInfo.B1 = ( buff[ 2 ] << 8 ) + buff[ 3 ];
            mWiimoteState.BalanceBoardState.CalibrationInfo.C1 = ( buff[ 4 ] << 8 ) + buff[ 5 ];
            mWiimoteState.BalanceBoardState.CalibrationInfo.D1 = ( buff[ 6 ] << 8 ) + buff[ 7 ];
            buff = ReadData( REGISTER_EXTENSION_CALIBRATION + 20, 12 );
            mWiimoteState.BalanceBoardState.CalibrationInfo.A2 = ( buff[ 0 ] << 8 ) + buff[ 1 ];
            mWiimoteState.BalanceBoardState.CalibrationInfo.B2 = ( buff[ 2 ] << 8 ) + buff[ 3 ];
            mWiimoteState.BalanceBoardState.CalibrationInfo.C2 = ( buff[ 4 ] << 8 ) + buff[ 5 ];
            mWiimoteState.BalanceBoardState.CalibrationInfo.D2 = ( buff[ 6 ] << 8 ) + buff[ 7 ];
            break;
...
    }
}

Wii Balance Boardは0x04a400feから読み込んだ値が0x04 0x02。
キャリブレーションの値は0x04a40024からということですが、一度のReadData()では16バイトまでしかダメみたい(?)なので、12バイトづつ読み込んでいます。
で、DataTypes.csに追加したキャリブレーションの値用フィールドに保存。


続いてHIDのレポートの設定なんですが、これはWiimoteクラスを使うアプリの側でWiimote.SetReportType()の引数を0x32で呼んであげます。
そうするとレポートとして0x32が返ってくるようになるので、ParseInput()にその時の処理を追加します。

private bool ParseInput(byte[] buff)
{
    InputReport type = (InputReport)buff[0];
    
    switch(type)
    {
        case (InputReport)0x32:
            ParseExtension( buff, 16 );
            break;
...
    }
}

0x32の宣言をしてやれっていう話ですが(´д`)
ちなみに、ここにはDecryptBuffer()はいらないです。


で、ParseExtension()内で4つのセンサーの値を取得してあげるっと。

private void ParseExtension(byte[] buff, int offset)
{
    switch(mWiimoteState.ExtensionType)
    {
        case ExtensionType.BalanceBoard:
            int a = ( buff[ 3 ] << 8 ) + buff[ 4 ];
            int b = ( buff[ 5 ] << 8 ) + buff[ 6 ];
            int c = ( buff[ 7 ] << 8 ) + buff[ 8 ];
            int d = ( buff[ 9 ] << 8 ) + buff[ 10 ];
...
    }
}

こんなカンジで修正を入れたWiimoteLibを使って、とりあえず体重の測定はできました(・∀・)*2


さて、減量しないとね…(´・ω・`)
健康のためは1日に10000歩は歩くべきなのですよ。

Wiiフィット (「バランスWiiボード」同梱)

Wiiフィット (「バランスWiiボード」同梱)

PLANEX Bluetooth Ver2.0+EDR対応 Microサイズ USBアダプタ BT-MicroEDR2

PLANEX Bluetooth Ver2.0+EDR対応 Microサイズ USBアダプタ BT-MicroEDR2

*1:そのうちWiimoteLib自体がWii Balance Board対応するでしょうけど(´ω`)

*2:センサーの値から体重の計算方法については、バランスWiiボードの解析メモを参照してくださいな(´・∀・`)