The Arduino Microprocessor Miniterm Project Pages: keattsd

Here is keattsd

Bluetooth SNES Controller

Supplies

I used the following supplies for my mini-term project:

  • Arduino Uno microcontroller
  • RN-42 bluetooth module
  • USB A to B cable
  • One 330-ohm resistor
  • Five alligator clips
  • One breadboard
  • Two basic LEDs
  • Close to 22 gauge wire
  • Bluetooth equipped computer
  • Blue painter’s tape may help

If you don’t care about any of my hard work, you can skip to the tutorial.

Daily Log (Hard Work)

Day 1

We started mini-term on Thursday, February 24. This was my first time dealing with the Arduino. We started with our first Hello, World programs in the Arduino programming environment. We used pin 13 for programming a blinking LED and pin 11 for a fading LED using pulse width modulation. We also covered a small amount of serialization and copy/pasted Marshall’s Processing code.

The Arduino Microprocessor Miniterm Project Pages keattsdDay 2

We started our actual Arduino projects today. I spent the entirety of the day on getting the bluetooth module to work. Getting the module powered and connecting was simple enough, it was the serialized input/ouput that was massively difficult. This, of course, was not helped by my seeming inability to use the correct baud frequency and my tendency to improperly connect the transfer/receive pins. However, by the end of the day (with a few extra hours put in) I was toggling a fading LED from my laptop and my phone.Day 3

With the bluetooth module out of the way, I– wait, something’s not right here. Oh yes, my current setup had me giving the arduino input (to toggle the LED) from my computer, but my actual project requires the opposite: to give my computer input from the arduino. At that point, I realized that I needed to plan out my entire project. I divided my project into three major objectives.

  1. Making the SNES controller send keypresses to the Arduino
  2. Making the Arduino send keypresses to my computer via bluetooth
  3. Having those keypresses being emulated as a real keyboard on my computer

I had already completed the second objective, and I had begun working on the first over the weekend. Unfortunately, I found out that the wires inside the SNES controller are fragile, ancient artifacts (weak threaded copper wires) and they can’t be put directly into a breadboard. Instead, I elected to put alligator clips on each of the five SNES pins. This ended up being extremely disorderly and the controller’s serial output was complete nonsense, which was (retrospectively) likely due to faulty connections and shorted circuits.

Night 3

So, I actually worked on my mini-term project outside of class every day, even though we weren’t required to. I accomplished so much after the third day of class that I’d feel guilty if I didn’t mention it. I wanted to rewire my entire project because it was too confusing for anyone other than myself to understand, and it generally hindered my work. I had the idea to tape it all down to a small piece of cardboard and labeling it. It took a few hours, but was ultimately worth it because the SNES controller worked perfectly after I rewired it.

Day 4

