Posts about... All (17) Android (2) Hooking Up Parts (10) Game Controllers (3) Robots (2)

Hack a Nintendo (NES) Controller

The Nintendo (NES) Controller is a familiar classic. It’s simplicity makes it easy to hack and re-purpose for your own needs. This post details how to easily read the button-state values into an Arduino.

Parts

Steps

  1. Before you begin, see the diagram showing the Nintendo pin-out below. (Pinouts.ru is also a great source)
  2. NES Pinout

  3. Now that you understand the pins on the Nintendo controller, hook up your jumper wires by using arrow’s colors from the photo above. (Note: The pins are fairly deep, be sure that your wires are deep enough and snug to insure a strong connection)
  4. As for the other ends of the wires, place the RED wire from +5V on the Nintendo controller to 5V on the Arduino. Place the BLACK wire from GROUND on the NES controller to GROUND on the Arduino. Pretty straight forward.
  5. Place the ORANGE wire from STROBE on the NES controller to Digital Pin 2 on the Arduino.
  6. Place the WHITE wire from CLOCK on the NES controller to Digital Pin 3 on the Arduino.
  7. Place the YELLOW wire from DATA on the NES controller to Digital Pin 4 on the Arduino.
  8. NES Wired

  9. Download the NESpad_1.3 library by rahjix. Unzip the folder into your “libraries” folder within your Arduino projects folder (ie. …/Documents/Arduino/libraries). If this is your first library, you may need to create a “libraries” folder, as I did. This handy library will do all the hard work dealing with the pulses, enabling you to simply check for Boolean values such as “NES_A” rather than dealing with binary. Besides, why reinvent the wheel?
  10. To be sure you installed the library correctly, restart your Arduino software and go to “Sketch > Import Library” and make sure NESpad is on the list.
  11. NES Import Library

  12. Copy & paste the following code into the Arduino software:
  13. #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);
    }
    }
    }
    }

  14. Connect the Arduino to your computer via the USB cable (A to B) and upload the code to your board.
  15. Once uploaded, open up the Serial Monitor within the Arduino Software. Notice when a button on the NES controller is PRESSED, the corresponding letter is printed to the monitor. (Note: If you’re getting very sporadic results, such as a bunch of letters and numbers rapdily filling the Serial Monitor, you most likely have a lose connection between your wire(s) and the NES controller’s pins. Be sure they are tight enough.)

Explanation

When a button is RELEASED, a unique number is displayed for each button. This number corresponds to the buttons position in the array that holds the binary number received from the NES controller. In other words, the Arduino is receiving 8-bit binary numbers from the the NES controller, ie. 10000100. The order is as follows: A, B, Up, Down, Left, Right, Start, Select. 1 stands for an “on” bit (button pressed), and 0 stands for an “off” bit (button NOT pressed); therefore, in the example 10000100, the ‘A’ and ‘Right’ buttons are pressed. Now the numbers that display after a button is released should make sense. When the ‘A’ button is PRESSED, ‘A’ is printed to the Serial Monitor. Once ‘A’ is RELEASED, ‘0’ is printed to the Serial Monitor (since arrays start at 0 and ‘A’ is the first bit). Feel free to modify the code to something possibly more useful, such as an uppercase letter (A) when pressed and a lowercase letter (a) when released for example.

Video