If you want a wii library then there are many out there so its a question of what you prefer.

What i would like is that i just plug something in to the I2C port and the wii library software should take care of the rest. So be it a classic controller , nunchuck, guitar hero guitar or drum kit or indeed a wii motion plus with one of these connected the wii library should work. The wii library should have a init function which can use the power by PIN port as used by tod but also be powered from the 3.3v supply freeing up these ports. It should then have an update function which simply places the values in appropriate variables. The user can then decide what to do it them ie print or just read. I have not found this to exist so if i have some time maybe i will attempt this in a new wii library.

Before making a wii library i wanted to be sure that all the bits and pieces work. This was done using a piece of processing code to visualize the equipment. Below you can see what i mean with the representation of the classic controller and of the standard nunchuck. When you press a button  the corresponding button blinks red or if you move one of the joysticks the yellow dot moves accordingly. The nunchuck buttons make the display colour blue and say on instead of off.

The values are also displayed below the corresponding joystick. Click on either picture below to view video of the wii library program in action.
wiilibrarynunchuckwiilibraryvisualisation

I had some initial problems getting the processing program to work due to a warning message about different RXTX components being used. I solved this as follows:
goto http://rxtx.qbang.org/wiki/index.php/Download
and download rxtx-2.1-7-bins-r2.zip from “Binary” column.
goto C:UsersDownloadsrxtx-2.1-7-bins-r2.ziprxtx-2.1-7-bins-r2
and copy RXTXcomm.jar to
C:Program Filesprocessing-1.5.1javalibext
goto C:UsersDownloadsrxtx-2.1-7-bins-r2.ziprxtx-2.1-7-bins-r2Windowsi368-mingw32
and copy both rxtxParallel.dll and rxtxSerial.dll to
C:Program Filesprocessing-1.5.1javabin

Once this was working it was easy to create the visualizations for each of the Wii components using the wii library. Here you can find the example for the classic controller as shown in the picture.
You need to set the right COM port in the program and open it in processing not arduino IDE.

[spoiler]

/*
* MiconoWiiClassicPrint
* for Wii Classic controller with WiiChunck
*
* 2009/10/04 Micono Utilities (http://micono.cocolog-nifty.com)
*
*/
// Adopt the serial library
import processing.serial.*;
// Prepare the instance for the serial
Serial myPort;
// Prepare for variable font
PFont font;
// Prepare variables for background image
PImage classicControllerPicture;
// Prepare variables for the Wii classic controller
int leftShoulder=0;
int rightShoulder=0;
int leftZ=0;
int rightZ=0;
int leftBtn=0;
int rightBtn=0;
int upBtn=0;
int downBtn=0;
int xBtn=0;
int yBtn=0;
int aBtn=0;
int bBtn=0;
int leftStickX=0;
int leftStickY=0;
int rightStickX=0;
int rightStickY=0;
int selectBtn=0;
int homeBtn=0;
int startBtn=0;

// Location information
int shoulderBtnTop=22;
int centerBtnTop=140;
int StickWH=96;
int leftStickPosLeft=177;
int rightStickPosLeft=324;
int StickPosTop=174;

void setup(){
// Size of screen
size(600,350);
// Load the font
font = loadFont("Osaka-Mono-12.vlw");
// Start using font size: 12
textFont(font, 12);
// Load the background image
classicControllerPicture = loadImage("Wii-classic-controller new.png");
// Set the serial port
myPort=new Serial(this,"COM8",19200);
myPort.clear();
// to invoke () serialEvent
myPort.bufferUntil(10);
}

