low-cost nunchuck fix

Hey there!

I just spent the whole night trying to make a low xost wii nunchuck bought from ebay work. According to this http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1264805255 topic the solution seems close, but i have some trouble implementing it:
The compilation is interrupted, and i receive the following error:

sketch_aug18b.cpp: In function ‘void nunchuck_init()’:
sketch_aug18b:56: error: ‘ctrlr_type’ was not declared in this scope

Please help me out, the code is definetly too complicated for my skill level, but I want to use the nunchuck so much :astonished:
Thanks,
Jannai

The code is the follwing:

/*
 * NunchuckPrint
 *
 * 2007 Tod E. Kurt, http://todbot.com/blog/
 *
 * The Wii Nunchuck reading code is taken from Windmeadow Labs
 *   http://www.windmeadow.com/node/42
 */
 
#include <Wire.h>

void setup()
{
  Serial.begin(19200);
  nunchuck_setpowerpins(); // use analog pins 2&3 as fake gnd & pwr
  nunchuck_init(); // send the initilization handshake
  Serial.print ("Finished setup\n");
}

void loop()
{
  nunchuck_get_data();
  nunchuck_print_data();
  delay(100);
}


//
// Nunchuck functions
//

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
void nunchuck_init()
{ 
  int cnt=0;
 Wire.beginTransmission(0x52);
Wire.write(0xFA);		        // extension type register
Wire.endTransmission();
Wire.beginTransmission(0x52);
Wire.requestFrom(0x52, 6); 	        // request data from controller
for (cnt = 0; cnt < 6; cnt++) {
    if (Wire.available()) {
        ctrlr_type[cnt] = Wire.read(); // Should be 0x0000 A420 0101 for Classic Controller, 0x0000 A420 0000 for nunchuck
    }
}
Wire.endTransmission();
delay(1);
            
// send the crypto key (zeros), in 3 blocks of 6, 6 & 4.
Wire.beginTransmission(0x52);
Wire.write(0xF0);		        // crypto key command register
Wire.write(0xAA);		        // sends crypto enable notice
Wire.endTransmission();
delay(1);
Wire.beginTransmission(0x52);
Wire.write(0x40);		        // crypto key data address
for (cnt = 0; cnt < 6; cnt++) {
    Wire.write(0x00);		        // sends 1st key block (zeros)
}
Wire.endTransmission();
Wire.beginTransmission(0x52);
Wire.write(0x40);		        // sends memory address
for (cnt = 6; cnt < 12; cnt++) {
    Wire.write(0x00);		        // sends 2nd key block (zeros)
}
Wire.endTransmission();
Wire.beginTransmission(0x52);
Wire.write(0x40);		        // sends memory address
for (cnt = 12; cnt < 16; cnt++) {
    Wire.write(0x00);		        // sends 3rd key block (zeros)
}
Wire.endTransmission();
delay(1);
// end device init 
}

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

// Receive data back from the nunchuck, 
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.read());
      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
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++;
}

// 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;
}
        ctrlr_type[cnt] = Wire.read(); // Should be 0x0000 A420 0101 for Classic Controller, 0x0000 A420 0000 for nunchuck

Better change that to:

        nunchuck_buf[cnt] = Wire.read(); // Should be 0x0000 A420 0101 for Classic Controller, 0x0000 A420 0000 for nunchuck
Wire.beginTransmission(0x52);
Wire.requestFrom(0x52, 6); 	        // request data from controller
for (cnt = 0; cnt < 6; cnt++) {
    if (Wire.available()) {
        nunchuck_buf[cnt] = Wire.read(); // Should be 0x0000 A420 0101 for Classic Controller, 0x0000 A420 0000 for nunchuck
    }
}
Wire.endTransmission();

You don’t put beginTransmission() and endTransmission() around a requestFrom call. Just omit those two lines.

http://www.gammon.com.au/i2c

Thanks for the quick answer!

