Nintendo vs Nyko nunchuck Arduino communication

Awhile back, I ordered a wiichuck adapter so I could eventually use a nunchuck to with my arduino. Today I purchased a Nyko nunchuck (which claims to be 100% compatible with the Wii) instead of buying the original Nintendo nunchuck. I'm testing this sample code (below) and the arduino is not responding at all to the nunchuck. I don't have a Wii system to try the nunchuck. I'm kind of wondering if the Nyko nunchuck sends out different commands as the Nintendo nunchuck. I'll do some more testing with it and see if I can figure it out myself.

Thanks,
duemilanove

The code:

#include <Wire.h>
#include "nunchuck_funcs.h"

int loop_cnt=0;

byte accx,accy,accz,joyx,joyy,zbut,cbut;
int ledPin = 13;
int Lledpin = 2; // left led
int Rledpin = 3; // right led
int Uledpin = 4; // up led
int Dledpin = 5; // down led


void setup()
{
    Serial.begin(19200);
    nunchuck_setpowerpins();
    nunchuck_init(); // send the initilization handshake
    
    Serial.print("WiiChuckDemo ready\n");
}

void loop()
{
    if( loop_cnt > 10 ) { // every 100 msecs get new data
        loop_cnt = 0;

        nunchuck_get_data();

        accx  = nunchuck_accelx();
        accy  = nunchuck_accely();
        accz  = nunchuck_accelz();
        joyx  = nunchuck_joyx();
        joyy  = nunchuck_joyy(); 
        zbut = nunchuck_zbutton();
        cbut = nunchuck_cbutton(); 
        digitalRead(zbut);
        if(zbut == 1 ){
          digitalWrite(ledPin, HIGH);
        } else {
          digitalWrite(ledPin, LOW);
        }
        //Left led accelerometer
        if(accx <= 90){
          digitalWrite(Lledpin, HIGH);
        } else {
          digitalWrite(Lledpin, LOW);}
        //Right led accelerometer  
          if(accx >= 180){
          digitalWrite(Rledpin, HIGH);
        } else {
          digitalWrite(Rledpin, LOW);}
        //Up led accelerometer
          if(accy >= 165){
          digitalWrite(Uledpin, HIGH);
        } else {
          digitalWrite(Uledpin, LOW);}
        //Down led accelerometer
          if(accy <= 100){
          digitalWrite(Dledpin, HIGH);
        } else {
          digitalWrite(Dledpin, LOW);}
        //Right led joystick
        if(cbut == 1){
        if(joyx >= 210){
          digitalWrite(Rledpin, HIGH);
        } else {
          digitalWrite(Rledpin, LOW);}
        //Left led joystick
        if(joyx <= 50){
          digitalWrite(Lledpin, HIGH);
        } else {
          digitalWrite(Lledpin, LOW);}
        //Down led joystick
        if(joyy <= 70){
          digitalWrite(Dledpin, HIGH);
        } else {
          digitalWrite(Dledpin, LOW);}
        //Up led joystick
        if(joyy >= 210){
          digitalWrite(Uledpin, HIGH);
        } else {
          digitalWrite(Uledpin, LOW);}
        }
        
          
        
            
        Serial.print("accx: "); Serial.print((byte)accx,DEC);
        Serial.print("\taccy: "); Serial.print((byte)accy,DEC);
        Serial.print("\taccz: "); Serial.print((byte)accz,DEC);
        Serial.print("\tjoyx: "); Serial.print((byte)joyx,DEC);
        Serial.print("\tjoyy: "); Serial.print((byte)joyy,DEC);
    }
    loop_cnt++;
    delay(1);
}

and the nunchuck_funcs.h code

/*
 * Nunchuck functions  -- Talk to a Wii Nunchuck
 *
 * This library is from the Bionic Arduino course : 
 *                          http://todbot.com/blog/bionicarduino/
 *
 * 2007 Tod E. Kurt, http://todbot.com/blog/
 *
 * The Wii Nunchuck reading code originally from Windmeadow Labs
 *   http://www.windmeadow.com/node/42
 */

#include <WProgram.h>

static uint8_t nunchuck_buf[6];   // array to store nunchuck data,

// Uses port C (analog in) pins as power & ground for Nunchuck
static void nunchuck_setpowerpins()
{
#define pwrpin PORTC3
#define gndpin PORTC2
    DDRC |= _BV(pwrpin) | _BV(gndpin);
    PORTC &=~ _BV(gndpin);
    PORTC |=  _BV(pwrpin);
    delay(100);  // wait for things to stabilize        
}

// initialize the I2C system, join the I2C bus,
// and tell the nunchuck we're talking to it
static void nunchuck_init()
{ 
    Wire.begin();                // join i2c bus as master
    Wire.beginTransmission(0x52);// transmit to device 0x52
    Wire.send(0x40);// sends memory address
    Wire.send(0x00);// sends sent a zero.  
    Wire.endTransmission();// stop transmitting
}

