Sunday, May 04, 2008

Improvements to Arduino Wii Nunchuck connection

I'm working on an Arduino based controller for an electric canoe. In the process of doing that, I've been looking more closely at the data coming off the wii Nunchuck. Using the avr math libraries, and the atan2 function, you can combine the data from the X and Z accelerometers on the nunchuck to get a nice smooth 360 degrees of roll information. Because this is using an inverse tangent function, it also makes for more accurate angular data than the raw data coming off the device.

Here's a quick demo video, followed by links to the code.


I posted all three files needed for this on the Arduino Playground.

For hardware setup, Todbot's little adapter is the best.


ps. For this same canoe project I wrote up a library for the Wii Classic Controller as well. For anyone interested, that's available here.

UPDATE:
George's asks a good question in the comments. If you try and run the code posted on the arduino playground. It's important to note that the third chunk of code needs to be run from the processing application, available here at processing.org.

14 comments:

Anonymous said...

Hey Tim,

I stumbled on your old sailing blog the other day and couldn't stop reading it. I've been planning to build a boat myself with crusing the ICW as the final goal, and the story of your trip captured exactly how I image my trip will be when it becomes a reality. I wondered here trying to find a way to send you a quick note.

Interestingly enough, I see that you lived a while in Bozeman, where I lived for 4 years too (I left in the summer of 2004). It is unfortunate that our paths didn't cross.

I would love to send you some questions for cruising advice sometime if my plans materialize. Would that be ok? Also, just so you know, I gave the Slow Times a link on my blog.

Anonymous said...

Dear Sir,

I am an old physicist now practically retired. I am very interested on your project. As I have an arduino board and an wiinunchuck, I downloaded your 3 codes and tried to reproduce the results. The first two seam to work OK. After creating a directory WiiChuck in the hardware/libraries, I copied in the code_1. Then I started the arduino and copied the code_2 as the main program. It works well. The last one gives a syntaxe error (void serialEvent) in the arduino 010 environment. Please help me with some guidance as I am new in this field and a lot of my knowledge was forgotten. send me mail on: const_g20 at yahoo dot fr.

Yours sincerely,
Georges

Anonymous said...

I noticed some bugs with your WiiChuck.h

When trying to use calibrateJoy() it will not calibrate the controlls at all but instead make it even worse. I found that adding update() before you set zeroJoyX = joyx; fixes this problem.

As with the Z and C buttons it wont keep them active if you do say

if(chuck.zPressed())
{
digitalWrite(1, HIGH);
}
else
{
digitalWrite(1, LOW);
}

this will have the LED blink once and not stay on if i keep holding it down. I found that if you change "return (buttonZ && ! lastZ);" to "return (buttonZ);" this fixes the problem.

Anonymous said...

yea disregard what I said about your calibrateJoy() function it does work how you have it, my bad >.<

The z and c pressed still only works when i change it though.

Anonymous said...

Tim,

On the Arduino site you listed a ".h" file an arduino sketch and a processing sketch.
I can't get the library(.h) file to work with the arduino sketch. Doesn't there need to be a (.cpp) (.o) and (keywords.txt) file included with each code library in order for the arduino to reference it?

How do I get the .h file working?

Thanks!

Tim Hirzel said...

Hey, in terms of the .h file, for me, I just put the .h file next to my sketch file, and call:
#include "WiiChuck.h"
from the main sketch. where I want to use that functionality.

That has worked for me.

Anonymous said...

Thanks for your work, looks great in a youtube vid!

It looks like maybe your WiiChuck.h file doesn't compile properly in Arduino 0012 Alpha though? I'm pretty new to Arduino so I'm not sure about which syntax changes broke it or if I'm just doing something wrong? I get dozens of errors compiling it, the first few errors are:

hardware\libraries\WiiChuck/WiiChuck.h:51: error: 'byte' does not name a type


hardware\libraries\WiiChuck/WiiChuck.h:53: error: 'byte' does not name a type


hardware\libraries\WiiChuck/WiiChuck.h:63: error: 'boolean' does not name a type


