Having a Wii bit of fun...

This week, I started playing with interfacing to the Wii remote. I have to give credit where credit is due:

Brian Peek wrote an excellent library to interface with the Wii remote

Johnny Chung Lee used the Wii's infrared camera to track objects (More about this later)

Rick Barraza from Cynergy started using the Wii and WPF together (Also look at Project Maestro)

Matthias Shapiro also did some excellent work getting the Wii remote and WPF to work together. He explored binding the Wii remotes status to the WPF applications data context!

Also check out the follow up article were I give the schematics of the IR lights and some code updates!

Background

The Wii remote uses standard Bluetooth (Broadcom BCM2042) to communicated with the host. It uses (abuses) the Bluetooth HID protocol. The WiimoteLib (by Brian Peek) handles all the reading and interpreting of the HID reports. All that we need to be concerned about is the WiimoteState. This contains all the statuses of the buttons, 3-axis accelerometer and the IR sensor information.

Matthias Shapiro has a excellent post on how to connect the Wii remote. Please also remember that not all Bluetooth adapters and stacks works, I will try and compile a list. I first tried to use my normal HP Bluetooth adapter but no success. Next, I installed the normal Bluetooth driver from Microsoft and it worked perfectly!

To test if everything works, try the test application that ship with the WiimoteLib (By Brian Peek) or the Wii Data Visualizer (By Matthias Shapiro).

For a IR source, I opened a normal infrared remote control and removed the IR led. I then connected the led to a AA battery holder (Available from Communica for R3). This allows me to create a infrared light source to track that runs from batteries!

Now that we have the Wii remote connected to our PC (Via Bluetooth) and we have a IR light source, we are ready to write some code.

Here is the code to setup WiimoteLib. First create a instance of Wiimote

Wiimote wm;

Next, initialise the Wiimote

wm = new Wiimote();
wm.WiimoteChanged += new WiimoteChangedEventHandler(wm_OnWiimoteChanged);
wm.Connect();
wm.SetReportType(Wiimote.InputReport.IRAccel, true);
wm.SetLEDs(false, false, false, false);

And now we are ready to look at what the Wii remote can do!

Every time something happens on the Wii remote, the wm_OnWiimoteChanged will be fired

void wm_OnWiimoteChanged(object sender, WiimoteChangedEventArgs args)
{
            WiimoteState ws = args.WiimoteState;

            //Here we can now inspect the WiimoteState object...
}
 

We can then look at the WiimoteState to see if buttons were pressed, the accelerometer's status or even what the IR camera "sees"!

BindableObject

Ok, the WPF geek inside me tells me that this might be simpler if I somehow make the state object inherit from something like a BindableObject (To implement the INotifyPropertyChanged stuff). This will have a huge performance boost because I will only update items which has changed and not everything each time the changed event fires! It will also simplify some UI stuff by allowing binding. Now I can bind to a buttons status and do animations based on its current pressed state all with the magic of dependency properties!

Instead of writing my own library, I decided to hack the WiimoteLib slightly to incorporate the BindableObject natively! I only did it for the IRState object and not even for all 4 points, I only did the first point (Assuming that the first IR light I see is the one I should use). If I have time I might just make my own WiimoteLibForWPF ;)

Now it is very simple to use the IRState object without even worrying about the WiimoteChanged event! I can now bind the WiimoteState object to my window DataContext. To simplify binding, I will only bind the IRState object and not the whole WiimoteState object!

DataContext = wm.WiimoteState.IRState;

And now its possible to bind using XAML!

<Label Content="{Binding Path=X1}" />
<Label Content="{Binding Path=Y1}" />

Very cool!!!

Next is the actual tracking. The Wii remote has a PixArt sensor in the front to assist with tracking infrared light sources. John Chung Lee had some excellent suggestions. The 1st option is to have a infrared emitting bar or array next to the Wii remote and then attaching reflective tape to your fingers to reflect the position of your hands or fingers or alternatively, have the infrared light source on your hands. Cynergy has a excellent video of how thy used this!

I opted for the more traditional way of using it. My IR source will be stationary and I am going to use the Wii remote as a "wireless mouse". This is very similar as to how it is actually used in the Wii console!