// Send a request for data to the nunchuck
// was "send_zero()"
static void nunchuck_send_request()
{
    Wire.beginTransmission(0x52);// transmit to device 0x52
    Wire.send(0x00);// sends one byte
    Wire.endTransmission();// stop transmitting
}

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

// Receive data back from the nunchuck, 
// returns 1 on successful read. returns 0 on failure
static int nunchuck_get_data()
{
    int cnt=0;
    Wire.requestFrom (0x52, 6);// request data from nunchuck
    while (Wire.available ()) {
        // receive byte as an integer
        nunchuck_buf[cnt] = nunchuk_decode_byte(Wire.receive());
        cnt++;
    }
    nunchuck_send_request();  // send request for next data payload
    // If we recieved the 6 bytes, then go print them
    if (cnt >= 5) {
        return 1;   // success
    }
    return 0; //failure
}

// 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
static void nunchuck_print_data()
{ 
    static int i=0;
    int joy_x_axis = nunchuck_buf[0];
    int joy_y_axis = nunchuck_buf[1];
    int accel_x_axis = nunchuck_buf[2]; // * 2 * 2; 
    int accel_y_axis = nunchuck_buf[3]; // * 2 * 2;
    int accel_z_axis = nunchuck_buf[4]; // * 2 * 2;

    int z_button = 0;
    int c_button = 0;

    // byte nunchuck_buf[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 ((nunchuck_buf[5] >> 0) & 1) 
        z_button = 1;
    if ((nunchuck_buf[5] >> 1) & 1)
        c_button = 1;

    if ((nunchuck_buf[5] >> 2) & 1) 
        accel_x_axis += 2;
    if ((nunchuck_buf[5] >> 3) & 1)
        accel_x_axis += 1;

    if ((nunchuck_buf[5] >> 4) & 1)
        accel_y_axis += 2;
    if ((nunchuck_buf[5] >> 5) & 1)
        accel_y_axis += 1;

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

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

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

    Serial.print("acc:");
    Serial.print(accel_x_axis, DEC);
    Serial.print(",");
    Serial.print(accel_y_axis, DEC);
    Serial.print(",");
    Serial.print(accel_z_axis, DEC);
    Serial.print("\t");

    Serial.print("but:");
    Serial.print(z_button, DEC);
    Serial.print(",");
    Serial.print(c_button, DEC);

    Serial.print("\r\n");  // newline
    i++;
}

// returns zbutton state: 1=pressed, 0=notpressed
static int nunchuck_zbutton()
{
    return ((nunchuck_buf[5] >> 0) & 1) ? 0 : 1;  // voodoo
}

// returns zbutton state: 1=pressed, 0=notpressed
static int nunchuck_cbutton()
{
    return ((nunchuck_buf[5] >> 1) & 1) ? 0 : 1;  // voodoo
}

// returns value of x-axis joystick
static int nunchuck_joyx()
{
    return nunchuck_buf[0]; 
}

// returns value of y-axis joystick
static int nunchuck_joyy()
{
    return nunchuck_buf[1];
}

// returns value of x-axis accelerometer
static int nunchuck_accelx()
{
    return nunchuck_buf[2];   // FIXME: this leaves out 2-bits of the data
}

// returns value of y-axis accelerometer
static int nunchuck_accely()
{
    return nunchuck_buf[3];   // FIXME: this leaves out 2-bits of the data
}

// returns value of z-axis accelerometer
static int nunchuck_accelz()
{
    return nunchuck_buf[4];   // FIXME: this leaves out 2-bits of the data
}

I doubt the Nyko 'chuck is any different.

There're a few things I don't like in that code - but rather than guess at the problems/solutions, I'd just ask if you've tried this simpler example:

http://todbot.com/arduino/sketches/NunchuckPrint/NunchuckPrint.pde

Thanks for the reply. I tried out the code you gave me. The arduino still did not sense the nunchuck, it just gives me this:

Finished setup
0      joy:255,255        acc:258,258,258      but:1,1
1      joy:255,255        acc:258,258,258      but:1,1
2      joy:255,255        acc:258,258,258      but:1,1
3      joy:255,255        acc:258,258,258      but:1,1
4      joy:255,255        acc:258,258,258      but:1,1
5      joy:255,255        acc:258,258,258      but:1,1
6      joy:255,255        acc:258,258,258      but:1,1
7      joy:255,255        acc:258,258,258      but:1,1

I tried pressing the buttons, moving the joystick, and turning the remote around (to change the accelerometer values) multiple times, and I still get what I posted above.

Hmm...

Which power pin does that adapter connect to? I do know the nunchucks are supposed to be fed 3.3V and may not like it if you feed in 5V.

Edit: quick search indicates that some chucks don't care, and other return max values which might be what you're experiencing.

From
http://todbot.com/blog/2008/02/18/wiichuck-wii-nunchuck-adapter-available/

Tenshi
June 4th, 2010 at 4:20 pm

Hello all and tod,