void draw(){

// Background
image(classicControllerPicture, 0, 0);//background(240);
// On / off button
OnOffFill(leftShoulder,124,shoulderBtnTop);
OnOffFill(leftZ,233,shoulderBtnTop);
OnOffFill(rightZ,366,shoulderBtnTop);
OnOffFill(rightShoulder,475,shoulderBtnTop);

OnOffFill(leftBtn,100,140);
OnOffFill(rightBtn,160,140);
OnOffFill(upBtn,130,110);
OnOffFill(downBtn,130,170);

OnOffFill(yBtn,416,143);
OnOffFill(aBtn,523,143);
OnOffFill(xBtn,470,105);
OnOffFill(bBtn,470,180);

OnOffFill(selectBtn,260,centerBtnTop);
OnOffFill(homeBtn,300,centerBtnTop);
OnOffFill(startBtn,340,centerBtnTop);

// Display the value of the stick
fill(0,0,0);
text("X:",leftStickPosLeft+20,300); text(leftStickX,leftStickPosLeft+40,300);
text("Y:",leftStickPosLeft+20,315); text(leftStickY,leftStickPosLeft+40,315);
fill(230);//noFill();
ellipse(leftStickPosLeft+48,StickPosTop+48,96,96);
fill(255,255,0);
ellipse(leftStickPosLeft+leftStickX*3,StickPosTop+StickWH-leftStickY*3,32,32);

fill(0,0,0); //black
text("X:",rightStickPosLeft+20,300); text(rightStickX,rightStickPosLeft+40,300);
text("Y:",rightStickPosLeft+20,315); text(rightStickY,rightStickPosLeft+40,315);
fill(230);//noFill();
ellipse(rightStickPosLeft+48,StickPosTop+48,96,96);
fill(255,255,0);
ellipse(rightStickPosLeft+rightStickX*3,StickPosTop+StickWH-rightStickY*3,32,32);
}

// Highlight when the button is pressed
void OnOffFill(int onoff, int l, int t)
{
if(onoff==1) {
fill(255,116,142);
ellipse(l,t,20,20);
}
}

// Serial communication processing
void serialEvent(Serial p){
// The data has been sent from the Arduino
// Prepare a string variable stringData,
// "10" until it is read (line feed)
String stringData=myPort.readStringUntil(10);

// When the data string is not empty
if(stringData!=null){
// Get rid of the newline character that is included in the data string
stringData=trim(stringData);
// Prepare an array of integer type data [],
// Separated by a comma symbol string data based on
// Keep the data to an integer array to []
int data[]=int(split(stringData,','));
// Data in the data array [] If the nineteen
if(data.length==19){
leftShoulder=data[0];
rightShoulder=data[1];
leftZ=data[2];
rightZ=data[3];
leftBtn=data[4];
rightBtn=data[5];
upBtn=data[6];
downBtn=data[7];
xBtn=data[8];
yBtn=data[9];
aBtn=data[10];
bBtn=data[11];
leftStickX=data[12];
leftStickY=data[13];
rightStickX=data[14];
rightStickY=data[15];
selectBtn=data[16];
homeBtn=data[17];
startBtn=data[18];
}
}
}

[/spoiler]

wii library software

Here you can find all the appropriate files that i have. The processing files include the pde file for processing and also a font file and the picture of the device.

controller                         funcs.h                             arduino                           processing
nunchuck                         WiiNunchuck.h             WiiNunchuck.ino        WiiNunchuck.zip
classic                                WiiClassic.h                   WiiClassic.ino               WiiClassic.zip
guitar                                 WiiGuitar.h
drum
wiimotionplus.

To better be able to see what is happening i use processing to visualize the data.
The two programs i use are
http://micono.cocolog-nifty.com/blog/2009/09/wiichuck-71aa.html
http://micono.cocolog-nifty.com/blog/wiiremote/index.html
http://micono.cocolog-nifty.com/blog/2009/09/wiichuck-d1cf.html

Software I2C from tod gives ability to have two sensors at the same time eg wii motion plus and a nunchuck without losing any bits. Normally you lose some accuracy due to the bit mapping having to change see below.

Other ideas that i have implemented.
1) Use a kalman filter to give 3D accurate orientation using a gyro and an accelerometer from the wiimotionplus and nunchuck
2) Passthrough mode gives option to have one connection with two devices connected.
3) Use glovepie to operate the computer with wiimote. This gives the option for a remote control for the PC but also cool applications such as smoothboard or headtracking by johnny lee.
4) You can also pretend that the arduino is a nunchuck, classic, guitar or drum controller.
This is the opposite of a wii library because rather than a wii library which converts codes into understandable text here it works the other way round.

If you are looking for other arduino projects look here.

Below you can find the mapping of all the devices i have tested.

Nunchuck

wiilibnunchuck

SX,SY are the Analog Stick X and Y positions, while AX, AY, and AZ are the 10-bit accelerometer data .

