Wii Motion Plus outputs '0' only

Hey folks,

I have been trying to interface a Wii Motion Plus to my Arduino Uno board for a project I have been working on and have been running into problems getting any meaningful values from the sensor.

Whenever I try and connect up the sensor and run the program, the data coming out of the serial monitor gives '0' values for each variable as shown below regardless of moving the WM+ in any direction or whether or not the device is connected up to the Arduino.

WM+ tester
Yaw0:0 Pitch0:0 Roll0:0
yaw:0 pitch:0 roll:0
yaw:0 pitch:0 roll:0
yaw:0 pitch:0 roll:0
yaw:0 pitch:0 roll:0

I have wired up the WM+ to the Arduino using the VCC, Ground, SCL and SDA pins according to the image below with the SCL and SDA going via 680ohm resistors into A5 and A4 respectively as shown in the Make tutorial (Make: Projects).

The code I have been using is from the Make tutorial, which I have also included below:

/*
Make Projects
Arduino Wii Motion Plus Data Reader
This code is used for the Make Projects: Wii Motion Plus on the Arduino.
Miles code did not include a license however we would like to thank him for posting it!
Author: Miles Moody
Home Page:
http://randomhacksofboredom.blogspot.com/2009/07/motion-plus-and-nunchuck-together-on.html
*/

#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.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 for each zero
    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; //see http://wiibrew.org/wiki/Wiimote/Extension_Controllers#Wii_Motion_Plus
  pitch=((data[4]>>2)<<8)+data[1]-pitch0; //for info on what each byte represents
  roll=((data[5]>>2)<<8)+data[2]-roll0;
}

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






/*
Additional Reading:
The wii motion plus's initialization sequence was pull from here:
http://wiibrew.org/wiki/Wiimote/Extension_Controllers#Wii_Motion_Plus
The data format is well documented here:
http://wiibrew.org/wiki/Wiimote/Extension_Controllers#Data_Format_.28Wii_Motion_Plus.29
More pinout diagrams can be found here:
http://wiibrew.org/wiki/Wiimote/Extension_Controllers#Hardware_.28Wii_Motion_Plus.29
*/

In terms of troubleshooting I have checked and rechecked all the connections multiple times and have tried searching for a similar problem and solution both here on the forum and elsewhere on the internet. Based on the discussion in a thread here (http://arduino.cc/forum/index.php/topic,16728.0.html) I thought that perhaps the fact that I was originally using a Wii Motion Plus clone was the reason for these results (or lack thereof) but after purchasing an official Nintendo WM+ and getting the same output result, the problem must be elsewhere. Other sites seem to have discussion mentioning this issue but no clear solution that remedies the problem.

Given that the output remains the same regardless of a connection to the WM+ I assume that the issue relates to the communication between the two devices, but while I am trying to learn more about it I am relatively new to I2C.

Anyone with any ideas, experience or tips with this problem would be very much appreciated.

Many Thanks,
Kristian

you don't have to use vcc(5V) but 3,3V

Lesto,

Thanks but unfortunately using the 3.3V or 5V pin doesn't seem to make a difference for me - the output remains the same...
Unless of course I have inadvertedly fried both chips... :~

Kristian

the pull up like in the schema are wrong. (they are NOT pull up). Try eliminating them.
If doesn't still work use 2 2.2kohm resistor, one from SCL to 3.3V and one from SDA to 3.3V (that's pull up!!)

did you move WMP? it read angular acceleretion, so when it is stable is normal to read 0

Kristan
here is the code I use.
2k7 pullups to 3v3, 3v3 to power the MP/NC

// .......................................................................
// Code for reading data from a Wii Motion plus device connected to a Nunchuck
// Links to other sites
// http://www.windmeadow.com/node/42   .... first time i saw arduino nunchuk interface
// http://www.kako.com/neta/2009-017/2009-017.html# .....Japanese site with lots of Wii info
// http://wiibrew.org/wiki/Wiimote/Extension_Controllers#Wii_Motion_Plus    .... the one and only
// http://randomhacksofboredom.blogspot.com/2009/06/wii-motion-plus-arduino-love.html
// ....original motion plus but not passthrough
// http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1248889032/35   .... great Kalman filter code
// thanks to duckhead and knuckles904. I will be using that code for sure.
// http://obex.parallax.com/objects/471/   .... ideas for passthrough
// by Krulkip
// Here is the bitmapping which is changed from the standard nunchuk mapping
// In Nunchuk mode:
//	    Bit
// Byte     7	 6	 5	 4	 3	 2	 1	 0
// 0	 SX<7-----------------------------------------------------0>
// 1	 SY<7-----------------------------------------------------0>
// 2	 AX<9-----------------------------------------------------2>
// 3	 AY<9-----------------------------------------------------2>
// 4	 AZ<9---------------------------------------------3>	1
// 5	 AZ<2-----1>     AY<1>   AX<1>   BC	BZ	 0/1	 0
// Please note also the loss of the bit0 resolution.
// Byte 5 Bit 1 is used to signify what data (0) = nunchuk, (1) is motion plus.
// Byte 4 Bit 0 is the extention controller detection bit. (1 = extension present)
// Hardware Arduino with ATMega 328
// Connections SCA to AD4 (Analog4) and SCL to AD5 (Analog5) with pullup of 2k7 to 3.3 volts
//........................................................................
// The Arduino I2C uses 7 bits, therefore the MP address (0xA6) becomes 0x53, and the (0xA4) becomes 0x52
// Modified by Mark Beckett
// May 2010

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

//setup the variables, etc
int ledPin = 13;
int xID;

//Nunchuck
uint8_t outbuf[6];           //nunchuck buffer for data
int cnt = 0;                 //nunchuck buffer counter
int joy_x_axis;              //Joystick x (8 bits)
int joy_y_axis;              //Joystick y (8 bits)
int accel_x_axis;            //Nunchuck x (10 bits - bit0)
int accel_y_axis;            //Nunchuck y (10 bits - bit0)
int accel_z_axis;            //Nunchuck z (10 bits - bit0)

//Wii Motion Plus
byte data[6];                //buffer for WM+ data
int yaw, pitch, roll;        //three gyroscope axes (14 bits)
int yaw0, pitch0, roll0;     //calibration zeroes
bool yaw_v, pitch_v, roll_v; //calibration zeroes


// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);


void setup (){
  Serial.begin (19200);
// set up the LCD's number of rows and columns:
   lcd.begin(16, 2);
  //lcd.clear();
  lcd.setCursor(0,0);
  lcd.print ("Initialising");
  Wire.begin();
  Serial.print ("Finished setup\n");
  Serial.print ("Now detecting WM+\n");
  delay(100);
  
// innitiate Wii Motion plus
    Serial.print ("Initialising Wii Motion plus ........");
    Wire.beginTransmission(0x52); //0xA6
    Wire.send(0xF0);
    Wire.send(0x55);
    Wire.endTransmission();
    Serial.print (" OK done"); 
    Serial.print ("\r\n");
    delay (100); 
  
// nunchuk mode = 05, wm+ only = 04, classic controller = 07
    Serial.print ("Initialising Wii Motion Plus for Nunchuk in passthru mode = 05 ........");
    Wire.beginTransmission(0x53); //0xA6
    Wire.send(0xFE);
    Wire.send(0x05);// nunchuk in pass thru mode
    Wire.endTransmission();
    Serial.print (" OK done");
    Serial.print ("\r\n");
    delay (100);
    
    Serial.print ("Set reading address at 0xFA .......");
    Wire.beginTransmission(0x52); //0xA4
    Wire.send(0xFA);
    Wire.endTransmission();
    Serial.print(" OK done");
    Serial.print ("\r\n");
    delay (100);
    Wire.requestFrom (0x52,6);  //0xA4
   outbuf[0] = Wire.receive();Serial.print(outbuf[0],HEX);Serial.print(" ");
   outbuf[1] = Wire.receive();Serial.print(outbuf[1],HEX);Serial.print(" ");
   outbuf[2] = Wire.receive();Serial.print(outbuf[2],HEX);Serial.print(" ");
   outbuf[3] = Wire.receive();Serial.print(outbuf[3],HEX);Serial.print(" ");
   outbuf[4] = Wire.receive();Serial.print(outbuf[4],HEX);Serial.print(" ");
   outbuf[5] = Wire.receive();Serial.print(outbuf[5],HEX);Serial.print(" ");
   Serial.print ("\r\n");
   xID= outbuf[0] + outbuf[1] + outbuf[2] + outbuf[3] + outbuf[4] + outbuf[5];
   //Serial.print("Extension controller xID = 0x");
   //Serial.print(xID,HEX);
   //delay (200);
   if (xID == 0xCB) { Serial.print (" Wii Motion plus connected but not activated"); } // 00 00 A6 20 00 05
   if (xID == 0xCE) { Serial.print (" Wii Motion plus connected and NC activated"); } // 00 00 A4 20 00 05
   if (xID == 0x00) { Serial.print (" Wii Motion plus not connected"); } // 00 00 00 00 00 00
   Serial.print ("\r\n");
   lcd.setCursor (0,0);
   lcd.print("Motion Plus OK");
   lcd.setCursor (0,1);
   lcd.print (" Nunchuck OK");
   delay (500);
   // Now we want to point the read adress to 0xa40008 where the 6 byte data is stored
    Serial.print ("Set reading address at 0x08 .........");
    Wire.beginTransmission(0x52);
    Wire.send(0x08);
    Wire.endTransmission();
    Serial.print(" OK done");
    Serial.print ("\r\n");
    lcd.clear();
  }
