Wii Nunchuck Troubleshooting

I have just discovered the Wii Nunchuck code and am trying to figure out why the data is not updating. I am not using the Wiichuck adapter, I opted wire directly to the Arduino. I am able to receive some kind of data from the nunchuck, but it does not adjust when I tinker with the nunchuck. It remains unchanged (255 255...1 1). I have searched everywhere and there seems to be no one who has addressed this problem.

I am starting to think that the problem lies within the adjustments to with twi.h file suggested on the windmeadow website. I have not found any other references to what should be done with that file. This is just a thought. Can someone please help?

please post your code, we cannot see it :slight_smile:

Code:

/*==========================================================
Arduino Wii Nunchuck Hack
orginal code provided by windmeadow.com
===========================================================*/
#include <Wire.h> //includes outside library Wire for this sketch

static uint8_t outbuf[6]; //array to store arduino output
int cnt = 0;
int ledPin = 13;
 
void setup() {
 
  Serial.begin(115200);
  Wire.begin(); //join i2c bus with address 0x52
  nunchuck_init(); //runs the nunchuck_init function defined below
  Serial.print( "Finished setup\n");
 
}// end of setup function
 
void nunchuck_init() {
  //This function sends the initialization handshake
 
  Wire.beginTransmission (0x52); //transmit to device 0x52
  Wire.send (0x40); //sends memory address
  Wire.send (0x00); //sends a zero
  Wire.endTransmission (); //stop transmitting
 
}// end of nunchuck_init function

void send_zero(){
 
  Wire.beginTransmission (0x52); //transmit to device 0x52
  Wire.send (0x00); //sends a zero
  Wire.endTransmission (); //stop transmitting
 
}//end send_zero function
 
void loop(){
 
  Wire.requestFrom(0x52,6); //request data from nunchuck
 
  while(Wire.available()) {
   
    outbuf[cnt] = nunchuk_decode_byte (Wire.receive()); // receive byte as an integer
    digitalWrite (ledPin, HIGH); // sets the LED on
    cnt++;
   
  }//end while loop
 
 
  //If we received the 6 bytes, then print them
  if (cnt >=5) {
   
    printNunchukData(); //runs print function below
   
  }//end if
 
  cnt = 0;
 
  send_zero(); //send the request for the next bytes
  send_zero(); //send the request for the next bytes
  send_zero(); //send the request for the next bytes
 
  delay(100); //delay 100 milliseconds 
 
}//end loop function