The idea is to have a very simple WPF application with 2 bars. One of the bars on the left hand side of the window and the other at the top. Each bar will indicate one axis of the "wireless mouse" with a simple line that is data bound to the status of the Wii remote.

The WiimoteLib's IRState object has a normalized X1 & Y1 that basically gives me a value of between 0-1.0 based on the current position of the IR objects. Next step is to write a very simple converter that takes this normalized value and the actual width or height to scale too and do the conversion.

public class NormalizedXYConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object param, CultureInfo culture)
    {
        try
        {
            float normalizedValue = (float)values[0];
            double scaleToValue = (double)values[1];

            return normalizedValue * scaleToValue;
        }
        catch (Exception)
        {
            return 0.00;
        }
    }
    public object[] ConvertBack(object value, Type[] targetTypes, object param, CultureInfo culture)
    {
        return null;
    }
}

NOTE: This can also be done using Marlon Grech's LambdaValueConverter 

And all that is now left is to bind my indicators position to the converted X1 and Y1 values! I just add two Border elements and bind the left hand side's height and the top one's width to the normalized X1 and Y1

Here is the left hand "bar"

<Border Width="20" Background="Black" VerticalAlignment="Top">
    <Border.Height>
        <MultiBinding Converter="{StaticResource normalizedXY}">
            <Binding Path="Y1" />
            <Binding ElementName="mainWindow" Path="ActualHeight" />
        </MultiBinding>
    </Border.Height>
</Border>

And here is the top "bar"

<Border Height="20" Background="Black" HorizontalAlignment="Left">
    <Border.Width>
        <MultiBinding Converter="{StaticResource normalizedXY}">
            <Binding Path="X1" />
            <Binding ElementName="mainWindow" Path="ActualWidth" />
        </MultiBinding>
    </Border.Width>            
</Border>

This is the end result

The bar's nicely indicate exactly where the Wii remote is pointing. It is also very easy to create a simple pointer on the screen.

<Ellipse x:Name="Pointer" Width="10" Height="10" Fill="Blue">
    <Canvas.Top>
        <MultiBinding Converter="{StaticResource normalizedXY}">
            <Binding Path="Y1" />
            <Binding ElementName="mainWindow" Path="ActualHeight" />
        </MultiBinding>
    </Canvas.Top>
    <Canvas.Left>
        <MultiBinding Converter="{StaticResource normalizedXY}">
            <Binding Path="X1" />
            <Binding ElementName="mainWindow" Path="ActualWidth" />
        </MultiBinding>
    </Canvas.Left>
</Ellipse>

Just remember that the root panel must be a canvas for this to work!

As a side note, the Sensor Bar of the Nintendo Wii Console is actually just 2 infrared lights used to assist in the calculation of the position of the cursor on your television screen!

The infrared camera can track up to 4 infrared sources. this opens the door to multi-touch scenarios (Like Microsoft Surface)

Here I only investigated a single point touch solution. Multi-touch has it's own set of problems. If you want to learn more about multi touch, I suggest start looking at Microsoft Surface! 

Digging deeper

If you want more information of the exact protocol exchanged between the Wii remote and the host have a look at the following 2 sources:

Wii Brew

WiiLi

Well, that is all for now... In the future I will try and get a multi-touch solution to work...

Published Wednesday, February 13, 2008 6:44 AM by rudi
Filed under: ,

Comments

# Having a Wii bit of fun

You've been kicked (a good thing) - Trackback from DotNetKicks.com

Wednesday, February 13, 2008 6:49 AM by DotNetKicks.com

# re: Having a Wii bit of fun...

What kind of a remote did you use for that? I just tore apart the remote for my television and the IR light is soldered into the circuit board.

