I play a lot of Elite: Dangerous. And while I use a reasonably nice HOTAS, I've long wanted a flight panel: a bank of toggle switches with LED indicators that would act as a USB joystick. I can only find one company selling such a thing, and their solution leaves exposed wiring. (a no-no when you live with cats) Also, their website looks like it is from the 90s and just feels kind of sketchy. (Seriously, guys, if you happen to read this, your website does not inspire confidence)

And, anyway, I've been looking for an excuse to learn some basic electronics for a long time. So, I built my own! Several other people have built similar things, but I decided to jump in head-first and not follow any guides, in hopes of learning about electronics and wiring along the way.

Acquiring Gear

First up, a parts list:


And a partial list of tools I needed:

Getting Started

Ok, now that you have this big pile of stuff, what do we do? I started by emulating everything; I was a bit worried about frying my new Arduino board! So I designed a circuit using 123d.circuits.io. You can see it here. Connecting the switch turns on the LED and changes I/O pin 2 from high to low. (the pin is configured as INPUT_PULLUP, see the programming section later)

Next I replicated this with my physical tools. I started by wiring everything up, (you'll want those hybrid jumper/alligator wires to hook up the toggle switch!) then plugged my Arduino into the PC to give it power. Before throwing the switch, I uploaded this very simple sketch to it:

void setup() {
  pinMode(2, INPUT_PULLUP);
  pinMode(13, OUTPUT); // this is the Arduino's on-board LED.
}

void loop() {
  int state = digitalRead(2);
  if (state == HIGH) digitalWrite(13, LOW);
  else digitalWrite(13, HIGH);
}
If this works as expected, then flipping the toggle switch should light up both the breadboard LED and the on-board LED (marked 'L' on the Arduino board). The logic is inverted (we write HIGH when we read LOW) because I'm using INPUT_PULLUP, which reverses the usual logic of the input pin. (This lets me wire the LED without worrying about how much current the input pin can sink. I'm probably being overly cautious here, actually.)

Building the thing

Now that I had a proof of concept, I moved on to building things in earnest. First, I needed a box to store it all in. I had trouble finding an appropriately-sized box (again, see "lessons learned"), so I decided to 3D Print one! I have access to a shared Ultimaker2 3D printer. So I designed and printed a box. I really don't recommend using this design. This was my first attempt ever at 3D printing. The print took about 13 hours, and the resulting box had a bunch of problems, despite my attempt to make careful measurements. I had to drill out the holes for the switches more, and had to hack up the back pretty badly to get the USB port out. I also neglected to put mounting posts in for the lid, (I printed some later, but it was a huge pain) or holes to mount the arduino board on. (The odd bumps on the inside and the plastic bar were meant to be a little physical barrier to hold the board in place, but they printed out way too low to actually do anything.)

So anyway, now I have a box. (the project quickly got nicknamed The Orange Box, naturally) Next, I created five of these, with varying LED colors:


This is just the design from the breadboard realized in a way that lets it interface with the Arduino sensor shield. The red wire is connected from 5V through the LED setup and onto one of the switch posts. The LED has a resistor in series with it; I used 1kΩ resistors for my red and yellow LEDs, and 10kΩ for blue and white. 

The other switch post has lines going to both Ground (black) and the input pin. (white) The wire splices and connections are all soldered, *except* for the 3-pin dupont casing. To make those connections, I had to learn to work with dupont pins, which is a little complicated. You have to:
  1. Strip the end of your wire.
  2. Twist the exposed wire strands together. (this is often a good idea when working with stranded wire)
  3. Lay the wire onto the 'open' part of the dupont pin, and push it in a bit. Ideally you want the bottom of the pin to be flush against your wire casing.
  4. Fold the metal flanges on the pin around the wire with needle-nosed pliers, so that it's semi-closed.
  5. Crimp those flanges down with a crimp tool. Be careful not to crimp the 'top' half of the pin, where you don't have wire. You'll need that to mate the pin with the headers on the board.
  6. Using the pliers again, squeeze the metal that was flattened by the crimp tool into a rounder shape.
  7. Insert the pin into the casing. (For this project, I hade to make sure the voltage line was in the middle, to match the pinout on the shield) There is a correct orientation but it's a bit hard to describe. The pin should click into place and not come back out easily.

It takes a little practice to get the hang of it, but not having any connections soldered directly onto the Arduino makes it a lot more reusable!

Once I had all 5 of these, I mounted them in the box and wired them onto the sensor shield (which was connected to the arduino board. It just plugs right in on top!) With the 3-pin dupont widgets, this was super easy:


Those 3 rows of pins are just a row of Ground, a row of 5V, and then a row for all the I/O pins. So the white wires are all on the bottom row (the input signals), and the black wires are on the top. Each row is labelled on the board: G, V, and S.

Programming the Thing

For me, this was the easy part. Familiar territory. Arduino's "IDE" is really just a slightly specialized C++ framework. I wanted the OS to treat my device as a joystick with as little hassle as possible, so I used this custom firmware for the Arduino's USB communication chip. (Note: you want to install that *last*, because while it's installed you can't upload new sketches to the Arduino. It's easily reversible, though, so you won't ruin anything.)

I wrote a simple library to interface with the Joystick firmware, and a sketch tailored to how I have my inputs setup and what I want them to do. The sketch interprets the toggle switches as momentary inputs; that is, it sends a short button-press event every time you toggle the switch, as opposed to "holding down" the button the entire time the switch is on. This design makes it work well with most of Elite: Dangerous' controls.

In a future iteration I hope to make this all a bit more generalized and include a lot more functionality in the Joystick library. But for now, this works really well!


The Finishing Touches

I printed some support structures to make it possible to screw the box (mostly) shut:



After putting these in place, I briefly lamented not printing counter-sunk screw holes into the box, but then I realized ABS plastic was soft enough that I didn't need them. All I had to do was tighten the screws a bit more, and:



And finally, with everything screwed in place, the finished product:



Lessons Learned

  • 3D printing the project box sounded super cool, but I wouldn't do it again. It took too long, the resulting plastic is a bit weak for the job, and getting the hole placement just right was a pain. (and 3D printed parts don't take especially well to drilling) For my next iteration of this box I've purchased a pre-made project box.
  • If I were to 3D print again: remember to put screw-holes and posts in!
    Mounting the LEDs was a bit of a problem, since the LED holders assume you're wiring them in place. I couldn't use their intended mounting setup, and had to just hot-glue them into place instead. This happened because the LED holders were back-ordered, and didn't arrive until late in the project.
  • Soldering is fun, but moderately permanent. For future projects I'd rather invest in connectors that are slightly easier to disconnect. I bought a bunch of these in the hopes that the female connectors can mount to switch/button terminal posts. (early tests suggest they will work well)
  • The Arduino Uno R3 + sensor shield is nice, but the total package is a bit big. I later discovered the Yourduino Robored, which has the same 3-row pinout as the sensor shield, but in a much smaller (and cheaper) package. I ordered a couple of these and intend to use them in future projects. One downside: they ship from Hong Kong and take a while to arrive.
  • In the quiet of night (when I often play Elite) these toggle switches are loud enough to wake up and scare my housemate! I bought a bunch of rocker switches with LEDs already integrated for future use.