Raspberry Pi で Wii コントローラを認識させる準備

Wiimote という python スクリプトがあって、これを使うとさっくりと Wii コントローラーを試せます。となるハズです。「ハズです」というのは、どうやら Wii コントローラ自体の個体差があって、すんなり繋がったり繋がらなかったりするらしいんですね。ちなみに、私の手元の Wii コントローラは「Wii MotionPlus INSIDE」というやつなのですが、すんなり繋がらないほうです。

Raspberry Pi – How to use a Wiimote! – YouTube
https://www.youtube.com/watch?v=bO5-FjLe5xE&list=UUfY8sl5Q6VKndz0nLaGygPw

にある通り、

– Bluetooth ドングルを RasPi に差しておく
– git clone https://github.com/the-raspberry-pi-guy/Wiimote でサンプルコードを取得
– sh setup.sh で bluetooth 関連を apt-get する
– python wiimote.py を起動したら、Wii コントローラの 1,2 ボタンを同時押ししてペアリングを行う。

そうすると、うまく接続できればペアリングが実行されて、各種のボタンを認識します。

ペアリングできない

しかし、私の手元にあるもので試すと、何度やってもペアリングができません。lsusb で確認したりしたのですが、No wiimotes found となって、認識しません。

Wii コントローラ自体が壊れているのかと思ったのですが、hcitool scan をすると MAC ID が取得できます。

ちなみに、実は Wii MotionPlus の場合は 1+2 ボタンの同時押しではペアリングできなくて、後ろの Sync ボタンを押さないとペアリングできないそうです。youtube の画像は 1+2 ボタンの同時押しでうまくいっているので、北米版と日本版との違いとか販売時期で違いがあるのかもしれません。手元にあるのは去年の夏に買ったものです。

CWiiDを直接調べる

最終的に使うのは、python ではなくて、C# から使いたいので、先の setup.sh でインストールしたライブラリを直接使う必要があります。

sudo apt-get update
sudo apt-get install --no-install-recommends bluetooth -y
sudo apt-get install python-cwiid

wiimote は、ライブラリに python-cwiid を使っていて、これが cwiid を使っています。

CWiiD – Community Help Wiki
https://help.ubuntu.com/community/CWiiD
abstrakraft/cwiid
https://github.com/abstrakraft/cwiid

github にコードが公開されているので、ビルドし直すかデバッグを入れればなんとかわかるだろうと思ったわけです。
cwiid 自体のビルドにちょっと苦労しましたが、以下のようにパッケージをインストールしておけば ok です。現在の RasPi は Gtk3 が入っているのですが、cwiid は Gtk2 を要求するので、パッケージを改めていれておきます。

apt-get install flex bison libgtk2.0-dev

で、結論から言えば、libcwiid/process.c にある process_write 関数での wiimote->rw_status の判別をコメントアウトしてしまいます。

cwiid/process.c at master ・ abstrakraft/cwiid
https://github.com/abstrakraft/cwiid/blob/master/libcwiid/process.c#L284-L287

int process_write(struct wiimote *wiimote, unsigned char *data)
{
        struct rw_mesg rw_mesg;
/*
        if (wiimote->rw_status != RW_WRITE) {
                cwiid_err(wiimote, "XXX Received unexpected write report");
                return -1;
        }
*/
        rw_mesg.type = RW_WRITE;
        rw_mesg.error = data[0];

        if (write(wiimote->rw_pipe[1], &rw_mesg, sizeof rw_mesg) !=
          sizeof rw_mesg) {
                cwiid_err(wiimote, "RW pipe write error");
                return -1;
        }

        return 0;
}

どうやら、手元にある wii コントローラだと wiimote->rw_status の値が RW_WRITE にならないみたいなのです。すんなり動くパターンもあるので、どこかのコードの判別だと思うのですが、ひとまず、ここをコメントアウトしてしまうと普通に通るようになります。

wmdemo で試してみる

これも 1+2 同時押しが効かない関連なのかもしれませんが、手元のものだと自動検索が効かないらしく Wii コントローラーの MAC アドレスを直接指定します。先に hcitool scan で探し出しておいた MAC ID を引数にして起動します。

wmdemo 8C:CD:E8:6B:B4:3A

そして、Wii コントローラの裏にある Sync ボタンを押すと、無事ペアリングが行われます。LED が常にちかちかした状態になってしまうのは、このあたりの不具合のせいなのかもしれませんが、一応ボタンなどのデータが取れます。

受信データは、以下のコメントアウトを戻せば表示されます。

cwiid/thread.c at master ・ abstrakraft/cwiid
https://github.com/abstrakraft/cwiid/blob/master/libcwiid/thread.c#L59-L62

データ長さは、4バイトか6バイトのようです。-/+ ボタンや方向ボタンを押すとビットが変わるので、これを取れば他のプログラムと連携することができます。

Windows で動く wiimote がある

あれこれと探していたら、以下に C# での実装がありました。

Managed Library for Nintendo’s Wiimote | Coding4Fun Articles | Channel 9
http://channel9.msdn.com/coding4fun/articles/Managed-Library-for-Nintendos-Wiimote
Managed Library for Nintendo’s Wiimote – Home
http://wiimotelib.codeplex.com/