I changed the code according to your advice, now it is compiled and i can upload it. But the serial monitor does not show anything, the led on the arduino is not blinking, too...

Why would the LED blink?

I made a small nunchuk library here:

Is this a "standard" Wii nunchuk you have? If so the library should work with it.

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

What's all this stuff? Can't we just use pinMode instead? And how have you wired the nunchuk up?

Hey,
thank you for your library. I have the feeling that I lack of some basic understanding regarding the code. I downloaded your Nunchuck.zip directory, unzipped and tried to compile the "Demo" pde, which was interrupted by the error message

Demo.pde:-1: error: 'Nunchuk' has not been declared

, although all the files are put together into one directory and the "Nunchuck.h" header file is visible as tab in the IDE.

I found another .zip file with codes to control the nunchuck, changed the code according to the mentioned thread http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1264805255, and made it work, as far as I could compile and upload it, but again i receive no feedback through the serial monitor (at the correct baud rate).

I then tried my luck with the codes at Aruino playground Arduino Playground - HomePage, within the code there is a comment mentioning that it should work for cheap ebay-controllers like mine. I failed to make a header-file out of the given code, I have no idea how to save it as an .h file, whatever I try, it still is an .ino . The Arduino tutorial about librarys explaines what they are, but not how to create them.

The Nunchuck is wired to analog pin 4 & 5 with the green (data) and the yellow (clock) wire. White goes to ground, red to 5V. I double checked the colour configuration with the pins inside the plug and a multimeter.

I saw the led on the board blinking during my other projects, every time the loop was completed and data was sent via serial, so I missed it.

Thank you for your help,
Jannai

The Nunchuk library should be installed in the standard way. Unzip the file and put the resulting folder “Nunchuk” into the libraries folder where your sketches are (the Sketchbook location directory).

Then restart the IDE so it notices the library.

The Nunchuck is wired to analog pin 4 & 5 with the green (data) and the yellow (clock) wire. White goes to ground, red to 5V. I double checked the colour configuration with the pins inside the plug and a multimeter.

Umm, Nunchuck is a 3.3V device.

Ok, I have done so and i can compile and upload your sketch. And again nothing happens, the serial monitor stays blanc (at any baud rate). Is it possible to find out if the nunchuk is the problem, without having a wii? The serial communication works fine with other sensors i use, even with a huge led matrix, so it should not be the arduino's fault.

Oh, I read in various posts that they connected it to 5V and had god results, so I did the same. Is it possible that i fried my device because of 1.7V high voltage?

I've seen people use 5v without damage, and I've even seen it recommended (although I don't advise it). Most likely your nunchuk isn't burned out, but from now on, always use 3.3 volts.

Most 3rd party nunchuks need "special" drivers to make them work.

I bought a generic nunchuk on eBay, and I got it to work using the following (note that the ADDRESS is 0xA4, but the wire library requires that you right shift the address by 1 bit, so on the arduino the ADDRESS should be 0x52):

Write ADDRESS, 0xF0, 0x55
Write ADDRESS, 0xFB, 0x00
Now it should be initialized, so you can read it.
Write ADDRESS, 0x00
Read 6 bytes from ADDRESS

I've tested it to work with the generic nunchuk, as well as a Nintendo brand nunchuk. Please don't ask for ready made Arduino functions, because I don't know if I have them.

First thing I would do in your shoes is see if it responds to the I2C address. Run the I2C scanner on this page:

http://www.gammon.com.au/i2c

Hey, thaks again for your answers.

As i invested already a lot of time to solve this problem I feel a little disappointed, so I simply bought an original Nintendo Wii nunchuck. If someone finds the ultimate solution I am very interested in it, but for now I think this solution is more suitable according to my programming skills.
In fact its a lesson in "don't buy too cheap". Now I paid 16€ altogether, instead of simply investing 10€ into an original, proven device.

Thank you for your help, from my side this thread is closed.