Introduction: Arduino Wii Nunchuck and Wii Motion Plus With Updated Code for IDE 1.0.2 and LEDs

So, I was trying to hack my Wii nunchuck because I want to control motors and lights with the Wii nunchuck.

The first problem that I found was how to connect the control without an adapter, I was planning to make one, but
when I was searching for the nunchuck I also found the Wii motion plus accesory then I did notice that it haves a
Male interface it haves holes to put wires, I did a search for Wii motion hacks with arduino and I found some code.

Second problem I found was that the code to hack both nunchuck and wii motion plus are outdated and you have
to change some commands, like Serial.begin, Wire.write instead of Wire.send  etc,

So I had to fix the code and also I added leds!

Step 1: Materials

1 Arduino
1 Breadboard
1 Wii motion Plus
1 Wii Nunchuck
6 Resistors 220 ohm
6 Leds (any color)
Solid core jumper wires

Step 2: Build It

Pinout

|~~_____~~|
|                      |
|      6 4 2       |
|       -----        |
|      5 3 1       |
\_________/

From the Wiimote side
Pin  Cable color  Description
1  Green  SDA. I²C Serial Data
2  Orange  Ground
3  -  Not connected.
4  -  Not connected.
5  Red  3.3V
6  Yellow  SCL. I²C Serial Clock. (400 kHz)

Get 4 cables, and put them in the correct place, in the photo the orange wire is ground, is very important to notice
that the powerline  uses 3.3V, dont use the 5V powerline it will not fry your control, but is better to play Safe.

Connect Pin 5 Green cable to Analog 4(A4) and Pin 2 Yellow cable to Analog 5(A5) to the arduino, Pin 1 Red cable to Power 3.3V
and Pin 6 (in the photo the cable is orange) to ground.

Step 3: Build the Led Array

The led array is easier to make, remember the anode witch must be connected to the power(digital pin) is the longer leg, and the shorter one must be connected with a 220 ohm resistor to the ground, the pins that you must use are from 7 to 12.

Step 4: The Code

First you must test the Wii motion Plus, if it works then you just need to connect the Wii nunchuck and it will work too.
NOTE: I got the original code from this webpage:

http://arduino.cc/forum/index.php/topic,8507.0.html
I did not make the code I just fixed it to be able to run in the new Arduino IDE 1.0.2. and I added new code for the
leds, all the credits are for knuckles904.

Ok first you need to go to your arduino library and find the Wire carpet then go to Utility and find the archive twi.h open it
with wordpad and delete the lines from //#define ATMEGA8 to #endinf and paste these lines instead:
#define ATMEGA8

#ifndef CPU_FREQ^M
#define CPU_FREQ 16000000L
#endif

#ifndef TWI_FREQ^M
#define TWI_FREQ 100000L
#endif

Save the twi.h archive and now open your arduino IDE and copy and paste the code:

#include <Wire.h>
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.write(0xfe); //send 0x04 to address 0xFE to activate WM+
Wire.write(0x04);
Wire.endTransmission(); //WM+ jumps to address 0x52 and is now active
}

void wmpSendZero(){
Wire.beginTransmission(0x52); //now at address 0x52
Wire.write(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.read();
}
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.read();
}
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);

pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
pinMode(10, OUTPUT);
pinMode(9, OUTPUT);
pinMode(8, OUTPUT);
pinMode(7, OUTPUT);
}

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);


if (pitch >= 1000){
digitalWrite(12,HIGH);

}

else if (pitch <= -1000){
digitalWrite(11,HIGH);

}
else if (yaw >= 1000){
digitalWrite(10,HIGH);

}

else if (yaw <= -1000){
digitalWrite(9,HIGH);

}
else if (roll >= 1000){
digitalWrite(8,HIGH);

}

else if (roll <= -1000){
digitalWrite(7,HIGH);

}
else {
digitalWrite(11,LOW);
digitalWrite(12,LOW);
digitalWrite(10,LOW);
digitalWrite(9,LOW);
digitalWrite(8,LOW);
digitalWrite(7,LOW);
}
}

