NOTE: Still a work in progress. I am hoping to finish it in the next couple of days. Thanks!
Hello this is my first week with my Arduino Uno and I thought I would take some time to write up a quick tutorial on my first project. My hope is that I will save someone time and energy hunting down all of the specs and websites I had to do in order to get this project up and running. The main portion of this project was actually figuring out how to actually control a NES emulator with the controller once we were done wiring. Most of the tutorials I found online were only “How to control leds with your NES controller?” or the like, but this isn’t what I wanted. What I wanted to do was to actually be able to control a NES Emulator on my computer.
So at a very high level this is what we are going to do. First we will wire up the Arduino to an old NES Controller. Then we will write an Arduino Sketch that will output the keypress and keyrelease events from the NES Controller. Lastly we will capture these serial output events in a Java class and then use the Java Robot class to convert those Serial Outputs to actual keystrokes, which we can then map to any NES Emulator.
Step 1 Parts List:
- Arduino Uno (Or equivalent)
- 22 gauge wire
- NES Controller (~$10)
- A USB cable type B (~$8)
- Project casing (optional ~$6)
- NES Port (optional ~$8.99 for two)
- Java Knowledge (Not optional…jk)
Step 2 Wiring:
This is the general pin layout for the NES controller, along with the Fritzing wiring diagram. Should be pretty easy to do, because the wire can just be pushed into the NES controller for prototyping. Make sure they get pushed in all of the way though.
Step 3: Coding the Arduino Sketch
Instead of rewriting all of the events by hand I used a current NES Library (NESpad) in my sketch to capture the events. Here is the link to that project http://code.google.com/p/nespad/. So head over there and download the most current version of the library. At the time of writing this is version 1.3. Copy the zip file to ArduinoHome/libraries and unpack it. You might want to also copy the contents of the examples folder to ArduinoHome/examples. Now start the Arduino IDE up and Click Sketch → Import Library → NESpad. If NESPad is not on this list then you installed the library incorrectly. Please head over to http://www.arduino.cc/en/Reference/Libraries for better instructions on installing libraries.
Now that we have installed the NESpad library correctly we can test out our connections to our controller. Cut and paste the code below, and then burn it to the Arduino. After the code is successfully uploaded you should be able to push the A button on your controller and see the LED from PIN 13 light up. Pretty cool huh? We can do better.
#include <NESpad.h>
NESpad nintendo = NESpad(2,3,4);
byte state = 0;
void setup() {
pinMode(13, OUTPUT);
}
void loop() {
state = nintendo.buttons();
digitalWrite(13, state & NES_A);
delay(1);
}
Now that you see your controller is working cut and paste the code below and upload it to the Arduino board. You can open the Serial Monitor and start pressing buttons. You will see a bunch of numbers and letters appearing as buttons are being pressed and released. These are the outputs we are going to capture in the Java Robot class we will be writing in a minute. If you are curious to see how this code works take a moment to peak through it. I have commented everything, so hopefully it is clear. I have also taken steps to ensure that it is as logical to follow as possible, and I am also well aware there are quite a few areas of the code where optimizations could be made.
#include <NESpad.h>
// put your own strobe/clock/data pin numbers here -- see the pinout in readme.txt
NESpad nintendo = NESpad(2,3,4);
byte state = 0;
/* A button gets marked as true as soon as it is pressed. That way
we know to not "press" it again */
boolean a = false; //A Button
boolean b = false; //B Button
boolean u = false; //Up Button
boolean d = false; //Down Button
boolean l = false; //Left Button
boolean r = false; //Right Button
boolean s = false; //Start Button
boolean e = false; //Select Button
/* We will pass on this array whenever a key is released. Once the
key is released we will turn that 0 into a 1. That way in our java program
we will know exactly which keys we just released. The keys will always go
in this order: a,b,u,d, l,r,s,e */
int keysReleased[] = {
0,0,0,0, 0,0,0,0};
/* We will set this to true only when a button has been released. This will
stop us from sending the keysReleased array every loop to our java robot */
boolean isReleased = false;
void setup() {
Serial.begin(9600);
}
void loop() {
delay(5);
state = nintendo.buttons();
// A
if (state & NES_A){
if(!a){
a = true; //Make sure the button is only pressed once
Serial.println('A'); //Print the button to be picked up by our robot
}
}
//Key might have been released so we check and if so change the
//value in our released array
else if (a == true){
a = false;
keysReleased[0] = 1;
isReleased = true;
}
// B
if (state & NES_B){
if(!b){
b = true; //Make sure the button is only pressed once
Serial.println('B'); //Print the button to be picked up by our robot
}
}
//Key might have been released so we check and if so change the
//value in our released array
else if (b == true){
b = false;
keysReleased[1] = 1;
isReleased = true;
}
// Up
if (state & NES_UP){
if(!u){
u = true; //Make sure the button is only pressed once
Serial.println('U'); //Print the button to be picked up by our robot
}
}
//Key might have been released so we check and if so change the
//value in our released array
else if (u == true){
u = false;
keysReleased[2] = 1;
isReleased = true;
}
// Down
if (state & NES_DOWN){
if(!d){
d = true; //Make sure the button is only pressed once
Serial.println('D'); //Print the button to be picked up by our robot
}
}
//Key might have been released so we check and if so change the
//value in our released array
else if (d == true){
d = false;
keysReleased[3] = 1;
isReleased = true;
}
// Left
if (state & NES_LEFT){
if(!l){
l = true; //Make sure the button is only pressed once
Serial.println('L'); //Print the button to be picked up by our robot
}
}
//Key might have been released so we check and if so change the
//value in our released array
else if (l == true){
l = false;
keysReleased[4] = 1;
isReleased = true;
}
//Right
if (state & NES_RIGHT){
if(!r){
r = true; //Make sure the button is only pressed once
Serial.println('R'); //Print the button to be picked up by our robot
}
}
//Key might have been released so we check and if so change the
//value in our released array
else if (r == true){
r = false;
keysReleased[5] = 1;
isReleased = true;
}
//Start
if (state & NES_START){
if(!s){
s = true; //Make sure the button is only pressed once
Serial.println('S'); //Print the button to be picked up by our robot
}
}
//Key might have been released so we check and if so change the
//value in our released array
else if (s == true){
s = false;
keysReleased[6] = 1;
isReleased = true;
}
//Select
if (state & NES_SELECT){
if(!e){
e = true; //Make sure the button is only pressed once
Serial.println('E'); //Print the button to be picked up by our robot
}
}
//Key might have been released so we check and if so change the
//value in our released array
else if (e == true){
e = false;
keysReleased[7] = 1;
isReleased = true;
}
/* If a key has been released then our java robot needs to know about it. So what we
are going to do is to iterate over our array if a key has been released and print out the
position in the array of that key. So for example if "Up" has been released we will
see that our array looks like this [0,0,1,0, 0,0,0,0]. So then we will print 2 to the java robot
so it knows that "Up" has been released. Likewise we would print 7 for the start button on release. */
if(isReleased){
isReleased = false; //Reset the boolean
for(int i=0; i < 8; i++){
if(keysReleased[i] == 1){
keysReleased[i] = 0; //Reset the button listener
Serial.println(i);
}
}
}
}