Part of the reason I haven't further updated my tutorials is because I've had a heck of a time getting a consistent mobile IR source, what with having to deal with all sorts of batteries and resistors. (I'm not an electronics geek.)

Can you explain in what you did with the IR light like you're talking to a complete idiot… because I'm not far off.  

Wednesday, February 13, 2008 8:00 AM by Matthias Shapiro

# re: Having a Wii bit of fun...

Hi Matthias,

Nice series so far... looking forward to reading the rest!

OK, I opened a remote I had lying round. It had the IR led soldered onto a board. I just used a side cutter to cut the leds two legs. Next, I soldiered two wires onto the 2 legs. The first time round I connected it striaght to a battery. 2 things to remember here. The LED is just a diode so it has a + and - leg. It must be connected right way round. It will not blow if you don't but it will not work. You can check if it works by pointing the remote at it and checking if it sees anything or use a standard video camera in a dark room. This should pick up the IR light!

After playing round a little I just added a 120 ohm resistor to increase the brightness!!!

Disclaimer: I am also not a electronics guy but this does work!!!

Keep up the good post and I am looking forward to seeing how you do multi touch!

Regards

Rudi Grobler

Wednesday, February 13, 2008 12:00 PM by rudi

# Having more fun with the Wii

After my first attempt to connect the Wii and WPF I started working on improving it! My infrared light

Thursday, February 14, 2008 1:54 PM by Rudi Grobler

# &raquo; Daily Bits - January 19, 2008 Alvin Ashcraft&#8217;s Daily Geek Bits: Daily links, development, gadgets and raising rugrats.

Pingback from  &raquo; Daily Bits - January 19, 2008 Alvin Ashcraft&#8217;s Daily Geek Bits: Daily links, development, gadgets and raising rugrats.

# 6 Links Today (2008-02-19)

Pingback from  6 Links Today (2008-02-19)

Tuesday, February 19, 2008 3:19 PM by 6 Links Today (2008-02-19)

# re: Having a Wii bit of fun...

If there ever was a reason for me to get Wii, THIS IS IT!!!! Awsome dude, this is really cool!

Wednesday, February 20, 2008 9:19 AM by Zlatan

# Wii, Wpf, and Binding

Having done minimal WPF work myself due to lack of time, I found an interesting thing on Rudi Grobler&#39;s

Friday, February 22, 2008 4:47 AM by Noticias externas

# Is Local Lekker?

I am currently sitting at Cape Town airport and as usual our flight is delayed, so I decided to use this

Friday, February 22, 2008 7:13 AM by Rudi Grobler

# W&ouml;chentliche Rundablage: Silverlight 2, ASP.NET MVC, WPF, C# 3.0, CardSpace, OpenID | Code-Inside Blog

Pingback from  W&ouml;chentliche Rundablage: Silverlight 2, ASP.NET MVC, WPF, C# 3.0, CardSpace, OpenID | Code-Inside Blog

# re: Having a Wii bit of fun...

Great stuff... keep it up :D

Friday, February 29, 2008 12:36 AM by Marlon Grech

# re: Having a Wii bit of fun...

Tnx Marlon...

Friday, February 29, 2008 6:16 AM by rudi

# re: Having a Wii bit of fun...

I just found your blog today while at MIX. Thanks for posting up on this stuff more. I haven't had a lot of time to blog too much about the details of Project Maestro (been very busy with Silverlight stuff, as you can imagine :), but will definitely add your post to the list I give out when people ask for more info, besides the intro on my cynergy blog. Nice work, Rudi. Keep it up!

Thursday, March 06, 2008 6:18 PM by Rick Barraza

# re: Having a Wii bit of fun...

Tnx Rick,

Keep up the great work... looking forward to learning more about Project Maestro!

Rudi

Friday, March 07, 2008 6:24 AM by rudi

# CodeProject Article

I just released another CodeProject article. This article describes how to restyle a standard WPF TabControl

Friday, March 07, 2008 6:39 AM by Rudi Grobler

# Using Wii Remote in your apps &laquo; Adisimon&#8217;s Weblog

Pingback from  Using Wii Remote in your apps &laquo; Adisimon&#8217;s Weblog

Saturday, March 15, 2008 2:04 AM by Using Wii Remote in your apps « Adisimon’s Weblog

# Revolutionising The User Interface (Introducing MenuKiller for WPF)

I don&#39;t fancy myself a frontend guy, getting controls and tables and other things to align is usually

Thursday, May 29, 2008 2:01 PM by Zlatan's Blog [MVP SharePoint]

# Revolutionising The User Interface (Introducing MenuKiller for WPF)

I don&#39;t fancy myself a frontend guy, getting controls and tables and other things to align is usually

Thursday, May 29, 2008 2:35 PM by Zlatan's Blog [MVP SharePoint]

# bit of fun

Pingback from  bit of fun

Saturday, June 14, 2008 6:02 PM by bit of fun