Loading...

You have no items in your shopping cart.

 
 
 
×

Registration

Profile Informations

Login Datas

or login

First name is required!
Last name is required!
First name is not valid!
Last name is not valid!
This is not an email address!
Email address is required!
This email is already registered!
Password is required!
Enter a valid password!
Please enter 6 or more characters!
Please enter 16 or less characters!
Passwords are not same!
Terms and Conditions are required!
Email or Password is wrong!
Captcha is required!
Captcha is wrong!

Play Arduino With Wii-Nunchuck Remote

The Wii Nunchuk controller is a secondary controller that adds even more innovation to the next generation of gaming. For each wii-numchuck, there are a joystick , 2 buttons and an acceleration sensor in it. Work with the  “Wiichuck- A Wii-Nunchuck break out board / adapter“, you can connect the wii-nunchuck with arduino boards, and it should be a very perfect motion controller for a interactive projects.

Using the code below, the arduino will read the motion information from the wii nunchuck and print out by serial port:

#define POWER_VIA_PORT_C2_C3 1

#define USE_NEW_WAY_INIT 1 
#define WII_IDENT_LEN ((byte)6)
#define WII_TELEGRAM_LEN ((byte)6)
#define WII_NUNCHUCK_TWI_ADR ((byte)0x52)

#include 
#include 
#include 
#undef int
#include 

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

void setup ()
{
Serial.begin (19200);

#ifdef POWER_VIA_PORT_C2_C3 // power supply of the Nunchuck via port C2 and C3
PORTC &=~ _BV(PORTC2);
PORTC |= _BV(PORTC3);
DDRC |= _BV(PORTC2) | _BV(PORTC3); // make outputs
delay(100); // wait for things to stabilize
#endif

Wire.begin(); // initialize i2c
// we need to switch the TWI speed, because the nunchuck uses Fast-TWI
// normally set in hardware\libraries\Wire\utility\twi.c twi_init()
// this is the way of doing it without modifying the original files
#define TWI_FREQ_NUNCHUCK 400000L
TWBR = ((CPU_FREQ / TWI_FREQ_NUNCHUCK) - 16) / 2;

nunchuck_init(0); // send the initialization handshake

// display the identification bytes, must be "00 00 A4 20 00 00" for the Nunchuck
byte i;
if(readControllerIdent(outbuf) == 0)
{
Serial.print("Ident=");
for (i = 0; i < WII_TELEGRAM_LEN; i++)
{
Serial.print(outbuf[i], HEX);
Serial.print(' ');
}
Serial.println();
}

Serial.println("Finished setup");
}

// params:
// timeout: abort when timeout (in ms) expires, 0 for unlimited timeout
// return: 0 == ok, 1 == timeout
byte nunchuck_init (unsigned short timeout)
{
byte rc = 1;

#ifndef USE_NEW_WAY_INIT
// look at  at "The Old Way"
Wire.beginTransmission (WII_NUNCHUCK_TWI_ADR);	// transmit to device 0x52
Wire.send (0x40);	 // sends memory address
Wire.send (0x00);	 // sends sent a zero.
Wire.endTransmission ();	// stop transmitting
#else
// disable encryption
// look at  at "The New Way"

unsigned long time = millis();
do
{
Wire.beginTransmission (WII_NUNCHUCK_TWI_ADR);	// transmit to device 0x52
Wire.send (0xF0);	 // sends memory address
Wire.send (0x55);	 // sends data.
if(Wire.endTransmission() == 0) // stop transmitting
{
Wire.beginTransmission (WII_NUNCHUCK_TWI_ADR);	// transmit to device 0x52
Wire.send (0xFB);	 // sends memory address
Wire.send (0x00);	 // sends sent a zero.
if(Wire.endTransmission () == 0)	// stop transmitting
{
rc = 0;
}
}
}
while (rc != 0 && (!timeout || ((millis() - time) < timeout)));
#endif

return rc;
}



byte readControllerIdent(byte* pIdent)
{
byte rc = 1;

// read identification
Wire.beginTransmission (WII_NUNCHUCK_TWI_ADR);	// transmit to device 0x52
Wire.send (0xFA);	 // sends memory address of ident in controller
if(Wire.endTransmission () == 0)	// stop transmitting
{
byte i;
Wire.requestFrom (WII_NUNCHUCK_TWI_ADR, WII_TELEGRAM_LEN);	// request data from nunchuck
for (i = 0; (i < WII_TELEGRAM_LEN) && Wire.available (); i++)
{
pIdent[i] = Wire.receive();	// receive byte as an integer
}
if(i == WII_TELEGRAM_LEN)
{
rc = 0;
}
}
return rc;
}

void clearTwiInputBuffer(void)
{
// clear the receive buffer from any partial data
while( Wire.available ())
Wire.receive ();
}


void send_zero ()
{
// I don't know why, but it only works correct when doing this exactly 3 times
// otherwise only each 3rd call reads data from the controller (cnt will be 0 the other times)
for(byte i = 0; i < 3; i++)
{
Wire.beginTransmission (WII_NUNCHUCK_TWI_ADR);	// transmit to device 0x52
Wire.send (0x00);	 // sends one byte
Wire.endTransmission ();	// stop transmitting
}
}

void loop ()
{
Wire.requestFrom (WII_NUNCHUCK_TWI_ADR, WII_TELEGRAM_LEN);	// request data from nunchuck

for (cnt = 0; (cnt < WII_TELEGRAM_LEN) && Wire.available (); cnt++)
{
outbuf[cnt] = nunchuk_decode_byte (Wire.receive ());	// receive byte as an integer
digitalWrite (ledPin, HIGH);	// sets the LED on
}

// debugging
#ifdef DEBUG_RCV_TEL
Serial.print("avail=");
Serial.print(Wire.available());
Serial.print(" cnt=");
Serial.println(cnt);
#endif

clearTwiInputBuffer();

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

send_zero (); // send the request for next bytes
delay (20);
}

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

// Decode data format that original Nunchuck uses with old init sequence. This never worked with
// other controllers (e.g. wireless Nunchuck from other vendors)
char nunchuk_decode_byte (char x)
{
#ifndef USE_NEW_WAY_INIT
x = (x ^ 0x17) + 0x17;
#endif
return x;
}