I spent some of the morning fixing minor issues and getting the serialized output to go through bluetooth, but most of my morning (and lunch break) was dedicated to finding an elegant solution to emulating keystrokes on a computer. I stumbled upon this wondrous forum post by cozmokramer and found that his implementation was exactly like what I was imagining, but even more efficient. I spent the remainder of the day modifying his NES code so it supported four more buttons. (That night is actually when I started writing things for my web page.

Day 5

My entire morning was devoted to documenting my project on my web page and fixing a few bugs. This was when I realized that returning “10” and “11” when the left and right buttons were unpressed was a bad idea because they could be read as 1 and 0 simultaneously being unpressed. I spent the entire afternoon replacing my directly wired controller with a fully working controller. The problem with my controller that I had cut open (because it was already broken… I fixed it) was that the d-pad was too stiff to smoothly play Super Mario World.

As you can see, I use gratuitous amounts of blue painter’s tape to ensure a consistent connection.

Day 6

I thought I’d finish my project in a few hours today, but I actually spent more time working than any other day. Discounting no more than an hour for food and bathroom runs, I spent 12 hours (from 8 am to 8pm) in the robotics lab. I would’ve been done around 4pm, but then found out that all of the wiring I had done on my Arduino shield was wrong for two reasons.

  1. I had a bunch of pointless wires bridging connections that already existed on the PCB.
  2. All of my wiring was shorting itself. I put the row of bluetooth wires and SNES wires in rows of PCB-connected holes.

It took many hours to fix it, but I now have a working product.

You may be wondering what that funky looking connector attached to the Arduino shield is. It’s actually an internal from a SNES. There are contacts on the back of the controller board that I wired directly into my Arduino shield. Opening the SNES wasn’t easy, either. It uses 4.5mm security bits, which are proprietary Nintendo screws. We used a drill press and a dremel to reach the internals.

Tutorial

Here’s my tutorial for setting the hardware and software up. Feel free to combine this tutorial with any other online resources. This tutorial assumes you are already slightly familiar with Arduino, Java, and everything.

Downloads

The first step is to download all the above and install them. They each have their own easily accessible installation instructions. Once you’ve done that, you should be able to save, verify and upload the following script to your Arduino via USB.

#include <SNESpad.h>

// put your own strobe/clock/data pin numbers here -- see the pinout in readme.txt
SNESpad nintendo = SNESpad(2,3,4);

int 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 x = false; // X Button
boolean y = false; // Y Button
boolean l = false; // L button
boolean r = false; // R button
boolean e = false; // Select Button
boolean s = false; // Start Button
boolean u = false; // Up Button
boolean d = false; // Down Button
boolean f = false; // Left Button
boolean i = false; // Right 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,x,y, l,r,e,s up,down,left,right */
int keysReleased[] = {
  0,0,0,0, 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(115200);
  pinMode(13, OUTPUT);
}

void loop() {
  state = nintendo.buttons();

  // Activity LED on pin 13
  if (state != 0) {
    digitalWrite(13, HIGH);
  } else {
    digitalWrite(13, LOW);
  }

  // A
  if (state & SNES_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
    }
  } else if (a == true) { // Key might have been released so we check and if so change the
    a = false;            // value in our released array
    keysReleased[0] = 1;
    isReleased = true;
  }

  // B
  if (state & SNES_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
    }
  } else if (b == true) { // Key might have been released so we check and if so change the
    b = false;            // value in our released array
    keysReleased[1] = 1;
    isReleased = true;
  }

  // X
  if (state & SNES_X) {
    if (!x) {
	x = true; // Make sure the button is only pressed once
	Serial.println('X'); // Print the button to be picked up by our robot
    }
  } else if (x == true) { // Key might have been released so we check and if so change the
    x = false;            // value in our released array
    keysReleased[2] = 1;
    isReleased = true;
  }

  // Y
  if (state & SNES_Y) {
    if (!y) {
	y = true; // Make sure the button is only pressed once
	Serial.println('Y'); // Print the button to be picked up by our robot
    }
  } else if (y == true) { // Key might have been released so we check and if so change the
    y = false;            // value in our released array
    keysReleased[3] = 1;
    isReleased = true;
  }

  // L
  if (state & SNES_L) {
    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
    }
  } else if (l == true) { // Key might have been released so we check and if so change the
    l = false;            // value in our released array
    keysReleased[4] = 1;
    isReleased = true;
  }

  // R
  if (state & SNES_R) {
    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
    }
  } else if (r == true) { // Key might have been released so we check and if so change the
    r = false;            // value in our released array
    keysReleased[5] = 1;
    isReleased = true;
  }

  // Select
  if (state & SNES_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
    }
  } else if (e == true) { // Key might have been released so we check and if so change the
    e = false;            // value in our released array
    keysReleased[6] = 1;
    isReleased = true;
  }

  // Start
  if (state & SNES_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
    }
  } else if (s == true) { // Key might have been released so we check and if so change the
    s = false;            // value in our released array
    keysReleased[7] = 1;
    isReleased = true;
  }

  // Up
  if (state & SNES_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
    }
  } else if (u == true) { // Key might have been released so we check and if so change the
    u = false;            // value in our released array
    keysReleased[8] = 1;
    isReleased = true;
  }

  // Down
  if (state & SNES_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
    }
  } else if (d == true) { // Key might have been released so we check and if so change the
    d = false;            // value in our released array
    keysReleased[9] = 1;
    isReleased = true;
  }

  // Left
  if (state & SNES_LEFT) {
    if (!f) {
      f = true; // Make sure the button is only pressed once
      Serial.println('F'); // Print the button to be picked up by our robot
    }
  } else if (f == true) { // Key might have been released so we check and if so change the
    f = false;            // value in our released array
    keysReleased[10] = 1;
    isReleased = true;
  }

  // Right
  if (state & SNES_RIGHT) {
    if (!i) {
      i = true; // Make sure the button is only pressed once
      Serial.println('I'); // Print the button to be picked up by our robot
    }
  } else if (i == true) { // Key might have been released so we check and if so change the
    i = false;            // value in our released array
    keysReleased[11] = 1;
    isReleased = true;
  }The Arduino Microprocessor Miniterm Project Pages keattsd Schematic /* 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 < 12; i++){
      if (keysReleased[i] == 1) {
        keysReleased[i] = 0; // Reset the button listener
		if (i < 10) { 
          Serial.println(i);
		} else if (i == 10) {
		  Serial.println("-");
		} else {
		  Serial.println("=");
		}
      }
    }
  }
  delay(1);
}

Unfortunately, I had to add two roundabout conditionals to if(isReleased). Because the program now returns integers 0-11, instead of 0-7, we have a problem with both of our two-digit integers (10 and 11.) The output is sometime broken up into multiple lines, in which case they wuold be read in as a 1 and a 0, or two 1s.

Now you should wire everything according to the following diagram. Once the bluetooth module is set up, you can connect to it using standard bluetooth serial terminal software (such as PuTTY.) The default passcode to the RN-42 is 1234.

 

For more detail: The Arduino Microprocessor Miniterm Project Pages: keattsd


About The Author

Ibrar Ayyub

I am an experienced technical writer holding a Master's degree in computer science from BZU Multan, Pakistan University. With a background spanning various industries, particularly in home automation and engineering, I have honed my skills in crafting clear and concise content. Proficient in leveraging infographics and diagrams, I strive to simplify complex concepts for readers. My strength lies in thorough research and presenting information in a structured and logical format.

Follow Us:
LinkedinTwitter

Leave a Comment

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

Scroll to Top