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 |
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:
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.
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.
No comments:
Post a Comment