Sunday 9 September 2012

Playing with a wiimote

Intro

I've got some plans for using a wiimote an an interface to a project I'm working on. I'm particularly keen to use the MotionPlus capabilities of the newer wiimotes to determine its orientation, but to get that to work I've first got to manage to get the raw data out of the wiimote.

This post will show how to connect to and get sensor data out of a wiimote on a linux machine.

Connecting to the wiimote

The first step is to connect to the wiimote. Wiimotes communicate via bluetooth, so you'll need a computer that has bluetooth capabilities. Most laptops have bluetooth built in, otherwise you'll need to grab a USB Bluetooth dongle. You should be able to pick one up for ~$5 on ebay (just make sure it works under linux before you buy it).

Okay so once you've got bluetooth connected, we'll see if we can discover the wiimote. Press the 1 and 2 buttons at the same time on the wiimote - this will put it into discoverable mode (the lights at the bottom should flash to indicate that it is in discoverable mode). Then run the command "hcitool scan" :
rlawther@voodoo ~ $ hcitool scan
Scanning ...
    E0:0C:7F:8B:4D:77    Nintendo RVL-CNT-01

Nice, it found our wiimote. That means our bluetooth is working. Let's see if we can get some interesting data out of it.

Testing the wiimote

Ok so we've managed to connect to our wiimote, so now lets see if we can get some data out of it. Luckily for us, someone has already written a nice little GUI to interpret the data come back from a wiimote - it's called wmgui and you can install it by running "apt-get install wmgui".

To run it simply type "wmgui". Then click File -> Connect and follow the prompts.  Once you're connected you should be able to press some buttons and see them get highlighted in the GUI.

wmgui showing current state of the wiimote

Have a bit of a play and get a feel for how the sensors react as you move it around.

Note that wmgui won't display MotionPlus values, and that's what we're after. So let's go a little depper and write some python code to get data from the 'mote.

Polling the wiimote

I've tried a couple of libraries to get wiimote data in python, and I found the easiest to be cwiid. Grab it with "sudo apt-get install python-cwiid". Now we can poll the MotionPlus data with a simple script

#! /usr/bin/python 
import cwiid 
import time 

print "Press 1+2 on the wiimote" 
wm = cwiid.Wiimote() 
wm.led = 1 
wm.enable(cwiid.FLAG_MOTIONPLUS) 
wm.rpt_mode = cwiid.RPT_BTN | cwiid.RPT_MOTIONPLUS 
print "OK, connected" 

while True: 
    print wm.state 
    time.sleep(0.1)

This script polls the wiimote at around 10 times per second and dumps the data to the screen. Have a look at the "motionplus" section of the output, and see what happens as you move the 'mote around.

rlawther@voodoo dumpMotionPlus $ ./dumpMotionPlus.py 
Press 1+2 on the wiimote 
OK, connected 
{'led': 1, 'rpt_mode': 130, 'ext_type': 0, 'buttons': 0, 'rumble': 0, 'error': 0, 'battery': 74} 
{'led': 1, 'rpt_mode': 130, 'ext_type': 0, 'buttons': 0, 'rumble': 0, 'error': 0, 'battery': 74} 
{'led': 1, 'rpt_mode': 130, 'ext_type': 4, 'motionplus': {'angle_rate': (8198, 8313, 8158)}, 'buttons': 0, 'rumble': 0, 'error': 0, 'battery': 74} 
{'led': 1, 'rpt_mode': 130, 'ext_type': 4, 'motionplus': {'angle_rate': (8199, 8294, 8159)}, 'buttons': 0, 'rumble': 0, 'error': 0, 'battery': 74} 
{'led': 1, 'rpt_mode': 130, 'ext_type': 4, 'motionplus': {'angle_rate': (8195, 8284, 8167)}, 'buttons': 0, 'rumble': 0, 'error': 0, 'battery': 74} 

When the 'mote is still, the motionplus values will hang around the 8200 mark. This will vary a bit from 'mote to 'mote, so you'll need to calibrate each time you connect to a 'mote to find out its "zero" value. Also note that these values represent the current angular velocity of the 'mote - if you want its absolute orientation in space, you'll need to integrate these values over time.

Stay tuned for another blog post on how to do that ... : )