試してみると、私の wii コントローラでは動かない(コード自体は wii remote 対応らしく微妙に違うみたい)のですが、コードがあるのでなんとかなりそうです。

ちなみに、Windows 8.1 では wii コントローラは認識されます。

Bluetooth でのペアリングで、PIN コードは何のか?と悩んだのですが、「何もいれない」まま次へボタンを押せば ok です。PIN コードが設定されていないので、そのままペアリングが成功します(むしろ、入れるとエラーになります)。

Bluetooth での認識では、Nintendo RVL-CNT-01-TR となっていて、サービスは、HID になっていますね。いくつか調べていくと、HID と SPP と両方が対応しているようなので、RasPi の cwiid では SPP を使っているような感じがします。このあたりは、PS3 の Dualshock3 のコードと後から見比べてみます。

デバイス – Windows app development
https://msdn.microsoft.com/ja-jp/library/windows/apps/bg182882.aspx#one

にストアアプリから HID を扱う方法があるのですが、これがそのまま wii コントローラで使えるかどうかは謎です。

Dolphinで実機のWiiリモコン(周辺機器)を使う – GC+Wiiエミュレータ Wiki*
http://wikiwiki.jp/gcwiiemu/?Tips_Connect_RealWiimote

Wii エミュレータをインストールして、ドライバー部分だけ使うっていう方法もあるみたいなんですが、動作確認はしていません。
Windows 10 だと Bluetooth 周りが楽になっているハズなので、そっちのほうは後で確認。

追記 Wii リモートで接続

気になったので、中古で Wii Remote を買ってきました。そうすると、あっさりつながりますね。managed 版の wiimote もあっさり認識するので、使うならばこっちのほうが良さそうです。これの話は後日。

カテゴリー: RaspberryPi パーマリンク

Raspberry Pi で Wii コントローラを認識させる準備 への5件のフィードバック

  1. shin のコメント:

    勉強になります。
    どうか↓の件CwiiD本家にfeedbackしていただけないでしょうか?
    >で、結論から言えば、libcwiid/process.c にある process_write 関数での >wiimote->rw_status の判別をコメントアウトしてしまいます。

    あちこちで新しいコントローラが動かないという報告(悲鳴)を見かけます。
    また、CwiiDのビルドの方法もご解説いただけますと助かります。
    以上、お願いばかりで申し訳ありません。

    • masuda のコメント:

      そうですね。
      libcwiid/process.c の件は、あまりにも暫定的なのと、日本で売っている Wii コントローラーだけの問題っぽい(海外では話題になってなさそう)なので、どうなのかなと思っていたのですが、プルリクを出しておきます。Windows の認識具合も違うので、大幅にファームまで変えてしまったのかなと勘繰っています。

      「CwiiDのビルドの方法」のほうは、後でまとめてみますね。libgtk2.0-dev を入れることと、ビルドするために autoconfig とか gcc のための make 環境を整えるところです。

  2. shin のコメント:

    masuda様
    どうもご返答有難うございます。
    wiiUについてきたリモコンがだめなので、wiiリモコンプラスがだめなのかと考えていました。

    とりあえず中古wiiリモコン注文しました。:-)

    ホワイトボードもやってみたいのでぜひともご経験を分けていただければありがたいです。

  3. gun のコメント:

    はじめまして。
    以前私も新旧のコントローラで使えるようにならないか試行錯誤していました。
    Windows7でwiimotelibというのを使っていたのですが、旧型のRVL-003ではなんの問題もなく使えていましたが、Wii Motion PlusのRVL-036では制限がありすぎて挫折しました。
    新型の方は東芝スタックでしか永久ペアリングができずBluetoothモジュールが皆無だったこと。
    もう一つは、永久ペアリングした後は、Wiiリモコンのボタンを押すと、切断されていても自動的に接続して欲しかった(OS起動直後など)のですが、旧型+Microsoftスタックでは自動接続できたのですが、東芝スタックでは自動接続ができず、そこで新型を使うのは諦めました。
    海外のフォーラムとかもたまに調べるのですが、新型が広まってからは結構諦めムードで開発も止まってしまった感じで残念です。
    また時間ができたら細かく調べてみようかと思っています。
    ちなみに旧型ではPINコードにMACアドレスを登録するとあまりスタックに関係なく永久ペアリングできましたが、新型は東芝スタックでしかできません。その他も色々と問題があって出来合いのライブラリでは厳しいですね。
    スタックとか気にせず使えるようにしたいです。
    長文失礼しました、、。

    • masuda のコメント:

      情報をありがとうございます。
      なるほど、Wiiコントローラ内で実際に新旧があるんですね。cwiid では、チェックが厳しくなってエラーになっているので、上記の対処をすると少し使えるようになるんですが、自動ペアリングもそれ絡みなのかなと思っています。
      Wii リモコンがうまく使えるようになると、VR 系のコントローラとしての利用価値もあるし(中古で2個でも大した値段ではないので)、もうちょっと突っ込んで調べてみようかなとは考えているんですが。
      多分、コードは github 残っているだろうから、「CwiiDのビルドの方法」あたりを1年越しに再開しますか。

コメントは停止中です。