hardware\libraries\WiiChuck/WiiChuck.h:68: error: 'byte' does not name a type

(...about 20 more follow)

Tim Hirzel said...

Hi Craig,
Thanks for pointing this out. I'll check into it real soon.
Tim

Unknown said...

Hi,

I'm trying to connect my Wii controller to my arduino. I used the source from http://www.windmeadow.com/node/42.

i wasn't able to get any data because when i connect the nunchuck to the arduino, my arduino just stop. I connect directly on pins 2 to 5 with the WiiChuck Adaptor. The TX and TR pins stop blinking when i connect the controller.

I have no idea where is the problem and i can't continue to go ahead because I just can't read data.

Do I need to use resistor or something else ?

I use an Arduino diecimila, an original Nintento Nunchuck and the Wii Nunchuck Adaptor. I also use the lastest arduino software (012).

Adresse to the WiChuck Adaptor : http://todbot.com/blog/2008/02/18/wiichuck-wii-nunchuck-adapter-available/


Thanks in advance.

Anonymous said...

Hi,

I am trying to use your code with an Arduino Diecimila using an ATmega328. I'm not using the Processing code, and I'm using a modified version of Arduino 12. The wii nunchuck is connected with one of the adapters.

Why do none of the variables get printed in the Serial Monitor?

The code seems to stall when it gets to chuck.begin();

I just tried it on an ATmega168 and an Arduino 12 IDE, it still didn't work.

Your help would be greatly appreciated!

Tim Hirzel said...

hrmmm... that's a tough one. Can you get hold of an Arduino 10 and try it with the 168 version? If that works, that will confirm that somehow this library has gotten stale since I set it up. With some other code, I've noticed v12 has been less happy with some of my libraries, and I've yet to sort it out yet.

If that doesn't help, I've definitely had i2c stuff freeze up my apps when there were hardware issues, like a slightly lose connection to the nunchuck. I since have started adding little solder blobs to the wiichuck adapter to widen the adapter just slightly and make a tighter fit to the nunchuck.

Lastly, try Todbot's library as an alternative. http://todbot.com/blinkm/example_code/BlinkMChuck/nunchuck_funcs.h
Note his special init function for when the nunchuck is connected directly to the arduino. That *might* illuminate something.

Please do post back with any clues or results. Thanks for your comment.

Anonymous said...

I got your Nunchuck code to work, but had the same freezing problem.

Seems that if the power pins are not set up, the ThingM wiichuck adapter can't power the i2c conversation, and the Wire library freezes whenever trying to converse with an unpowered nunchuck.

Interestingly, the board would unfreeze and start printing ~512~512~540 results if I pulled the nunchuck OFF the adapter entirely.

Once I powered the i2c pins (outputs 2 and 3), it would work. It would require the whole Arduino to be reset if it was unplugged and replugged, however.

You and todbot did a great job, but I'm thinking of merging both of your codes into one, which will handle the buttons, tilts and also try to auto-reset the i2c conversation if it thinks the nunchuck has not been initialized. I will also try to separate the Wire calls from the Wii-related features, so it's easier to extend. Any objections?

Roger McSpoonie said...

I think some of you are having the same problem I did: you need to init the nunchuck with power. Todbot's code has a function to do that. I've copied that in to the WiiChuck class and added two constructors - one that defaults to no power, and one that lets you supply a boolean indicating whether or not you want power. I can send this around if it's not clear what I mean.

Anonymous said...

Yep. I have the Ard powered by USB and this code jammed up.

I added this to the .h:

// General version of nunchuck_init_with_power()beginWithPower().
// Call this first when a Nunchuck is plugged directly into Arduino
static void init_with_power_pins(byte pwrpin, byte gndpin)
{
Serial.print("Powering");
DDRC |= _BV(pwrpin) | _BV(gndpin); // make outputs
PORTC &=~ _BV(gndpin);
PORTC |= _BV(pwrpin);
delay(100); // wait for things to stabilize

}


and this to the main sketch before chuck.begin():

chuck.init_with_power_pins(PC3, PC2);