Read wii nunchuck data into arduino
With a little hacking, data can be read from a wii nunchuck directly into an Arduino, using TWI (aka I2C). The nunchuck contains a 3 axis accelerometer, joystick and buttons for only $19.95. The same accelerometer in kit form, cost $34.95 at Sparkfun. Plus the nunchuck is already wired up in a nice clean case! So the wii nunchuck should fit nicely into anyones robotic project.

The nunchuck uses a proprietary connector. I just cut the end off of my nunchuck cable. The cable has 4 wires.
white - ground
red - 3.3+v
green - data
yellow - clock
Attach white to the Arduino's ground, red to 5 volt+, green to analog pin 4, yellow to analog pin 5. The nunchuck is only supposed to get 3.3+ volts. So far it has worked fine at 5 volts, but be warned. I am guessing that using the higher voltage will shorten the nunchucks lifespan.
My Arduino has an Atmel atmega168 chip. The atmega168 can read the TWI protocol. The "Wire" library is bundled with the Arduino IDE and contains a number of libraries that will be used for reading the TWI protocol. A few small changes have to be made to the default wire library. The Arduino's twi.h header needs two changes. Look in lib/targets/libraries/Wire/utility. Then delete twi.o. Open up twi.h. Uncomment line:
// #define ATMEGA8.
Since the nunchuck uses "Fast" I2C, we will need to change the default speed:
#define TWI_FREQ 400000L.
For the Arduino to communicate with the nunchuck, it must send a handshake. So first send 2 bytes "0x40,0x00". Then send one byte "0x00" each time you request data from the nunchuck. The data from the nunchuck will come back in 6 byte chunks.
| Byte | Description | Values of sample Nunchuk |
| 1 | X-axis value of the analog stick | Min(Full Left):0x1E / Medium(Center):0x7E / Max(Full Right):0xE1 |
| 2 | Y-axis value of the analog stick | Min(Full Down):0x1D / Medium(Center):0x7B / Max(Full Right):0xDF |
| 3 | X-axis acceleration value | Min(at 1G):0x48 / Medium(at 1G):0x7D / Max(at 1G):0xB0 |
| 4 | Y-axis acceleration value | Min(at 1G):0x46 / Medium(at 1G):0x7A / Max(at 1G):0xAF |
| 5 | Z-axis acceleration value | Min(at 1G):0x4A / Medium(at 1G):0x7E / Max(at 1G):0xB1 |
| 6 | Button state (Bits 0/1) / acceleration LSB | Bit 0: "Z"-Button (0 = pressed, 1 = released) / Bit 1: "C" button (0 = pressed, 1 = released) / Bits 2-3: X acceleration LSB / Bits 4-5: Y acceleration LSB / Bits 6-7: Z acceleration LSB |
Here is a simple program to read data from the nunchuck. It will read in data from the nunchuck then send it out over the Arduino's serial connection to your PC. On the PC, I just read it in with minicom, but you can use your favorite serial terminal program. The Arduino can't keep up with reading both serial and TWI at the same time. I have the Arduino read in about 50 bytes from the nunchuck then print that back to the PC over the serial connection. This means there will be a slight delay. Also you may see some strange characters every now and then. I think that is because of the serial connection interfering with the TWI connection.
Update: I updated the code some to slow down the serial data transmit and TWI requests. That seems to have fixed the bad data I was seeing.
If you are able to reproduce this hack, please drop me an email at chad AT chadphillips . org
#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;
}
Update I just tried running my code under Arduino 10. I had to make a different change to twi.h. Here are the first few lines of twi.h
#define ATMEGA8
#ifndef CPU_FREQ^M
#define CPU_FREQ 16000000L
#endif
#ifndef TWI_FREQ^M
#define TWI_FREQ 100000L
#endif
Comments
Anonymous:
thanks for sharing.
Buy Essay | Buy Thesis | Custom Term Paper
luca:
Hi all. My problem is apparently like jeff one. When i have nunchuck disconnected, all goes right, and arduino just prints all empty values (584 joy:0,0 acc:0,0,0 but:0,0
). When i connect the controller, it just stops transmitting, therefore it doesn't blinks ttx led, nor prints on the serial port monitor.
I'm still new to electronics, so can't modify the system by myself.
Maybe someone got any idea about it?
Johhnyonthespot:
It is best to post the code you are using; keep in mind that the nunchuck must be connected in time to receive the initalization message of the code. I ran into this problem a lot when I was interfacing 2 nunchucks to 1 arduino, where one nunchuck's data would output correctly, and the other one was at default values.
post that code, i'd be more than happy to take a look.
Anonymous:
ovvvvv all right :)
ovvvvv all right :)
ovvvvv all right :)
film indir film indir film izle
film izle
SpooExi
dizi izle
mp3 indir
sex porno izle
Leaning Tower:
Hi, thanks for this great page!
I've got it working and I ran into something that might be useful to others. The x, y, z values from the accelerometer are not centered at 512, as you might assume. Mine are centered around 600. That is, if I hold the nunchuk level, the z reading indicating "0 G" is about 600, and the min/max readings for a steady position are around 340/850. If you assume that 512 is the "middle" of the 1024 range, it will seem like your readings are tilted a bit forward and to the right all of the time.
Consulting the chip's data sheet (ST LIS3L02AL), it looks like this could be caused by running it at 5V instead of 3.3V. It doesn't seem to do any harm, but you might get different readings at different supply voltages.
Hope that's helpful to someone!
ukraine:
mm.. very good
Anonymous:
dasfsdfsdf qwerty sdsdfsdfsdf
BrandonToner:
Does anyone know how to get the calibration data from the nunchuck?
uphiearl:
I got the program to work under 016 no problem. Now to modify it to read the Wii motion plus data. It is a 3 axis gyro. I have done it on a Parallax Propeller micro no problem.
A 6DOF for under $35 with GREAT resolution!
I have this i2c combo reading fine with prop.
I think this could be a good replacement for the ArduPilot IR sensors that are very expensive. > $115.
Earl
raising kids:
I'm not sure but that would be very cool if you could. What about the new bowling ball controller they have out now. Anyway to get that data?
uphiearl:
You mean the motion plus ? Yes I have interfaced it also. It is a 3 axis gyro !
Same deal, data in 6 memory locations, hi bits then lo bits. 14 bit resolution! I found the lower 2 bits to be to senitive so I just mask them off.
Earl
Darron Angelocci:
Hello Guru, what entice you to post an article. This article was extremely interesting, especially since I was searching for thoughts on this subject last Thursday.
stress management techniques
jeux pour gagner des cadeaux
Jinseok:
I had a problem with this program with Arduino 0015. But I downloaded the new version 0016 from their homepage and now it works.
Thank you for sharing this great library.
andrew:
woo i got it to work i had got the clock and signal the wrong waty round first time and then i got all the cionnections wrong on the wiichuck wrong but then i got it write and it all works =]
psi:
What is pin 3 for on the Wiimote expansion port?
Johnson:
I am trying to connect a nunchuck to AtMega168. The nunchuck responds with ACK when I start Master Transmit or Master Receive mode with 0x52, but when I try to send data (for example, 0x40) it won't respond ACK. (The 9th bit of data goes high, I checked with an oscilloscope.) I have tried with 100kHz, 200kHz and 400kHz, but it doesn't make any difference.
When I try to read from the nunchuck I get only FFs (nothing).
Any ideas how to continue?
Chris:
I am facing exactly the same problem. Did you find a solution?
johnnyonthespot:
Lets see your code
mactitan:
Hello, Thank you to all the Guys who contributed towards the super Wii Nunchack project.
I would like to know if anyone has worked on code to log a Date Time Stamp from the DS1307 together with the Nunchuck data? I just can't get my code to work with both I2C devices. All help very welcome.
Dave:
Awesome work folks. I'll be trying something similar over the next few days. Lots of good info in the comments. Thanks.
johnnyonthespot:
I got it to work:
Here is a website to the code and circuit:
http://www.wiimoteproject.com/tech-chat/2-nunchuck-with-arduino-help/
I couldn't of done it without help from this site
:0)
bd
jordi:
THIS CODE IS FOR PICBASIC PRO COMPILER, THE CODE PRINT THE BYTES ON LCD.
'****************************************************************
'* Name : UNTITLED.BAS *
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2009 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 09/01/2009 *
'* Version : 1.0 *
'* Notes : read nunchuk, pic16f876, i2c=400kb *
'* : CLOCK: 20Mhz *
'****************************************************************
include "modedefs.bas"
DEFINE OSC 20
DEFINE I2C_HOLD 1
ADCON1=%00000110
trisa=%000000
trisb=%00000000
trisc=%00011110
porta=%000000
portb=%00000000
portc=%00000000
DEFINE LCD_DREG PORTA 'lcd pins
DEFINE LCD_DBIT 0
DEFINE LCD_RSREG PORTB
DEFINE LCD_RSBIT 7
DEFINE LCD_EREG PORTB
DEFINE LCD_EBIT 5
SDA VAR PORTB.1
SCL VAR PORTB.2
a1 var byte
a2 var byte
a3 var byte
a4 var byte
a5 var byte
a6 var byte
b1 var byte
b2 var byte
b3 var byte
b4 var byte
b5 var byte
b6 var byte
LCDOUT $fe, 1
lcdout "prova i2c = "
pause 2000
XX: 'read nunchuk
i2cwrite sda,scl,$A4,$40,[$00]
pause 10
i2cwrite sda,scl,$A4,[0]
pause 10
i2cread sda,scl,$A5,[a1,a2,a3,a4,a5,a6]
pause 10
a1=(a1 ^ $17)+ $17 'decoder
a2=(a2 ^ $17)+ $17
a3=(a3 ^ $17)+ $17
a4=(a4 ^ $17)+ $17
a5=(a5 ^ $17)+ $17
a6=(a6 ^ $17)+ $17
if (a1<>b1)or(a2<>b2)or(a3<>b3)or(a4<>b4)or(a5<>b5)or(a6<>b6)then
LCDOUT $fe, 1
lcdout "d: ",#a1," ",#a2," ",#a3,$FE,$C0,#a4," ",#a5," ",bin a6
b1=a1
b2=a2
b3=a3
b4=a4
b5=a5
b6=a6
endif
pause 200
goto XX
END
speed301:
Why do you use the $A5 address when you read the i2c data? I understand $A4 is necessary for 8 bit addressing but the www.wiili.org article does not mention a $A5 address.
chad:
awesome! Thanks for posting the code. What are you building with it?
Jeroen:
hello
I have read all the comments on this page but I can't get my nunchuck to work, the only thing dat comes out of the nunchuck is 255. I have put delays in my sequence, I use a 18F8723@20MHz PIC with microchip C18 compiler. The I2C bus works because I can read my I2C compass.
CODE
void Init_nunchuck(void){
Delay1KTCYx(100); //20ms Delay
i2c_start();
i2c_write(0xA4);
i2c_write(0x40);
i2c_write(0x00);
i2c_stop();
DLCD5MS; //5MS delay
i2c_start();
i2c_write(0xA4);
i2c_write(0x00);
i2c_stop();
Delay10TCYx(100); //200uS
i2c_start();
i2c_write(0xA5);
nunchuck[0]=i2c_read();
i2c_ack();
nunchuck[1]=i2c_read();
i2c_ack();
nunchuck[2]=i2c_read();
i2c_ack();
nunchuck[3]=i2c_read();
i2c_ack();
nunchuck[4]=i2c_read();
i2c_ack();
nunchuck[5]=i2c_read();
i2c_nack();
i2c_stop();
}
What Can I do to help the problem
NYX:
Hi! I got this hack to work as a charm, but I'm having trouble using the information in Processing. Anyone out there good at this? I really would need some general help, and maybe som basic examples! Thanx /NYX
Stuart Mcfarlan:
Hey;
Thank you chad for the great code to get a nunchuck connected to an Arduino. I've been having great fun with it. I have written up an Instructable about using a nunchuck to control a robot with an Arduino brain, and have used your code pretty much unchanged (many notes pointing people back here included) hope that's okay.
If you'd like to take a look;
http://www.instructables.com/id/How_to_Control_Your_Robot_Using_a_Wii_Nunchuck_an/
Thanks once more;
Stuart McFarlan
oomlout.com
Anonymous:
Hi, im trying to write an application that will use a wireless nunchuck. The nunchuck works fine with the wii but when i try and interface it with the code provided above, it will only display "Finished Setup" and one line of data in the serial program i am using and i have no idea why it stops. And i know its not a problem with the way i have implemented the code or the hardware because i have tried it with a normal nunchuck.
Michael Dreher:
Hi,
I found the solution for the wireless Nunchucks on the following page, thanks a lot guys! :
<http://wiibrew.org/wiki/Wiimote#The_New_Way>
I only have a wireless Nunchuck from Blazepro, therefore I couldn't test it with any other controller.
First the overview:
1. The initialization sequence must be changed and because it takes some time before the controller is connected via the wireless connection it has to be done in a loop until it works
2. The decryption (^ 0x17 + 0x17) is then no longer needed
3. Send_zero () has to be called 3 times in a row
4. The TWI freq must be set to 400000
5. The controller type can be read to verify that you really have an Nunchuck
6. When an error occours, the controller must be reinitialized (I haven´'t done that, yet)
Now the details:
1. The initialization sequence must be changed and because it takes some time before the controller is connected via the wireless connection it has to be done in a loop until it works:
// 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;
// disable encryption
// look at <http://wiibrew.org/wiki/Wiimote#The_New_Way> 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)));
return rc;
}
2. The decryption (^ 0x17 + 0x17) is then no longer needed:
// no decoding needed with new init sequence
char nunchuk_decode_byte (char x)
{
return x;
}
3. send_zero () has to be called 3 times in a row:
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
}
}
4. The TWI freq must be set to 400000:
The easiest way to do this without modifying the installed Arduino files is the following lines after 'Wire.begin()' in 'setup()':
#define TWI_FREQ_NUNCHUCK 400000L
TWBR = ((CPU_FREQ / TWI_FREQ_NUNCHUCK) - 16) / 2;
5. The controller type can be read to verify that you really have an Nunchuck:
Look at the function 'readControllerIdent()' in the code below.
The whole code put together:
// read out a Wii Nunchuck controller
// adapted to work with wireless Nunchuck controllers of third party vendors by Michael Dreher
// adapt to your hardware config
#define POWER_VIA_PORT_C2_C3 1 // use port pins port C2 and C3 as power supply of the Nunchuck (direct plug using wiichuck adapter)
//#define DEBUG_RCV_TEL 1
#define USE_NEW_WAY_INIT 1 // use "The New Way" of initialization <http://wiibrew.org/wiki/Wiimote#The_New_Way>
#define WII_IDENT_LEN ((byte)6)
#define WII_TELEGRAM_LEN ((byte)6)
#define WII_NUNCHUCK_TWI_ADR ((byte)0x52)
#include <Wire.h>
#include <string.h>
#include <utility\twi.h>
#undef int
#include <stdio.h>
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 <http://wiibrew.org/wiki/Wiimote#The_Old_Way> 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 <http://wiibrew.org/wiki/Wiimote#The_New_Way> 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;
}
// params:
// ident [out]: pointer to buffer where 6 bytes of identification is stored. Buffer must be at least 6 bytes long.
// A list of possible identifications can be found here: <http://wiibrew.org/wiki/Wiimote#The_New_Way>
// return: 0 == ok, 1 == error
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;
}
Michael
Björn Giesler:
Thanks a lot for this comment -- seems to be the only how-to post for getting a wireless nunchuk working with Arduino! I implemented this for my R2D2 and it works like a charm! Driving around happily with the wireless nunchuk now... Again, thank you very much!
Anonymous:
I have the same problem, but I don't have a regular nunchuk to try with. And sise I dont have a wii i cant test the wireless nunchuck.
I do however get some kind of response, when the arduino is conected the conection lights stopped blinking on the resiver
Any ideas?
Anonymous:
hi, i am also in a similar situation. i bought a wireless nunchuck and at first i couldn't receive any data from it, i adapted the wire library as initially suggested above, twi_frequency = 400000L so i am now able to receive data but i am just getting " 255 255 1023 1023 1023 1 1" as an output regardless of how i maneuver the nunchuck. i was wondering if anyone else had encountered this problem either with a wired or wireless nunchuck and whether anybody could help me solve this issue.
Thanks
Anonymous:
Exactly what is happening to me
Anonymous:
I'm also having problems connecting to a wiireless nunchuck. I'm using a Logic 3 Freebird. there is an additional pin used on the wireless nunchuck, which is raised high when the connect button is pressed. On a wired nunchuck this is tied directly to 3.3V.
I can get data back from the wireless nunchuck, but its garbage, one thing I have found is that the wireless nunchuck will only work from 20000 to 100000 bps.
Bill Rowe:
Thank you for the write-up. just what i needed.
you can drop the arduino's 5v to around 3.5V by sticking an LED between the +5 and the nunchuk. I got this idea from the schematic for the lilypad accelerometer which uses the same chip.
Jeff:
I’m trying to do the same thing but I have a problem. When I connect the Wii Nunchuck to my arduino, it just stop ... I not receive any data from the arduino to the serial port when it connected. When I just disconnect the Nunchuck, the arduino is unblocked and I could receive data.
I just bought a new nunchuck so I’m pretty sure it not broken. Any idea? I’m stuck I can’t go ahead.
I use an Arduino diecimila, an original Nintento Nunchuck and the Wii Nunchuck Adaptor. I also use the lastest arduino software. I’m on Windows 7 pre-beta.
JohnCohn:
Howdy..
Thanks to your excellent work here we were able to get a wiimote numchuck talking to our arduino in about 15 minutes last night.. But we're a bit stuck on how to move forward.. We'd like to read from two different numchucks because we need two sets of joysticks for our application.. We haven't been able to figure otu how we'd interface a second numchuck into this approach. Is it possible to run 2 versions of the i2c interface on a single arduino.. We haven't been able to figure out where the pins are set.. etc. Any help would be much appreciated !!!
-jc
johnnyonthespot:
http://www.wiimoteproject.com/tech-chat/2-nunchuck-with-arduino-help/
chad:
Good question. The arduino only has one I2C interface. You usually get around that by addressing your I2C slave. I don't know if you could do that with the nunchuck though. They may be hard set.
Maybe you could set up some type of transitor that would power off one of the nunchucks at a time. Then you could turn them on/off and only read one at a time.
Not sure if that would work, but might be worth a try.
Tommy:
I have no idea what to do. Your directions are not making any sense. What do i have to change in the wire lib. Please help.
jason:
First of all, thanks for all the great info, Chad!
I've been trying to get this working, but I hooked up the wires all wrong the first time (used the wrong pinout diagram). After fixing it, though, I still can't get any data from the nunchuck: the initialization routine hangs on Wire.endTransmission(...), which apparently indicates that the arduino did not receive a reply / acknowledge?
Do you think my nunchuck is dead? I've tried multiple combinations: all permutations of 5v/3.3v, 400khz vs 100khz, and switching the data and clock lines (since some diagrams on the internet have it the other way around).
Anyway, I'd appreciate any insight. Thanks!
chad:
The nunchuck is pretty tough. I have mis wired mine a few times and it still works. I would bet your nunchuck is ok.
What version of arduino software are you using? What os? Did you do the update to twi.h?
thanks
chad
Mister:
Thanks a lot
Biber hapi
Biber hapi
fx15
Anonymous:
Turns out it was dead: it had a short between clock and ground. I got a new one and it works fine now. I've been running it at 100khz / 3.3v on arduino-0011 (windows xp).
Thanks for the help!
chad:
Glad you got it working. Please post back if you build anything interesting.
Xo W.:
Sources for two popular compilers for the PIC 18F can be found at http://svn.stuytech.com/public/nunchuk_read/
All of the delays are nearly optimized to the bare minimum, so look here if you want to get the timing right. Also, check out the addressing and I2C rates.
Both code samples are targeting the 18F2550, with the config fuses set for a 20MHz crystal. The device will run at 48MHz (12 MIPS). Built hex files are available in Release/nunchuk_read.hex and within nunchuk_read_mcc18.zip.
I haven't licensed the code yet, so for now, please email me at xo HAT geekshavefeelings THE com DOT if you would like to use it.
This is the byproduct of a serious effort for a competition by a high school robotics team. Check out Stuyvesant Techtonics for more information: http://www.stuytech.com/
-Xo W.
Dalek:
Hey, I tried this on an atmega32 using the code above.
The only difference is that the FCU = 4000000.
Hyperterminal displays only
46 46 187 185 184 0 1
even as I move the nunchuck around
Any Ideas?
Bill Rowe:
This mysterious sequence is actually what happens when the arduino runs the decoding sequence on a bunch of 00's. If I don't have anything hooked up I get that sequence.
Dalek:
Ok, I checked the pins and I had the data and clock reversed
but now I get
255 255 1023 1023 1023 1 1
I saw someone else had this problem, but was it ever resolved?
chad:
I get those results if a pin comes loose while the arduino is running. Lets say I am getting correct data, then I get a loose connection to the nunchuck. It then starts giving me the 255s.
I was say make sure you pins are all secure, then reset the arduino.
Post new comment