How to Use a Wii Nunchuk with an Arduino

When the Nintendo Wii was released in 2006, there was a lot of talk about their new weird control system. In place of a typical control pad, players would use a one-handed “remote” with infrared sensors and accelerometers in place of a joystick. For those games that required additional controls, players would use an accessory controller in their off-hand.

This ‘accessory’ controller is the Nunchuk. A strange, bean-shaped attachment with a joystick, two buttons, and a three-axis accelerometer. Although the Nunchuk had a lukewarm response when it was first released, it’s the perfect controller for makers who want to add some fine control to their projects.

Although I’m writing this post with Arduino in mind, most of this information also applies to using a Nunchuk with something like a Raspberry Pi or an ARM-based board.

Let’s get started!

Getting Connected

While the Wii remote itself is wireless, the Nunchuk was designed to plug into an accessory port at the bottom of the remote. This is actually better for my purposes, because it means that I can connect the hardware directly to a microcontroller.

To connect to the Nunchuk I purchased a “Nunchuky” breakout board from Adafruit for a cool $3. The Nunchuk’s extension connector snaps right into the board, which exposes the power and data lines so I can connect it to a breadboard. I could have also cut the connectors off and used the bare wires, but there’s something to be said for keeping the controller intact.

From the Nunchuk’s 6-pin connector, these breakout boards expose 4 pins:

  • Gnd: Ground.
  • 3.3V: VCC, can also be +5V.
  • Data: SDA, serial data.
  • Clk: SCL, serial clock line.

Of the remaining two pins, one is not-populated on the connector and one is a power return used for controller detection. Unfortunately the breakout doesn’t expose this return pin, so I’ll have to live without another glowy indicator LED.

Inter-Integrated Wii

As it turns out, the communication protocol used by the Nunchuk is none-other than standard I2C! The data and clock lines from the Nunchuk can be hooked directly to the hardware protocol pins on the microcontroller.

For an Arduino Uno and other 328P-based boards, the connection pins for SDA and SCL are A4 and A5, respectively. For the Arduino Leonardo and other 32U4-based boards, you use pins 2 and 3 for data and clock.

Voltage Levels

According to information I can find online, the Wii remote outputs 3.3V from its extension connector at the bottom of the controller. This is the expected voltage level for the Nunchuk.

This presents a problem for using something like an Arduino Pro Micro, which has no onboard regulator and operates directly from the PC’s +5V via USB. Nevertheless, some information online seems to indicate that the Nunchuk works fine when powered with +5V. So I did what any maker would do with a $5 part and gave it a shot.

It works, but it doesn’t work perfectly. The Nunchuk will respond to commands and outputs data to the board when powered from +5V, which for the most part appears accurate. The only problem occurs when the joystick is maxed out on both the X and Y axis (NE corner). In this position, both axes report ‘center’ values over the bus (127) rather than maxed values (255). I verified this with a logic analyzer to make sure it wasn’t a software fault with my library.

These problems went away when using a +3.3V supply with a 5V -> 3.3V logic level converter. This may or may not be a problem with a ‘genuine’ Nunchuk. YMMV.

As with any electrical component, using a higher voltage level than expected – if it works at all – will usually lower the lifespan of the part. If your Nunchuk does work perfectly with +5V power, beware that it might fail prematurely.

Nunchuk Data

With the Nunchuk connected to the Arduino it’s time to start reading data from the controller!

Thankfully in the last 11 years a lot of smart people have messed around with these Wii extension controllers, so there is plenty of information online about how they work. After fighting with most of the existing libraries out there, I decided to create my own called NintendoExtensionCtrl, which works with the Nunchuk and a few other controllers. You can download it from GitHub or by using the libraries manager in the Arduino IDE.

Initialization

Before it will send any data, the Nunchuk needs to be initialized. The library makes this easy with a connect method, but let’s look at what’s going on under the hood.

The library joins the hardware I2C bus as a master and then writes two bytes to the Nunchuk: ‘0x55’ to register 0xF0, and ‘0x00’ to register 0xFB. According to information I found online, the Nunchuk normally encrypts its output using an XOR transformation. By initializing the device with these two commands, the Nunchuk operates in an “unencrypted communication mode”. This means the data it sends in response to a polling request is plainly formatted and easily parsed.

The connect method for the library also has a function to identify what type of controller was connected, as the Wii remote’s port also supports things like the Wii classic controller and musical controllers for things like Guitar Hero.

Lastly, the method polls the controller for its control data (update()) so the user can start using it right away.

Polling Updates

Because the Nunchuk works over the two-wire I2C bus, updates need to be polled from the device.

To poll for an update, the Arduino first sends ‘0x00’ to the Nunchuk to set the register pointer at the start of the data block. It then requests 6 bytes of data from the Nunchuk. These 6 bytes contain all of the information from the Nunchuk’s controls.

Data Formatting