void printNunchukData(){
  /*This function prints the received input data. Accelerometer 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 2*2 */
 
  int joy_x_axis = outbuf[0];
  int joy_y_axis = outbuf[1];
  int acel_x_axis = outbuf[2] * 2 * 2;
  int acel_y_axis = outbuf[3] * 2 * 2;
  int acel_z_axis = outbuf[4] * 2 * 2;
 
  int z_button = 0;
  int c_button = 0;
 
  /*outbuf[5] contains bits for z and c buttons. It also contains
  the least significant bits for the accelerometer data. So each
  bit of the outbuf[5] byte has to be checked. */
 
 
  if ((outbuf[5] >> 0) & 1) {
    z_button = 1;
  }
 
  if ((outbuf[5] >> 1) & 1) {
    c_button = 1;
  } 
  if ((outbuf[5] >> 2) & 1) {
    acel_x_axis += 2;   
  }
 
  if ((outbuf[5] >> 3) & 1) {
    acel_x_axis += 1;
  }
 
  if ((outbuf[5] >> 4) & 1) {
    acel_y_axis += 2;
  }
 
  if ((outbuf[5] >> 5) & 1) {
    acel_y_axis += 1;
  }
 
  if ((outbuf[5] >> 6) & 1) {
    acel_z_axis += 2;
  }
 
  if ((outbuf[5] >> 7) & 1) {
    acel_z_axis += 1;
  }
 
  Serial.print (joy_x_axis, DEC);
  Serial.print ("\t");
 
  Serial.print (joy_y_axis, DEC);
  Serial.print ("\t");
 
  Serial.print (acel_x_axis, DEC);
  Serial.print ("\t");
 
  Serial.print (acel_y_axis, DEC);
  Serial.print ("\t");
 
  Serial.print (acel_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"); 
 
}//end printNunchukData function

char nunchuk_decode_byte (char y) {
  //Encode data to a format that most wiimote drivers accept
  //only needed if you use one of the regular wiimote drivers
 
  y = (y ^ 0x17) + 0x17;
  return y;
 
}//end nunchuk decode
Wire.requestFrom(0x52,6); //request data from nunchuck
 
  while(Wire.available()) {
   
    outbuf[cnt] = nunchuk_decode_byte (Wire.receive()); // receive byte as an integer
    digitalWrite (ledPin, HIGH); // sets the LED on
    cnt++;
   
  }//end while loop
 
 
  //If we received the 6 bytes, then print them
  if (cnt >=5) {
   
    printNunchukData(); //runs print function below
   
  }//end if
 
  cnt = 0;

You request 6 bytes
suppose there are 3 available (less than 6)
the while loop will capture those 3
we dont have more than 4 so we print nothing
and make the counter zero again.

So the thext three readings will overwrite the three reading you allready have

so your code is a bit too optimistic

here some rewrite to make it more robust

void loop()
{
  Wire.requestFrom(0x52,6); //request data from nunchuck
 
  unsigned long timer = millis();
  cnt = 0;
  while (cnt < 6 && millis() - timer < 10000)  // wait max 10 seconds to receive those bytes
  {
    if (Wire.available()) 
    {
      outbuf[cnt] = nunchuk_decode_byte (Wire.receive()); // receive byte as an integer
      digitalWrite (ledPin, HIGH); // sets the LED on
      cnt++;
    }
  }  
  //If we received the 6 bytes, then print them
  if (cnt == 6) 
  { 
    printNunchukData(); //runs print function below 
  } 
  else
  {
    Serial.println(cnt); // debugging purpose
  }
//... rest of code
}

The data still remains unchanged from the Wii Nunchuck

give this a try - it can see if there are devices on the Wire (set baudrate @115200)

// I2C Scanner
// Written by Nick Gammon
// Date: 20th April 2011

#include <Wire.h>

void setup() {
  Serial.begin (115200);
  Serial.println ();
  Serial.println ("I2C scanner. Scanning ...");
  byte count = 0;
  
  Wire.begin();
  for (byte i = 1; i < 120; i++)
  {
    Wire.beginTransmission (i);
    if (Wire.endTransmission () == 0)
      {
      Serial.print ("Found address: ");
      Serial.print (i, DEC);
      Serial.print (" (0x");
      Serial.print (i, HEX);
      Serial.println (")");
      count++;
      } // end of good response
     delay (5);  // give devices time to recover
  } // end of for loop
  Serial.println ("Done.");
  Serial.print ("Found ");
  Serial.print (count, DEC);
  Serial.println (" device(s).");
}  // end of setup

void loop() {}

Using the I2C scanner, the nunchuck was found. And the address was verified (0x52).

I've used the code from here and it works.
http://home.online.no/~togalaas/ardubot/
Failing that I have some other code that will work.

Don't forget the 2k7 pullup resistors to 3v3 on the SDA and SCL lines.

Mark

Hey guys... I've been reading the forum for quite some time but never registered as i never had the need to ask something. Many people in here are very helpful and up to this day, i've always found what i was looking for. BUT today i have the same problem listed above... I tried with and without pull up resistors but the results are the same. It keeps on sending 255,255 for the joystick and 258,258,258 for the accelerometer. I tried many different codes (including those from the playground,todbot,windmeadow) but no luck.I also tried tweaking the twi.h as suggested but no change whatsoever. The i2c scanner works and recognises the nunchuck but as i said, no change of values when i plug it in... Anyone who has resolved a similar problem? Many thanks in advance to any kind soul who will reply. peace!

P.S. I am using an arduino duemilanove with atmega328 and a nunchuck purchased from gamestop (so it's not original).

I've the same problem, Willie_dv2.

But, I have a trick: the problems is print data! :wink:
First: Use this library http://arduino.emsley.ca/wiki/Nunchuck
Second: Try to use analogWrite(), like that:

void loop() {

  Nunchuck.getData();

  accelx = Nunchuck.accelx();
  accely = Nunchuck.accely();

  accelx = map(accelx, 280, 730, 0, 255);
  accely = map(accely, 280, 720, 0, 255);

  analogWrite(13, accelx);
  analogWrite(12, accely);
}

The code was cut, but if don't understand, ask me the complete sketch.

Best regards,

Willian Paixao

Guys
I have been using both a normal wired genuine Nunchuk and a wireless version from DealExtreme, and my initialisation and read code values are different to yours.
Maybe these might help.

// initiate Wii Nunchuk
      //Serial.print ("Initialising Wii Nunchuk ........");
      Wire.beginTransmission(0x52); //0xA4
      Wire.send(0xF0);
      Wire.send(0x55);
      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();

Mark

MarkB, that fixed the problem. I am now able to see a change in data. Thanks so much!!! Thanks to everyone who has offered suggestions and advice. Mark, May I ask how did you come across this initialization code?

@SAIcon
I was following the thread for a Balancing Robot, which used the Nunchuk (NC) and Motion Plus (MP).
The codes are modified because the MP receives the data, manipulates it and the controller (Arduino or Wii) then gets it from the MP.

I recall that in amongst all the thread there was a reference to the Wiki Wiimote/Extension Controllers - WiiBrew about Wii, and its in there tied up with the eprom address to read. (Looking at the codes .. it seems its the same as if a MP is plugged in, so maybe its intelligent enough)

Anyway glad it's resolved.
I've got some code for a Nunchuk controlled BOT using the joystick if you want.

Mark

@MarkB, Gotcha and sure I would love to see the code for the BOT

SAIcon
grab it from here
http://www.markbeckett.co.cc/ArduinoProjects.htm

cheers Mark