Links and Thanks:
First off, I'm going to link(and thank) a few sites that have helped me immensely with this undertaking:
Arduino.cc
original nunchuck code
Wii brew WM+ info
Propeller forums
Hardware connections:
I used full 5V TTL signals and power and have had no problems thus far (a week going strong) but if you have a 3.3v arduino or a level converter and 3.3v regulator, i would suggest that over a 5v connection. Furthermore, twi.h under the wire library does not need to be changed for my setup but might under some setups. Start with the default 100khz TWI_FREQ and if that doesnt work, use 400khz. Websites disagree about which is the proper speed for direct I2C on wii peripherals. Connections to WM+ are same as nunchuck and look like this:
| 1 2 3 |
| |
| 6 5 4 |
|_-----_|
1 - green - data
2 - nothing
3 - red - 3.3+v
4 - yellow - clock
5 - nothing
6 - white - ground
So its pin 3 to 5v, 6 to ground, 1 to A4, and 4 to A5
Adapters such as the one sold here should (theoretically) work; I use jumper wires and hot glue
Software:
I have commented the demo code pretty well so it should be easy to follow, if not comment here or on Arduino.cc Forums->Exhibition
byte data[6]; //six data bytes
int yaw, pitch, roll; //three axes
int yaw0, pitch0, roll0; //calibration zeroes
void wmpOn(){
Wire.beginTransmission(0x53); //WM+ starts out deactivated at address 0x53
Wire.send(0xfe); //send 0x04 to address 0xFE to activate WM+
Wire.send(0x04);
Wire.endTransmission(); //WM+ jumps to address 0x52 and is now active
}
void wmpSendZero(){
Wire.beginTransmission(0x52); //now at address 0x52
Wire.send(0x00); //send zero to signal we want info
Wire.endTransmission();
}
void calibrateZeroes(){
for (int i=0;i<10;i++){
wmpSendZero();
Wire.requestFrom(0x52,6);
for (int i=0;i<6;i++){
data[i]=Wire.receive();
}
yaw0+=(((data[3]>>2)<<8)+data[0])/10; //average 10 readings
pitch0+=(((data[4]>>2)<<8)+data[1])/10;
roll0+=(((data[5]>>2)<<8)+data[2])/10;
}
Serial.print("Yaw0:");
Serial.print(yaw0);
Serial.print(" Pitch0:");
Serial.print(pitch0);
Serial.print(" Roll0:");
Serial.println(roll0);
}
void receiveData(){
wmpSendZero(); //send zero before each request (same as nunchuck)
Wire.requestFrom(0x52,6); //request the six bytes from the WM+
for (int i=0;i<6;i++){
data[i]=Wire.receive();
}
yaw=((data[3]>>2)<<8)+data[0]-yaw0;
pitch=((data[4]>>2)<<8)+data[1]-pitch0;
roll=((data[5]>>2)<<8)+data[2]-roll0;
}
//see http://wiibrew.org/wiki/Wiimote/Extension_Controllers#Wii_Motion_Plus
//for info on what each byte represents
void setup(){
Serial.begin(115200);
Serial.println("WM+ tester");
Wire.begin();
wmpOn(); //turn WM+ on
calibrateZeroes(); //calibrate zeroes
delay(1000);
}
void loop(){
receiveData(); //receive data and calculate yaw pitch and roll
Serial.print("yaw:");//see diagram on randomhacksofboredom.blogspot.com
Serial.print(yaw); //for info on which axis is which
Serial.print(" pitch:");
Serial.print(pitch);
Serial.print(" roll:");
Serial.println(roll);
delay(100);
}
Orientation:
Sorry for the arrows being all in the negative direction. Picture was done quickly.

