Introduction: Wii Nunchuck Synthesizer
The World of Wii Music:
I decided to finally combine my love of music with the little bit of programming experience I have gained over the past few years. I have been interested in creating an instrument of my own ever since I saw a talk by Tod Machover at my school. If you're unfamiliar with his work give him a Google, as he has been pushing the boundaries of music, technology, as well as their intersect for a number of years now (MIT media labs, Rock Band, Guitar Hero etc. . .).
I have connected my Nunchuck to an Arduino Uno running on the Mozzi sound synthesis library due to the well-documented use of both online. For ease, I am using a WiiChuck breadboard adapter which plugs right into the Arduino. This relatively simple project plays a series of pitches depending on the Pitch (YZ-Plane) measured from the Nunchuck's accelerometer. The joystick's Y value is mapped to the gain to make the pitch louder or softer. It also changes chords depending on the Z-Button and turns on a phase modulation envelope when the C-Button is pressed. The envelope's frequency is then modified with the Roll measured from the Nunchuck (picture turning a knob).
Resources:
- 1 x Arduino Uno
- 1 x Wii Nunchuck
- 1 x WiiChuck Adapter
- 1 x breadboard compatible 3.5mm female stereo jack
- 1 x 3.5mm audio cable
- 1 x speaker of some sort (You can plug in a buzzer at first to test it out
- 4-5 Wires of various colors
Optional but recommended:
- 1 x 330 Ohm resistor
- 1 x .1 uF capacitor
Step 1: Plugging in Your NunChuck
Copy/Paste the WiiChuck class from Arduino Playground. We will need the version with the declaration of PWR and GND pins. Save it as WiiChuck.h and keep it in the same directory as your project.
Now copy/paste the following into Arduino IDE and upload it.
<p>#include "Wire.h"<br>//#include "WiiChuckClass.h" //most likely its WiiChuck.h for the rest of us. #include "WiiChuck.h" WiiChuck chuck = WiiChuck();</p><p>void setup() { //nunchuck_init(); Serial.begin(115200); chuck.begin(); chuck.update(); //chuck.calibrateJoy(); }</p><p>void loop() { delay(20); chuck.update(); </p><p> Serial.print(chuck.readPitch()); Serial.print(", "); Serial.print(chuck.readRoll()); Serial.print(", "); </p><p> Serial.print(chuck.readJoyX()); Serial.print(", "); Serial.print(chuck.readJoyY()); Serial.print(", "); </p><p> if (chuck.buttonZ) { Serial.print("Z"); } else { Serial.print("-"); }</p><p> Serial.print(", "); </p><p>//not a function// if (chuck.buttonC()) { if (chuck.buttonC) { Serial.print("C"); } else { Serial.print("-"); }</p><p> Serial.println();</p><p>}</p>
Disconnect your Arduino from power and connect your WiiChuck adapter to Analog Pins 2-5 on your Arduino.
Connect to power again and ensure that the Nunchuck's values are being sent to your Arduino and being printed to the Serial Monitor. If you are not seeing any change in the numbers make sure you're connections are good, and you're Nunchuck is functioning. I spent a few days trying to fix software before realizing my Nunchuck's wire was internally broken!
Next, we will hook everything up to Mozzi . . .
Step 2: Getting to Know Mozzi
First, you will need to download the latest version of Mozzi. They are fueled by donations so donate if you feel so inclined and download the library. You can add it to your libraries easily by choosing Sketch > Libraries > Add .ZIP Library... from Arduino IDE.
Now we will connect the 3.5mm headphone jack to the breadboard and Arduino so we can easily connect to it later (you can unplug the Nunchuck and adapter for now).
- Plug in your Jack to the bottom right corner of the board to make room for the rest. The jack should be 5 pins wide.
- Connect the middle row to ground with a jumper wire.
- Connect the topmost row of the jack to an empty row above (Row 10 in the picture). This is the wire carrying the audio signal.
Connect Digital Pin ~9 to row 10 as well.
Connect Ground on your Arduino to the ground rail on the breadboard.
- You don't necessarily need to use the resistor and capacitor yet but you may notice a high pitched squeal if you do not. It acts as a low pass filter to eliminate frequencies above ~ 15 kHz.
Open Mozzi's Sinewave sketch in Arduino IDE by choosing File > Examples > Mozzi > Basics > Sinewave. This is essentially Mozzi's equivalent of "Hello World".
Upload the sketch and plug in a speaker to the breadboard. You can use a buzzer as well if you haven't wired the breadboard to the audio jack yet.
If you don't hear a constant A4 (440Hz) coming from your speaker ensure all your connections are good and try again.
Next, we will connect the Nunchuck to the Arduino!
Step 3: Putting It All Together
Now we are going to use the roll value from the Nunchuck to change the frequency of a Sinewave.
- From Arduino IDE Choose File > Examples > Mozzi > Sensors > Piezo Frequency
We will need to add a few lines to this code in order to get it to work with the Nunchuck. Add an include to the WiiChuck library and instantiate a WiiChuck object called chuck. You can also comment out the declaration of PIEZO_PIN or just delete it as we won't be using it.
#include "WiiChuck.H" WiiChuck chuck = WiiChuck(); //const int PIEZO_PIN = 3; // set the analog input pin for the piezo
Now in setup, we will need to add the following:
chuck.begin();<br>chuck.update();
and finally we will need to change a few things in updateControl():
<p>void updateControl(){</p><p> chuck.update(); // get latest nunchuck data <br> // read the piezo //int piezo_value = mozziAnalogRead(PIEZO_PIN); // value is 0-1023 int piezo_value = map( </p>
Comment out the line that sets piezo_value and add the following underneath:
void updateControl(){<br> chuck.update(); // get latest nunchuck data // read the piezo //int piezo_value = mozziAnalogRead(PIEZO_PIN); // value is 0-1023 // We don't need the line above but why not map the roll to the same range? int piezo_value = map(chuck.readRoll(), -180, 180, 0 1023);
Upload the code and the frequency should correspond to your Nunchuck's Roll. Try mapping it to different frequency ranges. If you haven't noticed further below in the sketch the value from the sensor is multiplied by 3 so we are currently playing tones from 0 Hz to about 3000 Hz.
Step 4: Final Touches
Now you are ready to upload the final version of the code which I have pieced together from the previous step and a few more of Mozzi's examples (Phase_Mod_Envelope, and Control_Gain to be exact). To make my life easier I also included a file called pitches.h which simply defines frequency values with familiar note names (i.e. NOTE_A4).
I suggest reading the Mozzi documentation as much of the code is straight from the examples except for the code for the Nunchuck.
Here is a link to my Git repository. All important files are included except for the Mozzi library which you should get from their website so it's up to date. Download WiiMusic.ino and upload it to your device to hear what it sounds like. I suggest you play around with the parameters I am changing (change the map ranges, divide/multiply numbers, etc. . .) as that is how I found the particular sound I was looking for.
Reflection
I don't feel like I am quite finished. That's not to say I'm not satisfied with the project or the sound it makes, but I feel like I just dipped my toes into a new world that I want to keep exploring so I will add a new branch from this project as I continue to work.
Still, that being said this was my first true journey into the world of microcontrollers so I am very grateful for the learning experience. The twenty or so hours I spent working on it gave me Christmas ideas for myself and practically every member of my family. I somewhat regret not working on this project with someone else as I could have used plenty of advice and guidance along the way. However, I personally learned a lot through my trials including three days of pulling my hair out trying to debug a software problem that was never there (an internal wire in the Nunchuck had broken).
There are still a number of possibilities moving forward. For instance, I would love to use the Arduino as a type of MIDI interface in between a MIDI controller and the headphone out to change parameters of the MIDI note as there are so many to choose from (volume, cutoff, envelope frequency, pitch bend, modulation, vibrato, you name it). This would allow for a lot more flexibility including switching parameters with the buttons, and simply playing a chord that isn't hardcoded into a C++ array.