void send_zero (){
    Wire.beginTransmission(0x52);
    Wire.send(0x00);
    Wire.endTransmission();
}
void loop (){
// now follows conversion command instructing extension controller to get
// all sensor data and put them into 6 byte register within the extension controller

  send_zero (); // send the request for next bytes
  delay (100);
  Wire.requestFrom (0x52,6);
  outbuf[0] = Wire.receive();
  outbuf[1] = Wire.receive();
  outbuf[2] = Wire.receive();
  outbuf[3] = Wire.receive();
  outbuf[4] = Wire.receive();
  outbuf[5] = Wire.receive();
  print ();
  cnt = 0;
 
 delay (100); //slow down the printing
}
void print (){
// check if nunchuk is really connected
// Byte(4) bit 0 is 1 if the extension is connected
  if ((outbuf[4]&0x01)==0x01) {
  Serial.print("Ext con: ");
  }

 if ((outbuf[5]&0x03)==0x00) { //Nunchuck Data
 int joy_x_axis = outbuf[0];
 int joy_y_axis = outbuf[1];
 int accel_x_axis = (outbuf[2] << 2) + ((outbuf[5] >> 3) & 2);
 int accel_y_axis = (outbuf[3] << 2) + ((outbuf[5] >> 4) & 2);
 int accel_z_axis = (outbuf[4] << 2) + ((outbuf[5] >> 5) & 6);
 int z_button = (outbuf[5]>>2) & 1;
 int c_button = (outbuf[5]>>3) & 1;
  Serial.print ("joyx= ");
  Serial.print (joy_x_axis, DEC);
  Serial.print ("  joyy=");
  Serial.print (joy_y_axis, DEC);
  Serial.print ("  accx= ");
  Serial.print (accel_x_axis, DEC);
  Serial.print ("  accy= ");
  Serial.print (accel_y_axis, DEC);
  Serial.print (" accz= ");
  Serial.print (accel_z_axis, DEC);
  Serial.print ("  ");
  if (z_button == 0) { Serial.print ("z_button "); }
  if (c_button == 0) { Serial.print ("c_button "); }
  Serial.print ("\r\n");
  
   //Send the Accelerometer data to the first line
  lcd.setCursor (0,0);
  lcd.print ("x"); lcd.print (accel_x_axis,DEC);
  lcd.setCursor (5,0);
  lcd.print ("y"); lcd.print (accel_y_axis,DEC);
  lcd.setCursor (10,0);
  lcd.print ("z"); lcd.print (accel_z_axis,DEC);
 }
else if  ((outbuf[5]&0x03)==0x02) { //MP data
  int yaw = (((outbuf[5]&0xFC)<<6) + outbuf[2]);
  int pitch = (((outbuf[4]&0xFC)<<6) + outbuf[1]);
  int roll = (((outbuf[3]&0xFC)<<6) + outbuf[0]);
  Serial.print ("yaw= ");
  Serial.print (yaw, DEC);
  Serial.print ("  pitch= ");
  Serial.print (pitch, DEC);
  Serial.print ("  roll= ");
  Serial.print (roll, DEC);
  Serial.print ("\r\n");
  
  //Send the Gyro data to the second line
  lcd.setCursor (0,1);
  lcd.print ("w"); lcd.print (yaw,DEC);
  lcd.setCursor (5,1);
  lcd.print ("r"); lcd.print (roll,DEC);
  lcd.setCursor (10,1);
  lcd.print ("p"); lcd.print (pitch,DEC);
  Serial.print ("yaw= ");
  Serial.print (yaw, DEC);
  Serial.print ("  pitch= ");
  Serial.print (pitch, DEC);
  Serial.print ("  roll= ");
  Serial.print (roll, DEC);
  Serial.print ("\r\n");
 }
 }

Mark

hey guys,

Thanks to all your help, I finally managed to get the WM+ working! It seemed like one of those things where I had tested some of those changes such as changing the voltage, removing the resistors etc individually but hadn't put them all together in the right combination.

So I managed to get the official Nintendo WM+ working, but after all the moving around and testing of the clone my makeshift wiring has come apart a little so I will have to fix that up before confirming if the clone works also. The sensor now works for the code you put up markB and also for the original code I was using, which is also a good sign.

Thanks lesto and markB both for your help here, it is much appreciated! Now I just have to apply it to my project - a rocket telemetry and parachute release system...

cheers,

Kristian

Thats great news.

It sounds like a very interesting (and expensive if not right) project.

mark

Hey can you explain what exactly u did, i have the same problem, getting all 0's tried with pullup of 2.2k ohm, or without always getting 0s i also have a nunchuck so im trying to us markBs code. oh also getting "Wii Motion plus not connected"

EDIT: also found out that if i plug my wm+ only withot nunchuck it freezes at initialization at Wire.endTransmission();

Hi w1ndf4k3r.
Can you double check and make sure that SCL (clock) is connected to pin A5, and SDA (Data) is connected to pin A4 please.
The MP (and NC) use 3.3v, so please ensure your Arduino board is providing the 3.3 volts to the Power pin of the MP, it is also necessary to ensure the ground is connected to the Arduino board as well.

I pulled my MP apart and soldered directly to the pcb, rather than making a plug.

There are different initialisation codes when the MP is NOT connected in series with the NC.
I haven't tried the code with a MP only, so I can't suggest what would happen, and freezing is quite likely.

The resistors aren't a choice, they are there to ensure the line is pulled up, rather than randomly floating.
The I2C device (in this case the MP or NC) pull down this line to pass data.

Hopefully these suggestions will help you.

Mark