Step 5: Test It

Now the Wii Motion Plus haves 3 axis acelerometers, run the sketch in your arduino, open the Monitor Serial, move your wii motion plus and check how the leds and the motion serial works, titl it to the front, back, right left etc it should work fine, each Led programed to turn on for each positive and negative axis X,Z and Y

Step 6: Wii Nunchuck Code

Now that the Wii motion plus is working fine, you can just attach the Wii Nunchuck to the back of the wii motion plus with no troubles,
the data will pass right through, and you are ready to test the nunchuck but you will need new code, open a new arduino IDE, copy and paste the code:

Again the code is not mine I just fixed to be able to run in the ned IDE and I added leds, the original code is from this webpage:

http://www.windmeadow.com/node/42

all the credits for the code are for chadphillips

you dont need to chage anything in the breadboard it will work with the nunchuck



#include <Wire.h>
#include <string.h>

#undef int
#include <stdio.h>

uint8_t outbuf[6];        // array to store arduino output
int cnt = 0;
int ledPin = 13;

void
setup ()
{
  pinMode(7,OUTPUT);
  pinMode(8,OUTPUT);
  pinMode(9,OUTPUT);
  pinMode(10,OUTPUT);
  pinMode(11,OUTPUT);
  pinMode(12,OUTPUT);
 
  Serial.begin (19200);
  Serial.print ("Finished setup\n");
  Wire.begin ();        // join i2c bus with address 0x52
  nunchuck_init (); // send the initilization handshake
}

void
nunchuck_init ()
{
  Wire.beginTransmission (0x52);    // transmit to device 0x52
  Wire.write (0x40);        // sends memory address
  Wire.write (0x00);        // sends sent a zero. 
  Wire.endTransmission ();    // stop transmitting
}

void
send_zero ()
{
  Wire.beginTransmission (0x52);    // transmit to device 0x52
  Wire.write (0x00);        // sends one byte
  Wire.endTransmission ();    // stop transmitting
}

void
loop ()
{
  Wire.requestFrom (0x52, 6);    // request data from nunchuck
  while (Wire.available ())
    {
      outbuf[cnt] = nunchuk_decode_byte (Wire.read ());    // receive byte as an integer
      digitalWrite (ledPin, HIGH);    // sets the LED on
      cnt++;
    }

  // If we recieved the 6 bytes, then go print them
  if (cnt >= 5)
    {
      print ();
    }

  cnt = 0;
  send_zero (); // send the request for next bytes
  delay (10);
}

// Print the input data we have recieved
// accel data is 10 bits long
// so we read 8 bits, then we have to add
// on the last 2 bits.  That is why I
// multiply them by 2 * 2
void
print ()
{
  int joy_x_axis = outbuf[0];
  int joy_y_axis = outbuf[1];
  int accel_x_axis = outbuf[2] * 2 * 2;
  int accel_y_axis = outbuf[3] * 2 * 2;
  int accel_z_axis = outbuf[4] * 2 * 2;

  int z_button = 0;
  int c_button = 0;

 // byte outbuf[5] contains bits for z and c buttons
 // it also contains the least significant bits for the accelerometer data
 // so we have to check each bit of byte outbuf[5]
  if ((outbuf[5] >> 0) & 1)
    {
      z_button = 1;
    
    }
  if ((outbuf[5] >> 1) & 1)
    {
      c_button = 1;
     
    }

  if ((outbuf[5] >> 2) & 1)
    {
      accel_x_axis += 2;
    }
  if ((outbuf[5] >> 3) & 1)
    {
      accel_x_axis += 1;
    }

  if ((outbuf[5] >> 4) & 1)
    {
      accel_y_axis += 2;
    }
  if ((outbuf[5] >> 5) & 1)
    {
      accel_y_axis += 1;
    }

  if ((outbuf[5] >> 6) & 1)
    {
      accel_z_axis += 2;
    }
  if ((outbuf[5] >> 7) & 1)
    {
      accel_z_axis += 1;
    }

  Serial.print (joy_x_axis, DEC);
  Serial.print ("\t");

  Serial.print (joy_y_axis, DEC);
  Serial.print ("\t");

  Serial.print (accel_x_axis, DEC);
  Serial.print ("\t");

  Serial.print (accel_y_axis, DEC);
  Serial.print ("\t");

  Serial.print (accel_z_axis, DEC);
  Serial.print ("\t");

  Serial.print (z_button, DEC);
  Serial.print ("\t");

  Serial.print (c_button, DEC);
  Serial.print ("\t");

  Serial.print ("\r\n");
 
 if  (z_button == 0){
   digitalWrite(7,HIGH);
 }
 
 else if  (c_button == 0){
   digitalWrite(8,HIGH);
 }
 
  else if  (joy_x_axis >= 190){
   digitalWrite(9,HIGH);
 }
 
 else if  (joy_x_axis <= 60){
   digitalWrite(10,HIGH);
 }
 
 else if  (joy_y_axis >= 190){
   digitalWrite(11,HIGH);
 }
 
  else if  (joy_y_axis <= 60){
   digitalWrite(12,HIGH);
 }
 
 else{
 
 digitalWrite(7,LOW);
 digitalWrite(8,LOW);
 digitalWrite(9,LOW);
 digitalWrite(10,LOW);
 digitalWrite(11,LOW);
 digitalWrite(12,LOW);
 }
}

// Encode data to format that most wiimote drivers except
// only needed if you use one of the regular wiimote drivers
char
nunchuk_decode_byte (char x)
{
  x = (x ^ 0x17) + 0x17;
  return x;
}

Step 7: Conclusion

OK so, now when you push C or Z button a led will turn on, if you move the joystick to the right, left, up or down a different led will turn on, you can check also the real time data in the serial monitor(dont forget to choose the correct baud rate), I didnt programed
leds for the nuncuck acelerometer because I would need another array of 4 leds and is already covered in the wii motion plus, so now the imagination is your limit, right now you can get data from 2 acelerometers, 1 joystick and 2 buttons, that means that you have
16 different input data from both controls 14 are analog and 2 are digital(the buttons), that means you can control motors, servos, lights, 3D software, music, etc with your nunchuck and your wii motion plus.

NOTE: Nunchuck control dont have Yaw sensor only pitch and roll

I found also that there is a new nunchuck library here:

http://playground.arduino.cc/Main/WiiChuckClass

and it haves code to move a 3D cube with the software progress

so what are you waiting for??


I did this instructable to keep the tutorials updated, hope they can help you.

Comments

author
quike_gon (author)2014-08-22

Hello, I has looking for code to operate Wii sensor for my quadcopter, so thanks!

Just one thing: Will Nunchuck interfere with WMP? When you send Wire.requestFrom(0x52, 6); What do you receive? WMP data or nunchuck data?

author
animes25 (author)quike_gon2014-09-27

they dont interfere, in fact both gives you different data, motion plus is more accurate, I added the nuchuck just in the case that you want a joystick to control robots or cars

author
mjhearn (author)2014-09-06

was wondering, how'd that stabilizer work for you?

author
rsafa (author)2013-06-20

great job,I want to start with this project.can you please tell me if this can work without adding the nunchuck?I want to build a camera stabiliser(a very small camera) using servos and wii motion plus.if you have some good ideas with this project,let ma know please.greetings from France

author
animes25 (author)rsafa2013-11-10

Yes you can work with no nunchuck control, and make your camera stabiliser, but I think that you will need also a gyro sensor.

About This Instructable

11,412views

23favorites

License:

More by animes25:Arduino Portable Weather Monitor, altimeter, temperature, humidity, using DHT11 and BMP85 with LCD using only 3 pinsGoPro Ultrasonic Motion Sensor HC-SR04 controled by arduinoFull Color electroluminescent decals with El Panel
Add instructable to: