Used in this project:
- Arduino Mega, provided by DFRobot go check them out over at: https://www.dfrobot.com/product-1175.html
(All links below are affiliate links that help support the channel)
- Multiposition switches x2 https://s.click.aliexpress.com/e/_9z81kP (I’d recommend buying two three-position switches)
- LED Diodes x16 (8x green, 8x white) https://amzn.to/3G7crDR
- On/Off toggle switches https://amzn.to/3wGdnuN
- Wiring https://amzn.to/3MzwUDJ or https://amzn.to/3MyLHyw
Tools used:
- Soldering station (Hako FX-888) https://amzn.to/3Mx3NRr
- 3D printer (cr6-SE and Ender 3) https://amzn.to/3lrYjvi, https://amzn.to/39Dt3XO, https://s.click.aliexpress.com/e/_9hrZnl
- Makita drill https://amzn.to/3yMBIBt
Multiposition switches
There is an enormous amount of different multiposition switches available. The ones I’ve bought are humongous but smaller versions are also available. The switch we will be focussing on is the switch, as seen below.

Usually, the product’s store page will display a diagram or table explaining how to retrieve the current state. In this instance, they’ve provided a table referencing which pins are connected in each state.

When talking about states I’m refering to the positions as seen on the provided faceplate as seen on the image above
Terminals v Position -> | 0 | 1 | 2 |
1 -> 2 | x | x | |
3 -> 4 | x | ||
5 -> 6 | x | ||
7 -> 8 |
The simplest thing we might conclude is that terminals 7 and 8 aren’t used at all. So we might as well ignore these terminals completely (in this instance, they are also missing pads, but your seller might provide different setups). In the 0 state, no terminals connect. If we wired these terminals up using the internal pull-up resistors of our Arduino, the 0 state would be active when all terminals read as a HIGH signal (or LOW if you use pull-down resistors). In all other instances, the first and second terminals connect. This leaves us with a single check to see if we are in the first state.
//pulup resistors if(digitalRead(pinA) == HIGH){ //The terminals at pinA aren't connected thus we are in state 0 } //If using pull down resistors //if(digitalRead(pinA) == LOW){ //The terminals at pinA aren't connected thus we are in state 0 //}
We could then check whether or not the first state was set by checking if the 1 and 2 terminals are connected. The downside of this would be that in the second state, these terminals are connected as well. We could check if the first terminal is connected and if the third and fifth terminals are connected. But this would lead to unnecessary checks. It will be wiser to check if the third and fourth terminals are connected. We know for a fact that these terminals connect when we are in the second state.
//pulup resistors if(digitalRead(pinC) == LOW){ //The terminals at pinB are connected thus we are in state 2 } //If using pull down resistors //if(digitalRead(pinC) == HIGH){ //The terminals at pinB are connected thus we are in state 2 //}
In theory, we could add a third check to see whether or not we are in the first state. But if we aren’t in state two, and we aren’t in state zero. The only thing that would be left is state 1. So in this instance, a simple else statement would suffice.
//pulup resistors if(digitalRead(pinA) == HIGH){ //The terminals at pinA aren't connected thus we are in state 0 } //If using pull down resistors //if(digitalRead(pinA) == LOW){ //The terminals at pinA aren't connected thus we are in state 0 //} //pulup resistors if(digitalRead(pinC) == LOW){ //The terminals at pinC are connected thus we are in state 2 } //If using pull down resistors //if(digitalRead(pinC) == HIGH){ //The terminals at pinC are connected thus we are in state 2 //} else{ //Everything else has been checked so the only thing that is left is state 1 }
Wiring
These switches are pretty easy to wire up. You could use any pin you desire, but if you want to follow along with my code, I’d recommend using the same pins (if you use different pins, remember to change these pins everywhere in your code). The most effortless setup would be to use the internal pull-up resistors (for a full explanation of this approach, check out my article on pushbuttons).
The resistors will ensure that the signal stays HIGH when the terminals aren’t connected. Once they are connected, the power can flow towards the ground line. Therefore we could wire up all the terminals of either side (all the even or all the uneven terminals) to the same ground line. Whichever side you choose doesn’t matter. The end result will be the same. The other ends connect to three individual pins on your microcontroller. I went with pins 3,4, and 5 for the upper switch while using 6,7, and 8 for the lower switch.

