HOWTO make your own Wiimote peripheral
With a little wiring a Wiimote can be made into a cheap bluetooth transmitter for your microcontroller project. Wiimote peripherals like the nunchuk, communicate with the wiimote over I2C (aka Two Wire Interface, TWI). A number of microcontrollers support TWI, such as the Arduino,the Make Controller and Atmels ATmega series. I am using an arduino with a ATmega168 for this project.

The nunchuk sends a 6 byte packet to the wiimote. For an in depth discussion of the format go to wiili.org. So you can send whatever data you want across the wiimote, just send it 6 bytes at a time. On the PC side, there are a number of wiimote drivers to choose from. Since am running Linux, I am using libcwiimote. Running the program test1, the Arduino's data shows up as nunchuk data.
The wiimote uses a proprietary connect. I just bought an extra nunchuk and cut the cable off of it. The cable has 4 wires.
white - ground
red - 3.3+v
green - data
yellow - clock
Attach white to the Arduino's ground, red to AREf, green to analog pin 4, yellow to analog pin 5. Since the wiimote provides power you can actually power the Arduino straight from the wiimote. The Arduino's twi.h header needs two changes. Look in lib/targets/libraries/Wire/utility. Then delete twi.o. Open up twi.h. Uncomment line // #define ATMEGA8. Since the wiimote uses "Fast" I2C, we will need to change the speed #define TWI_FREQ 400000L.
Here is a simple program to send data across the wiimote.
#include <Wire.h>
uint8_t outbuf[6];
void
receiveEvent (int howMany)
{
while (Wire.available ())
{
char c = Wire.receive (); // receive byte as a character
}
}
void
requestEvent ()
{
outbuf[0] = nunchuk_encode_byte (125); // joystick X
outbuf[1] = nunchuk_encode_byte (126); // joystick Y
outbuf[2] = nunchuk_encode_byte (227); // Axis X
outbuf[3] = nunchuk_encode_byte (241); // Axis Y
outbuf[4] = nunchuk_encode_byte (140); // Axis Z
outbuf[5] = nunchuk_encode_byte (1); // Press C button, byte[5] is buttons
//C,Z and accelaration data
//outbuf[5] = nunchuk_encode_byte(2); // Press Z button
//outbuf[5] = nunchuk_encode_byte(0); // Press Z and C button
Wire.send (outbuf, 6); // send data packet
}
void
setup ()
{
Wire.begin (0x52); // join i2c bus with address 0x52
// this is the nunchuk address.
// all nunchuks use this address
Wire.onReceive (receiveEvent); // register event
Wire.onRequest (requestEvent); // register event
}
void
loop ()
{
delay (100);
}
// Encode data to format that most wiimote drivers except
// only needed if you use one of the regular wiimote drivers
char
nunchuk_encode_byte (char x)
{
x = x - 0x17;
x = (x ^ 0x17);
return x;
}
The regular nunchuk encodes the data before it is sent. To mimic the nunchuk, my codes performs the same operation. Now byte[0] will come over as nunchuk joystick X, byte[1] as joy Y, byte[2] as axis X, byte[3] as axis Y, byte[4] as axis Z. Byte[5] as buttons and accelaration data. Byte[5] as some more computations (an additional XOR 0xFF) done to it when using the regular wiimote driver. So your driver would need to be modified to accurately read that byte.
No one has quite figured out if it is possible to send data TOO the peripheral. If that can be figured out then the wiimote will make a cheap blue tooth transceiver especially compared to the cost of an Arduino blue tooth board $140.
Credit goes to Zudini at wiire.org. He figured out the wiimotes I2C protocol and posted the sample code that I based mine off of.
Update I just tried running my code under Arduino 10. I had to make a different change to twi.h. Here are the first few lines of twi.h
#define ATMEGA8
#ifndef CPU_FREQ^M
#define CPU_FREQ 16000000L
#endif
#ifndef TWI_FREQ^M
#define TWI_FREQ 100000L
#endif
Comments
Peter:
It looks not so cute like a white one, but it is much more cheaper with the same functionality.
sports writer jobs
obat:
I love to see people so creative like this, great work mate, keep it up.
Anonymous:
the jumper set to power from USB (Which is kind of weird) When I do that, Mario Kart (Which I've been testing with) pops up a message saying I've changed the controller, other than that, the only thing that happens is that the IR cam stops working sometimes. Anyone got any ideas?
Buy Dissertation | Essays | Research Paper Writing
blizzard:
Thanks for sharing this information. I found it very informative as I have been researching a lot lately on practical matters such as you talk about...
Rob A:
Thanks for this info, this will be extremely helpful. On your query as to whether or not you can do a transciever by sending information back, I have been considering using the vibration control to the wiimote as a digital serial port via a 3.5mm disconnect jack on the actual wiimote. Not as convenient as a plug in the nunchuck port, but still very useful for only $40 or so ready-to-use.
-R
Zoran:
Wow that is awesome, you are a genious!


Adam:
can I control the wiimote buttons externally? i.e could I control the D-pad on the wiimote through my arduino. Thanks for your help
Declan Williams:
As chad said,
It is possible by modding the innards of the wiimote.
But over the nunchuck port, not directly I don't think.
As far as I'm aware, none of the wiimotes own features are in the address shared by the expansion port.
chad:
I would think you could. The D-pad is just a couple of switches. You could probably wire them up with some reed relay or similar. Having the arduion control the relay, that would simulate a button push.
Anonymous:
r u guys talk about making wiimote???
Declan Williams:
Hi chad. I'm trying to make my own wiimote peripheral too. But after many hours observing oscilloscope traces, I have found that the data seems to be encrypted using different algorithms every time the peripheral (nunchuck or classic controller) is connected.
It looks to me like the wiimote decides which encryption is to be used, by sending out a 16 byte key during the initialization process. How have you over com this chad?
And just out of curiosity. What peripheral is you Arduino emulating? I mean, what does it reply, when the wiimote issues a read after the 0xFA command? 0x00, 0x00, 0xA4, 0x20, 0x01, 0x01 (Classic controller) or 0x00, 0x00, 0xa4, 0x20, 0x00, 0x00 (Nunchuck).
Jrblast:
I set up my Arduino exactly like you have and I even connected the attachment detection pin to 3v3 (I got an extension cable and cut it open, the extension cable doesn't connect them on its own) have made the changes to twi.h and I used the code you have posted (I have also tried tweaking the code a bit) The only time I get any effect is when the Arduino is wired to be powered from the wiimote (I.E. 3v3 connected to Vin) and the jumper set to power from USB (Which is kind of weird) When I do that, Mario Kart (Which I've been testing with) pops up a message saying I've changed the controller, other than that, the only thing that happens is that the IR cam stops working sometimes. Anyone got any ideas?
(Using an Arduino Diecimila)
Pace:
I've seen this article on hackszine.com. Nice post.
Valentin:
A FireWire Plug fits perfectly to all the 6 Connectors in the Expension Port.
Its way cheeper than buing a nunchuk for it.
cheers
apple pie recipe:
I think I might order some stepper motors and make an electronic, wiimote guided etch-a-sketch.
curious:
Perhaps I am mistaken here, but will the Arduino be using the 3.3v reference voltage in the situation you've described? See this post which is linked to by the Arduino reference.
Post new comment