ENJOY!
17 comments:
great! i will have a try later
Inspirational stuff, thank you!
Any snaps of your set up? Very impressive and cheap as chips! Good work knuckles
Great stuff! Soon the sky will be swarming with homebrew UAVs and the streets teeming with balancing robots thanks to Nintendo!
Thanks, I know where to turn for 6dof!
I'm confused, wouldn't this just give you 3 dof? Just rotation on 3 axes?
Since that it is using information from both the Nunchuck (using it's accelerometer) and the Wii Motion Plus (using it's gyroscope), it can detect acceleration as well as tilt (the tilt data is more accurate coming from the gyro than the accelerometer, especially during acceleration). You get 3 readings from each device (which is 6 readings).
Has anyone fried there arduino chip with this?
I bought the Wii-Motion-Plus and cabled it up as the example states.. ran it just fine.
Started to modify the code.. ie. was going to average the results for less bouncy-ness.. and I couldn't upload the code.. come to find out, the chip is dead.
I beleive it is the microcode (ie arduino-firmware) that is messed up.
Tried it on a second chip.. same thing happened.
Tried it on a second hardware-board and third chip.. same thing happened.
Really puzzled here.. and I hope someone else might clue me in..
Thanks
I'm mainly after this to get a straight rotational sensor, not even the 3 full axes of data, but I've hit a stumbling block after just opening the case...
My wiring to the Wii-extension port on the unit from the PCB, has 7 Wires. Not normally a big deal, but the colours do not even remotely match up to what's listed here, in terms of pin numbering.
I don't have the connector here to reference, but has anyone else seen a different wiring layout used in their WiiM+?
I tried your code with the 2 transistors. Works great ! Now for the Kalman filter. I want to use this to replace the expensive IR sensors in the Ardupilot. I also have been making an autopilot with the Parallax Propeller micro.
Hope to see the Kalman filter soon.
Earl
@mad robot : Never ever fried a chip yet. Have experimented with several ardunio boards no problem. This code works great. No problem here.
@k can we post pics of our projects that use the MP+ and Nun here ?
Mad_Robot here...
I did re-flash the chips. they were hosed.
The values I get from the sensor sometimes are low.. but most of the time are very large numbers.
So, if I were to make a guess, the homemade PCB-wii-adapter that I made might not be thick enough and maybe they are getting errorneous values. Values that might be bigger than an 'Arduino int' (>32k).. and possibly overwriting memory? (Not sure how Arduino would handle it).
So, I would ask (as I build a new PCB-wii-adapter) what is the average response range that people get from this code ie.(0-255)?
Thanks for the feedback.
MadR.
Does anyone know if the motion plus can cause trouble on the bus. I have hooked an i2C two axis accelerometer on the I2C bus and a wii motion plus, but it seems that i can't access the accelerometer (always reading zeros on accelerometer registers). I don't know if the trouble comes from the accelerometer or if the wii motion plus control the bus for every address ...
Hey,
I couldn't find any info on getting the MotionPlus to work with the passthrough (for the Nunchuck and Classic Controller), so I hooked it up to my logic analyzer and RE'd it.
Just wanted to let you know I updated my MotionPlus object for the Propeller (from the thread linked above) to work w/ the passthrough port: http://obex.parallax.com/objects/471/ . The code/comments should explain everything pretty well, so it should be easy to modify for the Arduino.
It alternates MotionPlus and Extension data on every other read, and you lose the LSBit of each accelerometer axis in Nunchuck mode (and the LSBit of each axis on the left joystick in Classic Controller mode), and it moves a couple bits around. I assume this is so you can tell the difference between MP data and Ext data (MP ends in 10, Ext ends in 00).
DogP
Muy bueno, genial.....muchas felicidades..
Solo le falta kalman....un 10
......
Very good, great ..... many congratulations ..
Only lacks kalman
Hi, great work here.
I've been able to interface with the nunchuck before but I can't get it to work with the M+. Can't even get the I2C start sequence to work.
I don't have a proper oscilloscope but it seems my clock and data lines are always low. Usually when I connect the nunchuck the lines would go high, not the case of the M+ though. And there's nothing wrong with my M+, works great in Sports Resort.
Any ideas?
Dan
Oh nevermind. I figured it out. It seems the M+ needs external pull-up resistors on the clock and data lines whereas the nunchuck doesn't. I tried 1K and 4K7 resistors, both worked fine (100KHz, 3.3V).
Dan
Post a Comment