Even though the multiposition switches I’ve used are massive, they behave the same way as a latching pushbutton. That is why I’ve opted to show the diagram above as an illustration.
Events used
In order to send commands to the game, I’ve used three custom commands. These can be added to the event file through the connector which can be downloaded from my downloads page.
6013 | (>L:OVERHEAD_HYD_SELECTOR) | Input with value |
6014 | (>L:OVERHEAD_HYD_SELECTOR_2) | Input with value |
6015 | (>L:LIGHT_TEST, bool) | Input with value |
Code used:
#include <BitsAndDroidsFlightConnector.h> BitsAndDroidsFlightConnector connector = BitsAndDroidsFlightConnector(); enum states { LEFT, UP, RIGHT }; const byte testPin = 53; const byte redLEDs[] = { 8, 9, 10, 11 }; const byte greenLEDs[] = { 12, 51, 50, 52 }; const byte upperSwitch[] = { 3, 4, 5 }; const byte lowerSwitch[] = { 6, 7, 8 }; byte oldLowerState; byte oldUpperState; byte oldTestState; long timer0State = 0; void setup() { Serial.begin(115200); for (auto& pin : redLEDs) { pinMode(pin, OUTPUT); } for (auto& pin : greenLEDs) { pinMode(pin, OUTPUT); } for (auto& pin : upperSwitch) { pinMode(pin, INPUT_PULLUP); } for (auto& pin : lowerSwitch) { pinMode(pin, INPUT_PULLUP); } pinMode(testPin, INPUT_PULLUP); } void loop() { connector.dataHandling(); checkUpperSwitch(); checkLowerSwitch(); checkTestState(); } void checkLowerSwitch() { //My top switch has 4 positions while the lower only has 3 //I'd recommend to buy two 3 position switches to make your life easier. //Pos 0 == all off | pos 1 == 6 connected | pos 2 == 6,7,8 connected byte currentState; //6 is always on unless we are in position 0, this will be our first check if (digitalRead(lowerSwitch[0]) == HIGH && digitalRead(lowerSwitch[1]) == HIGH && digitalRead(lowerSwitch[2]) == HIGH) { //I've added a custom command to the connector with prefix 6013 //0 is the switch state we want to set the ingame switch to currentState = LEFT; } //pin 8 will only be LOW if the switch is in position 2 else if (digitalRead(lowerSwitch[2]) == LOW) { currentState = RIGHT; } //if we checked all these sentences we know for a fact the other state will be 1 //(unless there would be an error in our wiring) else { currentState = UP; } if(currentState != oldLowerState){ Serial.println("6013 " + String(currentState)); oldLowerState = currentState; delay(100); setGreenLightState(); } } //The states differ between 3 and 4 position switches, //that is why I've used 2 functions void checkUpperSwitch() { //I use position 1,2 and 3. They all match 1 on 1 with their states. If they are LOW that position is set. byte currentState; if (digitalRead(upperSwitch[1]) == LOW) { currentState = RIGHT; } else if (digitalRead(upperSwitch[2]) == LOW) { currentState = UP; } else { if(timer0State==0){ timer0State = millis(); } currentState = LEFT; } //Because switchting states adds a gap where all states are HIGH I've added a timer //This filters out the incorrect readings for the 0 state when turning the dial long currentTime = millis(); if(currentState != oldUpperState){ if((currentState == 0 && abs(currentTime - timer0State) > 500) || currentState == 1 || currentState == 2){ timer0State = 0; Serial.println("6012 " + String(currentState)); oldUpperState = currentState; delay(200); setGreenLightState(); } } } void setGreenLightState(){ switch(oldLowerState){ case LEFT:{ digitalWrite(greenLEDs[3], HIGH); digitalWrite(greenLEDs[2], LOW); break; } case UP:{ digitalWrite(greenLEDs[2], HIGH); digitalWrite(greenLEDs[3], HIGH); break; } case RIGHT:{ digitalWrite(greenLEDs[2], HIGH); digitalWrite(greenLEDs[3], LOW); break; } } switch(oldUpperState){ case LEFT:{ digitalWrite(greenLEDs[0], HIGH); digitalWrite(greenLEDs[1], LOW); break; } case UP:{ digitalWrite(greenLEDs[0], HIGH); digitalWrite(greenLEDs[1], HIGH); break; } case RIGHT:{ digitalWrite(greenLEDs[1], HIGH); digitalWrite(greenLEDs[0], LOW); break; } } } void checkTestState(){ byte currentState = digitalRead(testPin); if(currentState != oldTestState){ if(currentState == LOW){ for(auto & led : greenLEDs){ digitalWrite(led, HIGH); } //The red lights are only in when the testSwitch is triggered //This makes it correspond with the ingame trigger without retrieving game data for(auto & led : redLEDs){ digitalWrite(led, HIGH); } Serial.println("6015 1"); } else{ //Make sure to set the lights back to the correct state setGreenLightState(); for(auto & led : redLEDs){ digitalWrite(led, LOW); } Serial.println("6015 0"); } oldTestState = currentState; } }