Sunday, May 15, 2016

Part 2: Building Test Rigs

This section covers wiring up some of the individual modules - audio amplifier, power boost charger, and Arduino Pro Micro - for testing purposes. I thought it was important to breadboard up as much as possible because I sourced ideas for this build from numerous places and wasn't entirely sure if it would all work together. As a result of this decision, I ended up soldering on several pin headers and connectors that I would later de-solder for final assembly. This ended up adding extra work to the build, but I was able to move ahead with programming the Arduino Pro Micro while waiting for the GamePad PCB to be manufactured.


Audio Amplifier

 This audio amplifier from Adafruit.com ($3.95) is a nice little piece of kit. The power coming out of the RPi 3 audio port isn't really enough to produce any sort of reasonable sound from the attached speaker, so this just kicks it up a notch. Here I'm just tacking on red/black wires to the positive and negative connections. Although not shown in the video, I connected these to pin headers to make them easy to plug into the breadboard. All of the wires added in this step were kept intentionally long, anticipating final assembly later on.
Here you can see the audio with it's other intended connections. On the left side, two wires are connected to the RPi board for sound output. The Vin and GND pins are connected to 5V and GND on the 1000C Power Boost board. The output on the right side is connected to a disconnecting headphone jack which in turn has a speaker connected to it.
The audio amp does have a shutdown pin, but after the power switch is configured, all power to the amplifier will be cut when it's turned off.

PowerBoost Charger

I thought I was going to need the PowerBoost Charger for the Pro Micro, but it turns out it's powered via USB. For some applications without being connected to USB it would need external power. In the video, I soldered on the USB connector and pin header for testing later.

Arduino Pro Micro

After counting up the number of GPIO pins I would need for the controller, I decided to just add in the Arduino Pro Micro (Amazon: $8.70). It's a pretty low cost solution to making a USB HID that will just be accepted by the RetroPie/EmulationStation install. It also has some useful analog-to-digital converters that may provide for some interesting add-ons later, like a volume control knob or low battery warning. I realized during this build you could make some pretty cool custom controllers/joystick/control panel using one of these.
Looking around on the net, I found a few confusing tutorials for turning a Pro Micro into a gamepad. Finally, I came across this library (ArduinoJoystickLibrary) by MHeironimus. Looking at the options included in the library API, it's a little overwhelming at first, but then realize you only need to catch button input as we're only creating a gamepad and nothing as complex as a joystick.

Arduino IDE

You'll need to download the Arduino IDE, if you don't have it already. Follow these instructions to get the Joystick library installed with the accompanying USBAPI.h and HID.cpp files. After the library is in place, in the Arduino IDE select Tools -> Board -> Arduino Leonardo, and then Tools -> Port -> USB modem. (Note: this will only show up when you connect the Pro Micro via USB)

Code