I've got a WARNING for those using a “Black nunchuck”:
It will only run/work on 3.3v power.
If you use it with 5v you'll only get maxed out values however it is not blown up,
run it on 3.3v and it will work like a sunnyday.

The information about the connection of the wiichuck adapter to an arduino is here. It states that analog pins 2&3 act as the power supply. To test if power was actually coming out of analog pins 2&3, I put an led in the pins, and it turned on, so the nunchuck is getting power. Does anyone know what voltage Nyko nunchucks are meant to run at?

To test if power was actually coming out of analog pins 2&3, I put an led in the pins, and it turned on

Hopefully with a resistor?

Does anyone know what voltage Nyko nunchucks are meant to run at?

It may be that they are designed to run on +3.3V. Not knowing how much current it draws, I wouldn't recommend wiring the 3.3V pin to the power pin, but do you by chance have a 3.3v regulator? Or perhaps 2 AA/AAA batteries in series?

I might add that I've used the Nintendo Nunchuck with the Wiichuck following the examples exactly, and I get perfect results.

No I did not use a resistor. :-/ Did I make a big mistake there?


I do not have a 3.3v regulator.

Did I make a big mistake there?

That depends on how long you let it burn the LED for. Always remember that LEDs are power-hungry. They consume only a certain amount of voltage, but they will try to take as much current as possible, which heats them up, which will make them blow eventually.

But that's not the real problem. The problem is that any given Arduino output can only source at the VERY MOST 40mA of current. As your LED was trying to draw probably several hundred, you may have damaged the chip itself. If you only left it on for a small amount of time, you might not notice the damage, and it might work just fine.

In the future, always use >~100 Ohm resistor if connecting LEDs to the outputs, I always use 330 Ohm (check the LED's forward current, and use this handy little calculator to figure out the best resistance).

FYI, the onboard 3.3V pin supplies AT MOST ~50mA, and if you exceed that, you will fry the FTDI (the surface mount chip) USB-TTL converter. It has occurred to me, though, that if the designers of the Wiichuck felt comfortable supplying power via a digital output, then it must draw <40mA, and so you should be able to safely attach the power pin of the Wiichuck to the 3.3V pin of the board. Try that out, and let us know if it works!

Thanks for the great info. I don't think I damaged the chip. I only put the led in the pins for about 3 seconds, and I did not have any issues when just uploading the 'blink' code right now, and it worked fine. I'll try your tip about connecting the power to the 3.3v pin on the arduino. I'll reply if I have any luck with it.

I got the same results as last time:

The arduino still did not sense the nunchuck, it just gives me this:

Finished setup

0      joy:255,255        acc:258,258,258      but:1,1
1      joy:255,255        acc:258,258,258      but:1,1
2      joy:255,255        acc:258,258,258      but:1,1
3      joy:255,255        acc:258,258,258      but:1,1
4      joy:255,255        acc:258,258,258      but:1,1
5      joy:255,255        acc:258,258,258      but:1,1
6      joy:255,255        acc:258,258,258      but:1,1
7      joy:255,255        acc:258,258,258      but:1,1




I tried pressing the buttons, moving the joystick, and turning the remote around (to change the accelerometer values) multiple times, and I still get what I posted above.

What would happen if I powered it with 5v?

I got the same results as last time

Hmm..I'm afraid I've reached the end of my expertise on this matter :.

What would happen if I powered it with 5v?

Presumably the same thing that happened when you powered it via the Analog Input, as when you drive a pin HIGH, it just supplies +5V.

I really wish you had a Wii to make sure the controller works :(.

Thanks a bunch for your time and thoughts. I might see if I can possibly return the Nyko nunchuck and pick up a Nintendo one. The Nyko was cheaper, and said it was fully compatible with the Wii and Nintendo products, so I'm surprised at how it does not work with an arduino. If anyone has any other suggestions or tips, please post.

I have the wii nunchuck and it works well with power from the 3V3 pin. It also works fine with power from the 5V pin but just gets warm. Maybe your problem is happening because you are not doing the decoding of bytes:
x = (x ^ 0x17) + 0x17;

Here is a code I use that always works:

#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 ()
{
  beginSerial (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.send (0x40);            // sends memory address
  Wire.send (0x00);            // sends sent a zero.  
  Wire.endTransmission ();      // stop transmitting
}

void
send_zero ()
{
  Wire.beginTransmission (0x52);      // transmit to device 0x52
  Wire.send (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.receive ());      // 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 (100);
}

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

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

Try it one last time before buying the Nintendo Wii nunchuck :slight_smile:

Sorry royboy, I did not get the chance to try that code, but I successfully returned the Nyko, and got a Nintendo nunchuck, and everything is working perfectly! :slight_smile: I still don't understand why the Nyko did not work, unless it was defected when I bought it.

Me ha encantado este blog, estoy seguro que mis televidentes que disfrutan de esto también, voy a estar seguro para enlazar a esta y los favoritos, gracias!
r4 ds
nintendo ds r4
ps3 games
cheap ps3 games