The data from the Nunchuk comes packaged in a specific way to save bandwidth on the bus. This allows Nintendo to squeeze a little more range out of the accelerometer while keeping the max polling rate the same.

Table from WiiBrew.org

The first two bytes are the joystick X and Y values, respectively. The next three bytes are the most significant bits for the accelerometer values (XYZ). The last byte contains the two least significant bits for all three accelerometer values, as well as single bits for the on/off states of both buttons. These button values are inverted, so a ‘0’ means the button is pressed (don’t worry, this is flipped by the ‘get’ function).

The bit-depth for the controls are as follows:

  • Joystick XY: 8 bit / 0 – 255
  • Accelerometer XYZ:  10 bit / 0 – 1023
  • Buttons C/Z: 1 bit / 0 – 1

In the library, each control is parsed by it ‘get’ method as they are called. This keeps the overhead low for controls that aren’t needed by the user.

Retrieving Data

Using the NintendoExtensionCtrl library, getting data from the Nunchuk is a piece of cake:

Calling updatewill update the microcontroller’s buffer with the latest values from the Nunchuk. Calling each data function will return the transformed version of that respective value, either as an unsigned integer (joystick, accelerometer) or as a boolean (buttons).

Using Multiple Nunchuks

This is all fine-and-dandy for using a single controller, but what if you want to use two or more Nunchuks?

This is possible, but unfortunately it isn’t quite as easy. The system was designed to only use one device per Wii remote, so they aren’t built with scalability in mind. The limitation here is the I2C address.

The I2C bus used by the Nunchuk (and other extension controllers) is addressable. This means that it’s possible to have dozens of devices all communicating on the same bus using just two wires. To talk to a specific device the controller makes a request to that address. This is the problem, as all Wii extension controllers have the same address – 0x52. If you put two controllers on the same bus, they will both try to respond at the same time and you’ll have a conflict.

The solution is to use two I2C buses. Or, if you only have one bus, to use an I2C multiplexer like the TCA9548A. Adafruit sells a nice breakout that works well. I’m currently using this multiplexer to have two Nunchuks work on an Arduino Pro Micro. It also conveniently acts as a level-converter!

Example Project: LED Controller

Now it’s time to put this knowledge to work and make something! My typical go-to is something with RGB LEDs because they are quick to set up, have a lot of parameters, and offer clear visual feedback. As the Nunchuk is a controller, why not set it up to control a few LEDs?

I’m going to set this up as follows:

  • Joystick X: Set number of LEDs (left to right)
  • Joystick Y: Set brightness
  • Accel XYZ: Set RGB values
  • C Button: Flicker on/off
  • Z Button: Turn on / off all

For my LEDs I’m going to use a small strip of WS2812B addressable LEDs, or what Adafruit calls “NeoPixels”. They’re inexpensive and easy to work with if you use a library like FastLED.

Setup

First a few housecleaning things. Import the NintendoExtensionCtrl and FastLED libraries, set a few global variables, and start both libraries in the setup function.

Once we get to the loop, the code clears the LED data and polls the controller for new information. Each control is then handled in-turn.

JoyX: Number of LEDs

The ‘X’ value of the joystick controls how many LEDs are on. The value is divided by a parameter so the max possible value is the maximum number of LEDs in the strip.

This value is stored in a global variable. It’s going to be used to set the loop length when the LED colors are set.

JoyY: Brightness

The ‘Y’ value of the joystick controls the brightness of the LEDs.

The brightness is scaled depending on the ‘min’ and ‘max’ brightness values, set at the top of the code. This is just a quality of life thing – the LEDs can get crazy bright. It also works using the joystick value directly.

Accel XYZ: Color Values

The accelerometer values for X, Y, and Z control the RGB color of the strip.

The accelerometer value is 10 bits (0 – 1023), so it’s divided by 4 to get an 8-bit value that fits in the array. The LEDs are assigned from the start of the strip through the number dictated by the ‘X’ joystick value stored earlier.

Z Button: Turn off

The large ‘Z’ button turns off the entire strip.

This just calls the ‘clear’ function from earlier if the button is pressed. Nice and easy.

Z Button: Flicker

The smaller ‘C’ button makes the strip flicker.

The function takes a millisecond input of the total blinking period and flips a boolean every half period. If that boolean is true, the function clears the LEDs.

Writing to the Strip

At the end of the loop, the program updates the brightness and writes the LED data to the strip.


And just like that, I have a working LED controller from a Wii Nunchuk!


Here’s the full sketch. Click below to expand the code.

Conclusion

These are really cool little controllers, and they’re surprisingly easy to interface with (library or not). I have a thousand different ideas for how to use these things, and I hope this inspires you to use a Nunchuk in your own project.

My first ‘proper’ project with these is going to be replacing the DDR dance pad for my Nerf McCree controller. Stay tuned!


2018/6/22: This post was originally written using Kevin Harrington’s fork of the WiiChuck library, version 0.0.23. That library no longer works as well as it used to, so I’ve rewritten this using my own extension controller library.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.