The values returned by the analog stick in the nunchuk enclosure do not encompass the full possible range, but rather have upper and lower bounds. These bounds seem to be in the same range across Nunchuks, but there is some variation. Analog stick X returns data from around 35 (fully left) to 228(fully right), while analog stick Y returns from around 27 to 220. Center for both is around 128.

The accelerometer data uses the full range of 0-1024. However, the full range is only seen when moving or rotating the Nunchuk sharply. To measure still Nunchuk rotation in space, the following approximate bounds apply: X goes from around 300 (fully tilted left) to 740 (tilted right), turning further starts bringing the value closer to 512 (neutral position). Similarly, Y goes from around 280 (tilted backwards) to 720 (forwards). Z goes from 320 (upside-down) to 760 (right-side up). BC and BZ are the state of the C and Z buttons (0=pressed). Nintendo games calibrate the center position of the Analog Stick upon power-up or insertion of the Nunchuk.

Classic

wiilibclassic

LX,LY are the left Analog Stick X and Y (0-63), RX and RY are the right Analog Stick X and Y (0-31), and LT and RT are the Left and Right Triggers (0-31). The left Analog Stick has twice the precision of the other analog values.
BD{L,R,U,D} are the D-Pad direction buttons. B{ZR,ZL,A,B,X,Y,+,H,-} are the discrete buttons. B{LT,RT} are the digital button click of LT and RT. All buttons are 0 when pressed.
Nintendo games calibrate the center position of the Analog Sticks upon power-up or insertion of the Classic Controller.

Guitar Hero Guitar

wiilibguitar

SX,SY are the Analog Stick X and Y positions. BG,BR,BY,BB,BO are the fret buttons by color (Green, Red, Yellow, Blue, Orange). B-,B+ are the + and – buttons at the base of the controller, on the GHWT Guitars the B- is the StarPower button. BU and BD are up and down on the strum bar, respectively. WB is the analog whammy bar. Bits marked GH3 seem to be 1 on GH3 Gibson Les Paul Guitars and 0 on GHWT Guitars.
TB is the analog touchbar found on the neck of the Guitar Hero World Tour Guitars, which does not exist on Guitar Hero 3 Guitars.
Not touching it – 0F 1st (top) fret – 04 1st AND 2nd – 07 2nd – 0A 2nd AND 3rd – 0C/0D (keeps changing) 3rd – 12/13 3rd AND 4th – 14/15 4th – 17/18 4th and 5th – 1A 5th (bottom) – 1F You can hold two (touchbar) frets at once, as long as those two (touchbar) frets are adjacent, otherwise it will take the value of the lowest fret held (Eg, if you hold the highest and lowest fret, it reads 1F) Note that high/low means physically on the guitar neck (in musical terms I think it’s the other way around, so I thought I’d better specify)

Guitar Hero Drum

wiilibdrum

R, B, and G are the drum pads by colour (Red, Blue, and Green). O and Y are the cymbals. Bass is the pedal. B- and B+ are the black – and + buttons behind the Wii Remote. They will be 0 when hit, 1 when not.
SX and SY are the black analog stick behind the Wii Remote. 0x20 means centered.
None will be 0 if there is velocity data, and 1 if there is none. If there is none, bytes 2 and 3 will be FF FF and contain no data, and all the ??s will be 1.
If there is velocity data, then “Which” tells you which pad it is for:
Pedal = 11011 = 27 dec, 0x1B Red = 11001 = 25 dec, 0x19 Yellow = 10001 = 17 dec, 0x11 Blue = 01111 = 15 dec, 0x0F Orange = 01110 = 14 dec, 0x0E Green = 10010 = 18 dec, 0x12 “Softness” is how hard or soft you hit the pad. It ranges from 0 = Very hard to 6 = very soft, with 7 = not hit at all
“HHP” is 0 if the velocity data is for the hi-hat pedal (unmarked 3.5mm jack above bass pedal jack), and 1 otherwise. When hi-hat pedal data is sent, “Which” is set as it is for the bass drum pedal (ie 11011). The velocity varies according to how far the pedal is pressed. The pedal to connect to the jack is not the same as the bass drum pedal; it must be a some sort of variable resistor (varying between 20k Ohms when down and 40 Ohms when up seems to give a good spread of velocity values from 0 to 7). The messages are not always sent and are delayed by around 35ms (probably due to the home-made pedal I’m using working wrong).
“0110” is 0110 if there is velocity information, or 1111 if there is not. Its meaning is unknown.
The data in the “??” bits is also unknown, although they are always 1 if there is no velocity data.

