KOSAKA LABORATORY->Tips

 このBlogの一部が書籍になりました。
書籍:「WiiRemoteプログラミング」
著者:白井暁彦・小坂崇之・木村秀敬・くるくる研究室
表紙:タナカユカリ
発売:2009年7月25日 好評発売中
詳細:こちらから

内容:WiiRemoteを利用したインタラクティブ技術のプログラミング学習書

 話題の家庭用ゲーム機「Wii」の特徴的なコントローラーである「WiiRemote」をPCで使うプログラミングが注目されている。高性能な加速度センサーや赤外線センサーを持ち、Bluetooth接続が可能で、プログラミング可能なデバイスを、個人レベルで自作したり入手したりすることはできなかった。WiiRemoteの登場とともにそれが安価で手軽に入手可能になり、多くの人々が興味を持っている。

 本書は、WiiRemoteの応用に興味があるプログラミング初学者向けに、WiiRemoteをPCから扱うためのプログラミングを解説する。ハードウェア寄りのゲームプログラミング入門書として、ステップバイステップでソースコードを解説する。具体的なサンプルを開発しながら、インタラクション技術を独習できる。言語はC/C++、C#およびActionScript 3、Processingなどをサポート。

Wiiリモコン バイブレータをPWM制御

 Wiiリモコンにはバイブレータが搭載されており振動を伝えることができます。以前、解説したプログラムでもバイブレータのON/OFF制御を行ってきました。しかし、バイブレータの動作は、ON/OFFのみで強弱はありません。
 今回は、バイブレータの振動に強弱をつけるプログラムについて説明します。
1.ピクチャボックスの追加
1.フォームにラベル(Label)とスクロールバー(HScrollBar)を張り付けてください。

2.貼り付けたhScrollBar1プロパティのLargeChaneを「1」に設定する。
3.貼り付けたhScrollBar1プロパティのMaximumを「5」に設定する。
2.タイマーの追加
1.フォームにTimerを張り付けてください。

2.貼り付けたtime1プロパティのIntervaltを「1」に、button1のプロパティのTextを「切断」に設定する。

3.タイマーイベントの追加
1.timer1をダブルクリックし、以下のプログラムを追加する。
        //タイマー 指定したミリ秒毎に実行される
        private void timer1_Tick(object sender, EventArgs e) {
            this.label1.Text = this.hScrollBar1.Value+"";//ラベルに値を表示

            if (count < this.hScrollBar1.Value) {
                this.wm.SetRumble(true);                              //バイブレータON
                this.wm.SetLEDs(15);                                  //LED ON
            } else {
                this.wm.SetRumble(false);                             //バイブレータOFF
                this.wm.SetLEDs(0);                                   //LED OFF
            }
            count++;                                                  //カウントを増やす

            //指定以上になるとカウントを0に戻す
            if (count >= hScrollBar1.Maximum) { count = 0; }
        }
4.Wiiリモコン赤外線プログラム
Form1.csに以下の部分を追加する。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using WiimoteLib;                                                      //WimoteLibの宣言

namespace WiimoteLib_Sample {
    public partial class Form1 : Form {

        int count = 0;//カウント

        Wiimote wm = new Wiimote();                                    //Wiimoteの宣言
                
        public Form1() {
                        
            InitializeComponent();
            
            //他スレッドからのコントロール呼び出し許可
            Control.CheckForIllegalCrossThreadCalls = false;
        }

        //接続ボタンが押されたら
        private void button1_Click(object sender, EventArgs e) {
            this.wm.Connect();                                        //Wiimoteの接続
            this.wm.SetReportType(InputReport.IRExtensionAccel, true);//レポートタイプの設定
            this.timer1.Enabled = true;                               //タイマー開始
        }

        //切断ボタンが押されたら
        private void button2_Click(object sender, EventArgs e) {
            this.timer1.Enabled =false;                               //タイマー終了
            this.wm.SetRumble(false);                                 //バイブレータOFF
            this.wm.Disconnect();                                     //Wiimote切断
        }


        //タイマー 指定したミリ秒毎に実行される
        private void timer1_Tick(object sender, EventArgs e) {
            this.label1.Text = this.hScrollBar1.Value+"";//ラベルに値を表示

            if (count < this.hScrollBar1.Value) {
                this.wm.SetRumble(true);                              //バイブレータON
                this.wm.SetLEDs(15);                                  //LED ON
            } else {
                this.wm.SetRumble(false);                             //バイブレータOFF
                this.wm.SetLEDs(0);                                   //LED OFF
            }
            count++;                                                  //カウントを増やす

            //指定以上になるとカウントを0に戻す
            if (count >= hScrollBar1.Maximum) { count = 0; }
        }

    }
}
実行

1.WiiRemoteを接続してください。

 

2.F5キーを押して実行してください。

 

3.接続ボタンをクリックしてください。
  ※もしエラーが発生する場合はWiiRemoteが正しく接続されているか確認してください。

 

4.スクロールバーをスクロールさせてください。

 左にスクロールし値を0にするとバイブレータがOFFになり、右にスクロールさせるとバイブレータが振動します。

 

解説

 Wiiリモコンのバイブレータを簡易PWMを用いて0~5の6段階で制御(しようと)しています。PWMとはPulse Width Modulationの略です。簡単に説明すると電源のONとOFFを高速に繰り返すことによって制御する方式です。詳しい説明は各自調べてみてください。

 本プログラムではWiiリモコンのLEDが光っている時にバイブレーションをONにしています。

        //タイマー 指定したミリ秒毎に実行される
        private void timer1_Tick(object sender, EventArgs e) {
            this.label1.Text = this.hScrollBar1.Value+"";//ラベルに値を表示

            if (count < this.hScrollBar1.Value) {
                this.wm.SetRumble(true);                              //バイブレータON
                this.wm.SetLEDs(15);                                  //LED ON
            } else {
                this.wm.SetRumble(false);                             //バイブレータOFF
                this.wm.SetLEDs(0);                                   //LED OFF
            }
            count++;                                                  //カウントを増やす

            //指定以上になるとカウントを0に戻す
            if (count >= hScrollBar1.Maximum) { count = 0; }
        }
 timer1_Tickは、timerで指定したInterval値ミリ秒毎に呼び出される関数です。1000ミリ秒は一秒です。今回、Interval値は1ですので、1ms秒毎(1000Hz)に呼び出されます。
 count値が呼び出されるごとにカウントされていきます。そしてその値がHScrollBar1の値を超えた時に、バイブレータをONにしています。

 既にお分かりかと思いますが、このプログラムは失敗です。一般的なPWMの周期は10~20msといわれています。timer1のインターバルを1m/sに設定しているので問題ないように思いますが、実際にどれぐらいの値が出ているか計測したところ、約120ms程度かかっています。SetRumble関数を処理するのに時間がかかりすぎて「制御している」とは言えない状況です。WiimoteLibが原因なのかWiiリモコンとの通信が問題かはわかりませんが、今後、SetRumble関数の処理時間が軽減されればより、厳密なバイブレーションの強弱をつけることが可能になります。