Courtesy of Sparkfun.com
Below is the code I used to program my Pro Micro. You will probably need to change the pins connected to each button. Reference the pin out diagram to determine the number for each pin. Avoid using Pin 0 and 1. There's nothing spectacular about this code, but it works with good reaction times. My choice of pins was determined more by wire organization than logic. Copy the code below, paste it into the Arduino IDE, save it. Click the verify button to make sure everything checks out, then you can upload it to the Pro Micro. To test the controller, I used Controllers Lite app (free) from the Apple store. Based on the tutorial linked above, you should be able to test it with built-in tools on Windows.
 #include <Joystick.h>  
 int A=5;  
 int B=4;  
 int X=3;  
 int Y=2;  
 int L1=21;  
 int R1=20;  
 int Up=14;  
 int Down=10;  
 int Left=15;  
 int Right=16;  
 int Start=6;  
 int Select=7;  
 int led=13;
 int BTN_UP=0;  
 int BTN_DOWN=1;  
 int BTN_LEFT=2;  
 int BTN_RIGHT=3;  
 int BTN_SELECT=4;  
 int BTN_START=5;  
 int BTN_A=6;  
 int BTN_B=7;  
 int BTN_X=8;  
 int BTN_Y=9;  
 int BTN_L1=10;  
 int BTN_R1=11;  
 int AState=0;  
 int BState=0;  
 int XState=0;  
 int YState=0;  
 int L1State=0;  
 int R1State=0;  
 int UpState=0;  
 int DownState=0;  
 int LeftState=0;  
 int RightState=0;  
 int StartState=0;  
 int SelectState=0;  
 bool pressed = false;  
 void setup(){  
  pinMode(A,INPUT_PULLUP);  
  pinMode(B,INPUT_PULLUP);  
  pinMode(X,INPUT_PULLUP);  
  pinMode(Y,INPUT_PULLUP);  
  pinMode(L1,INPUT_PULLUP);  
  pinMode(R1,INPUT_PULLUP);  
  pinMode(Up,INPUT_PULLUP);   
  pinMode(Down,INPUT_PULLUP);  
  pinMode(Left,INPUT_PULLUP);  
  pinMode(Right,INPUT_PULLUP);  
  pinMode(Start,INPUT_PULLUP);   
  pinMode(Select,INPUT_PULLUP);  
  pinMode(led,OUTPUT);  
  digitalWrite(led,LOW);  
  Joystick.begin(true);  
 }  
 void loop(){  
  AState=digitalRead(A);  
  BState=digitalRead(B);  
  XState=digitalRead(X);  
  YState=digitalRead(Y);  
  L1State=digitalRead(L1);  
  R1State=digitalRead(R1);  
  UpState=digitalRead(Up);  
  DownState=digitalRead(Down);  
  LeftState=digitalRead(Left);  
  RightState=digitalRead(Right);  
  StartState=digitalRead(Start);  
  SelectState=digitalRead(Select);  
  if(AState==LOW){  
   pressed = true;  
   Joystick.pressButton(BTN_A);  
  } else {  
   Joystick.releaseButton(BTN_A);  
  }  
  if(BState==LOW){  
   pressed = true;  
   Joystick.pressButton(BTN_B);  
  } else {  
   Joystick.releaseButton(BTN_B);  
  }  
  if(XState==LOW){  
   pressed = true;  
   Joystick.pressButton(BTN_X);  
  } else {  
   Joystick.releaseButton(BTN_X);  
  }  
  if(YState==LOW){  
   pressed = true;  
   Joystick.pressButton(BTN_Y);  
  } else {  
   Joystick.releaseButton(BTN_Y);  
  }  
  if(L1State==LOW){  
   pressed = true;  
   Joystick.pressButton(BTN_L1);  
  } else {  
   Joystick.releaseButton(BTN_L1);  
  }  
  if(R1State==LOW){  
   pressed = true;  
   Joystick.pressButton(BTN_R1);  
  } else {  
   Joystick.releaseButton(BTN_R1);  
  }  
  if(UpState==LOW){  
   pressed = true;  
   Joystick.pressButton(BTN_UP);  
  } else {  
   Joystick.releaseButton(BTN_UP);  
  }  
  if(DownState==LOW){  
   pressed = true;  
   Joystick.pressButton(BTN_DOWN);  
  } else {  
   Joystick.releaseButton(BTN_DOWN);  
  }  
  if(LeftState==LOW){  
   pressed = true;  
   Joystick.pressButton(BTN_LEFT);  
  } else {  
   Joystick.releaseButton(BTN_LEFT);  
  }  
  if(RightState==LOW){  
   pressed = true;  
   Joystick.pressButton(BTN_RIGHT);  
  } else {  
   Joystick.releaseButton(BTN_RIGHT);  
  }  
  if(StartState==LOW){  
   pressed = true;  
   Joystick.pressButton(BTN_START);  
  } else {  
   Joystick.releaseButton(BTN_START);  
  }  
  if(SelectState==LOW){  
   pressed = true;  
   Joystick.pressButton(BTN_SELECT);  
  } else {  
   Joystick.releaseButton(BTN_SELECT);  
  }  
 }  

Game Pad

At this point in the build and video recording, I didn't have the gamepad PCB back from manufacturing yet. First, I'll cover the test controller I made and then I'll go over the creation and design of the gamepad PCB.

Test Controller

Here is the test controller I came up with. A while ago I ordered 100 tactile buttons to have on hand for stuff, but I read the serial number wrong and ended up ordering brown buttons. *sigh* Great for testing, but not much else. The test controller is very simple. One side of each button is connected to a common ground (the top rail on the breadboard). The other side connected to its own pin on the Pro Micro. Each pin corresponds to the above code. I was actually able to play an entire level of Super Mario and Tetris using just this game pad. One very nice feature about the Joystick library, versus something like simulating a keyboard, is you can hold down buttons and they will be continuously read by the Pro Micro. This is kind of important for playing some games.

GamePad PCB

Front Case Layout
Originally, I purchased an SNES knock-off controller to part out for this project. I guess some part of me was hoping Nintendo used relatively the same layout for buttons. After tearing down the controller and looking at the measurements, I realized cutting up the circuit board wasn't really going to work for the build I wanted. Both because it would be pretty janky and because the button pads didn't exactly line up with the existing holes in the GAMEBOY case. I did find an existing gamepad PCB for sale by kitsch-bent.com, and now that I actually look at their site I see that they also have an A/B/X/Y version (facepalm). Had I seen that before, I would have just ordered it instead of designing my own. But since I went through all the work, I'll post what I created here.

Note: the Front Case Layout below is probably not going to match the kitsch-bent.com PCB. Just looking at it, my buttons are a little closer together and skewed slightly where the kitsch-bent.com PCB has more square tangents.

If you would like to order the PCBs I designed, they can be ordered directly from OSHPark.com (my favorite PCB fab house) from here:

Order from OSH Park
You will have to order three (3) PCBs as a minimum order which comes to about $37.05 with shipping and wait about 2 weeks for shipping and manufacturing.

Files

No comments:

Post a Comment