WiiMotionPlus

wiilibwmplus

While the Wiimote is still, the values will be about 0x1F7F (8,063), although it is best to calibrate for a few seconds every time you start, to get the actual zero values.
Voltage reference is 1.35V that you can assume it as 8192 unit (half of the ADC range), using 2.27 mV/deg/s, 8192 is 595 deg/s (1.35V/2.27mV), you must divide by ~13.768 unit/deg/s (8192/595) to know the correct deg/s.
At high speed (slow bit = 0) raw values read are small with the same deg/s to reach higher values on top, so you must multiply it by 2000/440 (they are the max reference in the two modes in deg/s [1]). Example: reading 8083 raw value and assuming 8063 as zero, 20 unit in slow/normal mode are 1,45 deg/s and in fast mode are 1.45*2000/440=6.59 deg/s.
Yaw/Roll/Pitch fast/slow bits are 1 when the Wii Remote is rotating slowly (or not rotating at all), 0 when the Wii Remote is rotating fast.
Extension connected is 1 when an extension is connected to the MotionPlus extension port.
Note: The definition of yaw, pitch, and roll, are slightly different for the gyros and accelerometers. Accelerometers measure angles relative to gravity. Gyros measure angles relative to the Wii Remote. If the Wii Remote is up the right way, then they are the same. But if the Wii Remote is on its side, then what the gyros call “pitch” is actually what the accelerometers would call “yaw”.
The correct way to measure orientation is to maintain a rotation matrix (or alternatively a quaternion) of the current orientation (relative to gravity), and update it each time you get a gyro reading. It will drift a little, so you should reset the matrix’s pitch and roll (but not yaw) with the values from the accelerometers whenever the accelerometers and gyros indicate no movement. After significant rotation, you should reset the matrix’s yaw to zero when the Wii Remote is pointing near the middle (horizontally) of the sensor bar.

Nunchuck in passthrough mode with WiiMotionPlus

wiilibwmplusnunchuck

Note that AZ, BC and BZ and the least significant bits of AX, AY and AZ are moved. Also, the least significant bit of each accelerometer axis are lost, consider them 0 to keep 10 bit values. Extension connected is usually 1.
Bit 1 of Byte 5 is used to determine which type of report is received : it is 1 when it contains MotionPlus Data and 0 when it contains extension data.

Classic controller in passthrough mode with WiiMotionPlus

wiilibwmplusclassic

Note that BDL and BDU are moved, and each axis of the left joystick loses its least significant bit.
Extension connected is usually 1.
Bit 1 of Byte 5 is used to determine which type of report is received : it is 1 when it contains MotionPlus Data and 0 when it contains extension data.

Finally here are some links that also cover some aspects of a wii library and connecting it to the arduino

Motion Plus – exposed
MotionPlus – CWiid
Wii motion plus and Arduino « Robotics / Electronics / Physical Computing
The WiiMote and FEZ Domino « Robotics – Electronics – Physical Computing
A Library for Using the Wii Nunchuk In Arduino Sketches | t-square
WiiMote
Wii IR camera as standalone sensor | Let’s Make Robots!
WiiCamera Arduino – Rocket Brand Studios
NUNCHUK拆解与分析–阿龙的笔记
moyuchin/WiiRemote_on_Arduino · GitHub
Arduino Forum – Read wireless Wii Nunchuck with Arduino
WiiNunchuck.cpp – camwiichuck – wiichuck – Google Project Hosting
Tree for arduino-wiimote in Random Stuff – Gitorious
/Source/Plugins/Plugin_WiimoteNew/Src/WiimoteEmu/Attachment/ – dolphin-emu – Dolphin, a Gamecube / Wii / Triforce Emulator – Google Project Hosting
http://micono.cocolog-nifty.com/blog/wiiremote/index.html

Leave a Comment