Boris Smus

Software Designer

Prototyping with Wii Remotes in Python

I’ve been working on a couple of researchy projects involving gait recognition and running foot strike analysis. For my proof of concept, I turned to the wiimote, everyone’s favorite physical interaction prototyping input device. Wiimotes are portable and rugged, and thus well suited to high-intensity activities like running. They attach easily to legs with a physio band, although the elastic tension tends to cut off circulation. No big deal, though… it’s For Science!

This article is not about attaching Wiis to legs (more on that at a later date!), but about communicating with the Wii remote using python. I started out by writing a Cocoa application to harvest accelerometer data using the WiiRemote framework provided by the DarwiinRemote project. After some objective-c iterations of my initial gait recognizer algorithm, I decided to port to python, an environment better suited for light prototyping. There’s a few packages explicitly developed to integrate with the wiimote. Pywiiuse provides a lightweight wrapper around the wiiuse library and does not work on OS X. An alternative, pywiimote claims to be multiplatform but pointedly isn’t. Here’s the start of their code:

from ctypes import *
kernel = windll.kernel32

Having found no existing wiimote-specific python libraries that would work on my platform, I had no choice but to dig a little into the bluetooth-based protocol that the wiimote uses. I found all the details in all their gory glory on the wiibrew wiki. The communication protocol involves two open L2CAP sockets between the host and wiimote: one for reading and one for writing. After an initialization string is sent over the write socket, the wiimote springs into life and sends a stream of data on the read socket. In this data are accelerometer values and button presses. Here’s a simple python snippet using the lightblue library:

import sys, lightblue, hexbyte

WIIMOTE_DEVICE_NAME = 'Nintendo RVL-CNT-01'

# auto-discover nearby bluetooth devices
devs = lightblue.finddevices(getnames=True, length=5)
# find the one with the correct name
wiimote = [d for d in devs if d[1] == WIIMOTE_DEVICE_NAME] and d[0] or None
if not wiimote:
    print "No wiimotes found!"
    sys.exit(1)

# create a socket for writing control data
write_socket = lightblue.socket(lightblue.L2CAP)
write_socket.connect((wiimote, 0x11))

# create a socket for reading accelerometer data
read_socket = lightblue.socket(lightblue.L2CAP)
read_socket.connect((wiimote, 0x13))

# initialize the socket to the right mode
write_socket.send(hexbyte.HexToByte('52 12 00 33'))

# start reading data from it
while 1:
    byte = read_socket.recv(256 * 7)
    data = hexbyte.ByteToHex(byte)
    # do something interesting with the data
    print data

You’ll need hexbyte.py to run the above snippet. I hope you (the wii remote wielding python fan) find this snippet useful. As a side note, if you’ve figured how to pair a wiimote with an android phone and released the code into the public domain, please let me know. Since Android 2.2 still doesn’t ship with L2CAP APIs, I hit the wall.

7 comments:

John Harrison

There is a darwiinremote wrapper in python written by Ian Johnson. here is the url for it:

http://enja.org/enj/enjapen/

I believe there is also a github project now under:

http://github.com/enjalot

I wrote about my own experience using it at:

http://blog.insightvr.com/?p=16

Hope this is helpful. Have fun hacking up wiimote projects in python!

on May 28th, 2010 at 8:57 pm
Boris Smus

Thanks for the links, John!

on May 29th, 2010 at 2:52 am
Ian Johnson

Hi Boris,
It’s been a while since I’ve touched that project, but making a cross-platform python wiimote framework is on my backburner. I believe that DarwiinRemote has issues with it’s bluetooth implementation as me and others have had annoying connection issues.

I’ve also just started Android dev, perhaps using the NDK you could get L2CAP functionality:
http://blog.bruary.net/2009/07/android-bluetooth-hacking-using-ndk.html

P.S. I love your wordpress theme, did you make it yourself?

on June 19th, 2010 at 1:56 pm
Boris Smus

Ian, I have seen some of those strange connection issues too. And thanks for the NDK link.

Yes I made the wordpress theme myself. I’m glad you like it!

on June 24th, 2010 at 9:37 pm
Matt Williamson

Any samples of actually interpreting the data? I know wiibrew has all of the details, but if someone else has already done it…. :)

on July 7th, 2010 at 7:51 am
Boris Smus

Matt, here’s a short snippet extract accelerometer data. Consult wiibrew for exactly the acceleration values mean (it was irrelevant for my project).

        byte = read_socket.recv()
        data = [int(val, 16) for val in ByteToHex(byte).split()]
        accelerometer_data = data[4:7]
on July 7th, 2010 at 10:59 pm
Asim Mittal

Look up the CWiiD Project for a Python wrapper that allows you to easily tap the sensor data from the Wiimote.

And its the only completely functional and stable library that runs on Linux.

on July 26th, 2010 at 11:00 pm

speak your mind