Arduino-based throttle controller with 3D printed case
Following on from the custom joystick mounts I designed, I also needed a device to serve as the “throttle” part of my Hands On Throttle and Stick (HOTAS) setup. I already had a joystick and rudder pedals from VKB which I was very happy with. However, VKB’s throttle was not due to be released until sometime in 2021. I considered other brands but I did not want to commit to a purchase until VKB’s throttle was out.
In the meantime, I still needed a device with one or more throttle controls and several additional buttons. I decided to make my own.
At this point I had been playing a fair bit of Elite Dangerous and Microsoft Flight Simulator. Despite having ~30 different inputs on the Kosmosima joystick I wanted even MORE inputs to bind to. I planned a device with the following controls:
- Throttle Axis x2
- Push Button x8
- Dual throw momentary toggle x2 (Toggle switches with separate UP and DOWN poles which return to center after being flipped)
- Rotary encoder with button x1
I sketched out the parts list and a rough layout along with some dimensions for a box to hold them:
With those components in mind I researched which controller board to use for the build. I considered several options but ultimately settled on the Arduino-based Adafruit ItsyBitsy. I chose this due to its very low part cost and the fact that it is based on the ATmega32u4 which makes it easy to implement a USB HID (this means we can plug the device into a PC and it shows up as a game controller). The ItsyBitsy included enough pin inputs to support all of the components in my spec sheet.
With the controller board and all of the individual components on order I started to design a case to hold everything together. As a first step, I modeled every part in Blender with accurate dimensions. Fortunately, the components I ordered all provided datasheets which included technical drawings of the parts. I used these to get accurate dimensions for the 3D models.
I placed those parts in a collection in the Blender scene then placed instances of them into a separate collection containing the pieces of the case. I used boolean modifiers to cut out mounting holes in the case top for the various parts.
Placing the parts this way ensures that the case itself has enough clearance to actually fit the entirety of the part. The rest of the case design followed the same basic non-destructive approach I took with the design of the chair mounts. I also designed a simple print-in place bracket to raise the height of the throttle to a comfortable position.
For the actual throttle handle itself I created a split design that could attach to a pair of cheap rotary potentiometers. The handles are attached to the pots with a thick pad of felt to give them some resistance and keep them from moving due to their own weight. The potentiometers are attached to a pair of brackets which are bolted directly to the main panel.
I 3D printed the parts of the case and attached all of the components to the main panel. This allowed me to test the fit which worked well because I had verified this properly in the design phase (woo!).
I wired up everything with some alligator clip leads and tested the connections while building out the code. Once everything was verified and working I soldered it all together.
The ItsyBitsy micro-controller runs a very basic Arduino HID joystick program which maps the state of the various hardware controls to logical jostick buttons. I used two great libraries to make this as simple as possible.
The device needed to handle USB HID communication to present the ItsyBitsy to the host operating system as a game controller. For this, I used Giuseppe Martini’s Joystick Library for Arduino. With this library I can simply fetch the current state of each controller’s pin and assign it to an axis or button in the virtual controller.
Button and potentiometer values are very simple to read. However, the rotary encoder is much trickier. The encoder itself has three pins (not counting voltage and ground) which go LOW or HIGH in a particular pattern depending on the specific state of the physical control itself. There is a fair amount of complexity involved in correctly reading the signals coming from a rotary encoder and turning them into a series of UP and DOWN button presses. Naive implementations can often fail when the encoder is spun too quickly, for example.
I tried several libraries which attempt to handle this challenge and even wrote some of my own code. The best implementation I found, and the one I chose for this project, is gfvalvo’s NewEncoder library. This library had the most consistent and accurate handling of all of the ones I tested.
I am quite happy with the finished design. It incorporates a variety of controls into a simple easy-to-mount box. I’ve been using it constantly with all of the popular Earth and space-flight games. With what I learned from making this I could definitely see building a more advanced custom button box in the future.
Here is the finished device in action. I am taking off in the Icon A5 in Microsoft Flight Simulator: