Introduction: Boeing 737NG Lights Overhead Panel for FSX
I decided to start this project for my 18yo son, addicted to flying and airplanes (ok, I influenced him a bit...). He knows my passion for electronics and Arduino, so he asked me to create a Boeing 737 panel for his MS Flight Simulator X, his first choice was overhead lights and engine starters. It is a relatively simple panel compared with others, as made up of switches, but I accepted the challenge and try to make it as similar as possible to the original, and interface it to Arduino and then to FSX. Obviously the goal was to use cheap components: there are already many good panels for FSX in the market but they are pretty expensive, especially the most realistic ones.
But the challenge to design and build something from scratch is priceless...
Current project aims to reproduce 737NG panel and its controls on FSX, but you can change it a bit to any other aircraft model/type.
My next project will be the 737 MCP (autopilot), but it's pretty complex (it includes 7-segment displays, rotary encoders, backighted pushbuttons, etc...) and it will take me more time...
Step 1: Project Start
It all started with a sketch made by hand over a paper sheet. The panel has a trapezoidal shape, and after a quick Google search to find the size of the real panel, I started to design a slightly smaller version to make it easier to handle. To create base frame I chose wood strips, while for the front panel the solution I decided to realize was two plexiglass sheets with a simple printed paper sheet between them.
Given that it is an "overhead" panel, it should be placed above the monitor so in my project I simply used a wooden plate to be placed on a shelf (perhaps under some book to keep it steady, or screwed with a couple of bolts if you can make holes in the shelf), and the panel tilted down 45 degrees to simulate plane ceiling. Obviously, the choice of where/how you'll position the panel will change the shape of the support: make the choice that best suits your needs. Here we area to the materials used in the project:
- 1 x wooden slat 2mt long 4x1.5cm
- 1 x plexiglass sheet 50x25cm, 2mm thickness
- 1 x Arduino Nano v3 ATMega328
- 9 x ON-OFF or ON-ON 1-way lever switches
- 5 x ON-OFF-ON 1-way lever switches
- 2 x rotary switches, 12 positions 1 way
- 2 x knobs for rotary switches (grey or cream)
- 1 x mini breadboard or perfboard
- 2 x pin headers 12-pin male
- USB cable, wires, wood glue, wood screws
- various tools: cutter, ruler, drill, iron drill bits...
First of all I made a drawing of the panel, with all its labels:
Because it seems that the font used in 737 panels is reserved and owned by Boeing only (sic), I chose a similar font. I chose my panel width (50 centimeters) to be the same of small sizes plexiglass panels I found.
Step 2: Wooden Frame
First of all, check the size of the pieces to be cut from the wooden slat:
- 1 x 50 cm for the upper crossbar
- 1 x 28 cm for the lower crossbar
- 2 x 5 cm for the two vertical reinforcing uprights
- 2 x 11 cm for the lower diagonal sections
- 2 x 2 cm side blocks
Before assembling the frame, print the panel faceplate. Since it is larger than an A4 sheet, I divided it into three parts (see file "B737lights_OH.zip", where you can find full size PNG pictures, ready to be printed) which I then cut and joined with adhesive tape on the back to form a single 50cm wide mask. Then manually assemble the wooden pieces on a table, and place the paper mask to check the size and positioning.
When everything is ok, first of all mark the position of the two vertical 5 cm uprights, paying attention not to make them overlap any of the switches. During the design I have also made a diagram of the "internal" parts (you can see its picture above) including uprights, to precisely determine their position. Using some glue assemble top and bottom crosbars with the two uprights and press together for a few minutes, then use 4 wood screws to definitely fix them. Other two wood screws are used to fix the two side blocks, then with hot glue fix the lower diagonal sections and you're done.
At the end check again if the paper mask fits properly with the wood frame.
Attachments
Step 3: Plexiglass Panel: How to Cut and Drill It
Now we have our wooden frame and the mask as a reference, so we can get on with plexiglass panel.
This is undoubtedly the most delicate phase. Without removing the protective film on the sheet of plexiglass, draw with a pencil or marker twice the mask shape, forming the two transparent sides which will contain the printed mask. I suggest to make use of the two upper and lower plexiglass sheet edges as the widest part of the panel (the one corresponding to the 50 cm crossbar, the same as the sheet width). Remember that plexiglass is very delicate, even though with the protective film, so take care not to scratch it or bend it during processing. By the way, a sheet of 50x25 sheet at a DIY department store is quite cheap, less than 3 Euros.
To cut the plexiglass you can use special saws, but the easiest thing in case of simple linear cuts over thin sheets is to break it: using just a metal ruler (or a straight strip of wood) and a cutter. Position the ruler over a line then start carefully marking with the cutterthe entire width of the slab. Repeat the process with patience and precision at least ten times, to engrave it deeper and deeper: do not use excessive force to avoid breaking the plexiglass. Do the same on the opposite side, then place it on the edge of a table and with one hand press the ruler along the edge, with the other hand gently bend the sheet of plexiglass: if you did everything correctly, it will simply break exactly along the incision. Now you will get a rectangle of 50cm to 8cm. Repeat for the other plate 50x8. Do the same to make the triangular bottom cuts. In this case the operation will be a little more critical because of the angle: if the cut is not be perfect, use the cutter to trim it.
Now you have the two plexiglass panels ready for drilling. Using a battery drill set to low speed with iron drill bit. Make the first pilot holes of each switch using a little drill bit (eg. 2.5 or 3 mm), following the marks on the mask. Like cutting, drilling plexiglass is not difficult but it is critical, it takes no time to form a very bad crack so use LOW SPEED rotation, and DON'T PUSH too much, be light like a butterfly! You need to have patience especially when the drill is coming out from the back.
I suggest you keep both sheets one over the other, with paper mask inside, all lined up on the wooden frame and start making the screw holes: this way you can insert the screws and proceed to drill the two panels at the same time making holes always perfectly aligned.
If a plexiglass sheet shown some cracks around a hole do not worry, it will be the inner panel so you will not see the cracks.
Once you made all the pilot holes, switch to a bigger drill, depending on the size of your switches. In my case the 6mm one was perfect. After the first hole try a switch into it before continuing with others, to check hole size.
Rotary switches require a bigger drill, in my case was a 10mm but I recommend you to make a hole with the 6mm drill before.
Step 4: Assemble the Switches
Now we have the frame and the panel, we need to plan the connections.
Attached there is an Excel file ("Connessioni Lights.xlsx") with the list of all switch names (in sequence from left to right), the switch type (ON-ON, ON-OFF-ON, and Rotary), the wire color/number (you'll need to edit this column to suit your wires). Just for now, ignore the rightmost columns as they are the FSX codes, you'll need them later.
I decided to set all Arduino digital inputs with internal pullup to avoid using external resistors: this means that we will read HIGH (+5V) if the pin is NOT connected, and LOW (0V or GND) when we trigger switch, bringing the pin to ground. All ON-ON (or ON-OFF) switches are connected to ground on one side, and the central goes directly to Arduino digital pin. This way when the switch is in "OFF" position we will read HIGH (or "1") value, while in the "ON" position it will be connected to ground and then we will read LOW (or "0").
To reduce the number of needed input pins, for each ON-OFF-ON switches and the two rotary switches I used one analog input thanks to resistive dividers which will give different voltage values depending on the position of the switch (see figures). This way we only need 7 analog pins, instead of 18! And Arduino Nano can fit the project better than UNO, thanks to its 8 analog inputs, two more than UNO.
The panel is internally divided into three sections delimited by the two uprights, so better wire switches in three separate groups. Each wire is then welded to a pin of one of the two headers, corresponding to Arduino pins, see the scheme in the Excel spreadsheet.
Attachments
Step 5: Edit the Program and Link2FS Configuration
Load Arduino IDE and open the program FSX737LightsPanel.ino you find linked to this step.
The code is set for the use of PMDG 737NGX aircraft, so if you intend to use it no changes are required, but in any case I describe in this step the entire configuration to let you better understand the way it works. If you want to use it with any other aircraft you probably need to customize the codes sent to Link2FS and this to FSX. First of all, open the Excel file that you downloaded from the previous step ("Connessioni Lights.xlsx"), and look at the columns labeled Code, Cmd, and the four "SimConnect".
- - "Code" contains the FSX event code corresponding to the command (e.g. Event #69749 corresponds to the lights for taxing).
- - "Cmd" contains the code that Arduino sends to Link2FS
- - 4 SimConnect columns are the additional parameter to Cmd, to give FSX the switch status
For example, Taxi lights Cmd is "Y09", so the command sent to Link2FS will be "Y091" to turn them "on" or "Y090" to switch them off, or if I have motor switch 1 in position 3 (FLT) the command is "Y063".
Link2FS will interpret such command+state and sends to FSX the corresponding event code, followed by the state.
This means that if your plane has specific custom codes different from 737NGX ones, you need to find the corresponding event codes and insert them in the "Code" column, then program Link2FS to associate one of the "Yxx" in the "Inputs SimConnect" screen under tab "Expert", and write them down on the sheet on corresponding "Yxx" command. In the attached "SimConnectExpert.png" you can see current settings of Link2FS for 737NGX, corresponding to commands from the Excel spreadsheet.
Finally, you must set up the codes in the following three lines of code:
- S1Cmd String [] = {"Y07", "Y08", "Y03", "Y04", "Y09", "Y10", "Y11", "Y12", "Y16"};
- S3Cmd String [] = {"Y01", "Y02", "Y05", "Y14", "Y13"};
- R4Cmd String [] = {"Y06", "Y15"};
These rows correspond to the three types of switches (see TYPE column on the Excel spreadsheet): the first is related to ON-ON (2 positions) switches, the second to ON-OFF-ON (3-positions) ones, and the third to the two rotary 4-positions switches.
The order is from left to right while looking the front panel (see numbering reference in the Excel spreadsheet).
If you use the 737NGX you only need to set the codes shown in the "SimConnectExpert.png" picture, or directly copy "expertsettings.ini" file under Link2FS Expert directory, making sure Link2FS is not running.
Step 6: Configure Link2FS And... Fly!
Now we simply need to plug our Arduino Nano, check cables and connections, install Arduino USB serial drivers if needed, connect USB cable and upload Arduino sketch.
Now run FSX, run Link2FS, and... HAPPY FLYING!
PS: For any question or problem, use comments or PM. Thanks!
36 Comments
3 years ago
Hi everyone, could you plaise tell me witch CUR values should I put in the code below to get 7 rotary positions with one analog pin?
// ------------------------------------------------------
int Analog2Rotary(int cur) {
if (cur < 200) // Posizione 0 (STBY PWR)
return 0;
else if (cur < 500) // Posizione 1 (BAT BUS)
return 1;
else if (cur < 900) // Posizione 2 (BAT)
return 2;
else if (cur < ???) // Posizione 3 (TR1)
return 3;
else if (cur < ???) // Posizione 4 (TR2T)
return 4;
else if (cur < ???) // Posizione 5 (TR3)
return 5;
else if (cur < ???) // Posizione 6 (TEST)
return 5;
else // Posizione 7 (FLT)
return 7;
}
Reply 3 years ago
First of all, I suppose you used the same scheme I used for my 4-positions rotary switch: for your case, 6 identical resistors connected between adjacent pins, to form a resistive divider. The corresponding values can be found by using a simple sketch that reads the analog value, like:
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println(analogRead(A0));
delay(500); // twice a second
}
In theory, that means you will read 0 for the first position (connected to GND), then there are steps for 1/6 of the range equal to around 170 each (depending on the resistors precision), so: 0, 170, 340, etc. by adding 170 for each step.
The values to be used on that function can then be the "middle point" of each interval starting from 170/2=85, and going on by adding 170. The first if() will be "if( cur<85 )" then cur<255, cur<425, and so on.
Reply 3 years ago
Hi Palms, sorry for the late replay i tried the cur values as advised withe addeding ( cur<85 ) for each interval and it works very well :-) thank you so much for your support.
Question 3 years ago
Just want to confirm - is this for the iFly 737NG addon aircraft? We're trying to build this and configure it for the stock 737 in FSX but running into some issues with the simconnect event codes as displayed above which seem to not activate any functionality. The # numbers I am assuming are custom simconnect event codes for the 737NG - is that correct?
Reply 3 years ago
The panel and all interface configuration are for 737NG from PMDG (737 NGX) addon. You can try other planes I suppose, but you need to find out specific ways to send the correct event codes, even for stock 737 planes.
I'm sorry, I don't know how to help you more than that.
5 years ago
Does anyone know how to connect the seat belt and no smoking sign to link2fs? I see where I can get the status, but can't set it. Awesome project, I am working on one myself.
5 years ago
Hi I'm building a 737 NGX overhead and I used the 25 line in simconnect inputs Experts what can i do to add more than 25 input helpe me plz thx
Reply 5 years ago
Because you used all your Y commands the Z commands at the control page are still not used. You can use the Controls page and use the Z... Instead of the Y. You only have to change or add the code to Z01 for example. Also you need fsuipc otherwise it is not gonna work. but that is not a problem. Change the pin numbers and a few other things.
// On-off switch Digital test pin
int S1Pin[] = { 2, 3, 4, 5, 6, 7, 8, 9, 10 }; <----CHANGE / ADD
int S1Old[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1 }; <----- ADD
String S1Cmd[] = { "Y07", "Y08", "Y03", "Y04", "Y09", "Y10", "Y11", "Y12", "Y16" }; <----- CHANGE / ADD
// On-off-on switch test Analog pin
int S3Pin[] = { 0, 1, 2, 4, 6 }; <----- CHANGE / ADD
int S3Old[] = { -1, -1, -1, -1, -1 }; <----- ADD
String S3Cmd[] = { "Y01", "Y02", "Y05", "Y14", "Y13" }; <--- CHANGE / ADD
// Rotary switch test Analog pin
int R4Pin[] = { 3, 5 }; <----- CHANGE / ADD
int R4Old[] = { -1, -1 }; <--- ADD
String R4Cmd[] = { "Y06", "Y15" }; <---- CHANGE / ADD
int CodeIn;// used on all serial reads
void setup()
{
for (int KoutPin = 2; KoutPin < 13; KoutPin++)// Get all the pins ready for simconnect codes and "Keys"(all inputs) <---- CHANGE IF NECESSARY
{
pinMode(KoutPin, INPUT_PULLUP);
digitalWrite(KoutPin, HIGH);
}
Serial.begin(115200);
}
void loop() {
int i;
for ( i=0; i<=8; ++i) <---- CHANGE IF NECESSARY
checkOnOff(i);
for ( i=0; i<=4; ++i) <---- CHANGE IF NECESSARY
checkOnOffOn(i);
for ( i=0; i<=1; ++i) <---- CHANGE IF NECESSARY
checkRotary(i);
} // end of void loop (The main one)
5 years ago
Hello,
Me again! Sorry. I started building a complete overhead but with my second arduino a Arduino Mega. I have connected 13 On-Off switches now but when I install more, I get a rapid switch signals.
for ( i=0; i<=13; ++i) <--- When I change that to 14 or higher I get a Also two orange lights that are all the time on but when I change it back to 13 or lower I get 1 solid orange light and 1 blicking orange light.
checkOnOff(i);
for ( i=0; i<=0; ++i)
checkOnOffOn(i);
for ( i=0; i<=0; ++i)
checkRotary(i);
Plz Help me !!
Reply 5 years ago
Firstly, the for() should go from 0 to 12, not 13 (like your previous message, saying to cycle from 0 to 9 instead of 0 to 8): if you have 13 switches, the indexes must go from 0 to 12 (i.e. 13 elements). Any C programmer should know that.. ;-)
If you don't have any OnOffOn and Rotary, you must remove the two subsequent for()s (and the related functions called there), and NOT put a cycle from 0 to 0 (meaning you still have ONE call to that functions!)
Anyway, if you want me to give a try, please send me a PM with the complete sketch.
5 years ago
Hello,
I would like to know what I need to do/ know when I want to use more than 9 on-off (on-on). I started to make a complete overhead and I am using a mega but I installed the 10th on-off(on-on) switch and the arduino gives no signal to link2fs. I just add some new numbers plus the others stuff ( I am using Z01, ZO2...Etc.).
Thx,
Stijn.W
Reply 5 years ago
I can't get what you mean with "the arduino gives no signal to link2fs". The interface is a three-step process: 1) Arduino detects a change in a switch or other control and writes the corresponding code via serial/USB, 2) Link2FS receives the code and sends to FSX the associated command, 3) FSX receives the command and does what corresponds to such command.
So, what happens when you implement the 10th switch? If you simply monitor serial outputs from Arduino (i.e. opening the COM with a Serial Monitor), do you see the command or not? If not, you need to check the cabling and/or the code. If the right command comes out from serial, then you should check link2fs settings and logs to be able to understand why it either doesn't recognise it, or doesn't send the FSX code, or if the code is right for FSX.
Reply 5 years ago
Thx,
I checked the code and I saw a tiny mistake :-).
Before:
void loop() {
int i;
for ( i=0; i<=8; ++i)
checkOnOff(i);
for ( i=0; i<=4; ++i)
checkOnOffOn(i);
for ( i=0; i<=1; ++i)
checkRotary(i);
}
After:
void loop() {
int i;
for ( i=0; i<=9; ++i)
checkOnOff(i);
for ( i=0; i<=4; ++i)
checkOnOffOn(i);
for ( i=0; i<=1; ++i)
checkRotary(i);
}
Every time I add a switch I need to change it!
6 years ago
Second question,
how can I use the others analog and digital pin. when I add a extra switch than nothing happens?
6 years ago
Hello,
After using the panel I wanted to maybe upgrade the panel to make the engine start switches return to the off position when the engine is started. But I don't know which code I have to add to my arduino sketch and I don't know how to set it up in link2fs. Is it even possible? When the answer is yes I really would like to know which code and how.....
greetings from me
6 years ago
Hello again. I have sorted out all of the other problems that I was having but now when I try to use Link2FS I am unable to define what the switch toggle means? Does anyone have any suggestions on how to define what the switch does in the code?
Thanks in advance.
6 years ago
Hi. I am currently building this and I am wondering where to put the second wire for the switch (to complete the circuit). I have tried a few things but none of them have worked. I have the UNO R3 board. If possible can you please include a picture of how you wired it up?
Thanks
Reply 6 years ago
I already answered to your next question ("GND"), but if you are using UNO instead of Nano be aware you can't connect all switches as described, because UNO has 7 Analog ones, while Nano has 8!
Reply 6 years ago
Oh ok. Is their anything that I need to do to make it work becuase I'm having trouble getting link2FS to recognize the inputs from the switches.
6 years ago
Thnx Palms,
I maybe wanna build a complete overhead :-). Do you have any kind of tips and tricks?