Voltage dividers can be used to control 3-way latched switches. They work in a quite simple way: depending on the position of the switch, the analogue pin connected reads a different value, therefore the status of the switch is identifiable and an appropriate Joystick Output can be sent to the PC.
After having implemented such latched switched I had a simple idea: using a series of resistors connected to an analogue pin to control a number of buttons, each of them wired after a resistor. Being a series, the total resistance value of each button (when considered in sequence)
adds up and is greater than the button before it. This can be used to identify (hence control) multiple buttons by means of a single analogue pin.
Unfortunately, this also mean that only one button can be pressed at the same time (per pin), although this is rarely an issue, at least for flight sims, Star Citizen and similar games.
Here comes reality
The idea is simple: press a button, read the analogue value, compare it to a reference value, activate the corresponding HID Joystick Output. However, due to a number of factors, if we read the value on the analogue pin as we press a button, we may have a dodgy reading. This is due to a number of facts. Extremely simply put, the current doesn’t change from zero to a certain level right away, the board’s circuitry requires a brief amount of time to process the reading and so on. In other words, the whole process needs a bit of time to digest the variation and stabilize.
Escaping real life
There are many ways and techniques to resolve the issue but in this article I will consider only a simplified version of the algorithm I use for my firmware. It uses a timer for each analogue pin and, as a button is pressed, the relative timer starts. When the timer expires, if the reading matches a specific reference value, then a HID “Button Pressed” Joystick output signal is sent to the PC.
When the button is released, the reading doesn’t match the reference any more and a “Button Released” signal is sent to the PC.
Up to here, everything sounds very easy.
Reality strikes back
In theory each button can be identified by one of the 1023 (0 is the open circuit) values used by the board to represent what the analogue pin reads, but unfortunately there are a number of limitations that must be taken into account.
Resistors are not perfect. If you are familiar with the Resistors Colour Code, you know that one of the bands is dedicated to represent the tolerance.
To better understand what this entails, let’s consider a 100 Ω resistor. Its colour code can be: Brown, Black, Brown, Gold. Gold = ±5% tolerance therefore such resistors may present an actual resistance value between 95 Ω and 105 Ω. This means that an arbitrary reference value cannot be used.
Moreover, the read value can change over time due to external factors, such as the temperature (as it gets higher, the conductivity decreases) and therefore, the firmware must take into account all the effects that can affect the process of identification of a button.
A simple solution can be having a wide tolerance but, depending on the resistors chosen and the amount of inputs on the series, the intervals may overlap, making the button identification incorrect.
Compared to a button matrix, the wiring diagram is very simple.
The following is a WIP sketch of my first implementation of this method to a Control Panel. I actually never finished the diagram and since then I didn’t draw any new sketch because, simply put, they are all the same, no matter the number of analogue pins or buttons used.
Once you get the idea behind it, the wiring is extremely easy.
The following picture is a phase of the wiring and soldering of one of my Panels. You can see the breadboards filled with resistors. That’s the series of resistors that allow this algorithm to work. I usually use one breadboard per analogue pin.
The following is a flow chart that should make more clear how the algorithm works. I removed most of the controls, checks and watchdogs to make it is as easy to understand as possible.
For simplicity’s sake, let’s assume that only one analogue pin is being used.
The first part is about the detection of a pressed button. This is accomplished by controlling the status of the analogue pin. There are may different ways to implement this passage: for instance, the reading can be confronted vs the open-circuit reference reading or to the value read in the previous run of the loop. The means you choose may influence the following steps of the program and the additional features the firmware can provide (which are beyond the scope of this article).
If the condition defined in Part I is met, the timer is started. When the timer expires (or reaches a defined threshold, if it’s incremental rather than decremental), the reading on the analogue pin is checked again.
If the reading matches the reference value ± tolerance, a Joystick Output is sent to the PC. Depending on your preferences, the signal can be timed or “toggled on” and released when the condition above is not met any more. I suggest you to avoid sending Joystick commands if the button’s status is not changed. For instance, my firmware sends the command only once.
The last part starts as the condition above is not met any more, therefore the button has been released. If you have opted for a non-timed Joystick output, this is the moment to send a “toggle off” Joystick command to the PC.
After discussing for so long, what is the result of this different implementation? This is an example, the first Panel to use this new algorithm rather than the button matrix: the “Auxiliary Panel”. We have seen part of its wiring diagram above.
I use it mostly for secondary functions, such as Lights, Oxygen, additional LANTIRN controls and so on.
The 3-way latched Master Switch was originally intended for the Mi-8: by toggling the switch, the corresponding seat is selected and the controls operate on a different set of buttons. In other words, it’s like having a different Panel for the pilot, co-pilot and engineer seat.
No Firmware Download?
I’m sorry to disappoint you but I’m now going to share this firmware. I’d love at some point to open a small company (or join one) to build and sell my own, custom-made (and accessible!) Control Panels and the latest, improved and expanded versions of firmware may be the starting point.
Unfortunately the Flight Simulation hobby in a niche, and hardware producers sometimes take advantage of this fact and inflate the costs of their devices (or, I guess, they don’t produce them altogether due to a potentially low ROI). A Control Panels such as the ones I build, with 7 encoders and ~130 logical buttons should be on the market for no more than the cost of an Elgato Stream Deck, which provides 15 buttons for 120£ (of course it’s fancy and has lots of great functions and has amazing features, justifying its cost, but imo a Flight Simmer should have a more ad hoc peripheral).
Not to mention the fact that a custom solution can be adopted to take advantage of the muscle memory and your tactile sense by choosing different shapes of buttons and layouts. This is fundamental for VR users.
I hope you have found this article useful. As usual, my goal is giving you ideas, feel free to use and improve my suggestions 🙂