My 737 I/O Controller PCB has arrived!

Well to be honest, this is not the first time it has "arrived". But this is the first time that a version of the PCB has arrived which is usable, due to some earlier bugs! 8-)

As i noted in my earlier post, here are the specifications:

  • 192 digital switch inputs (expandable to 256)
  • 128 constant current LED outputs, up to 60 mA per channel (expandable to 224)
  • 48 digits of 7-segment numeric displays
  • 8 characters of 14-segment alphanumeric displays
  • 16 servo outputs, 12-bit resolution
  • 8 analog inputs, 12-bit resolution
  • 24 interrupt-driven GPIO pins for rotary encoders
  • Powered by a Raspberry Pi Zero W
The design files for the PCB can be found here. You can download a Gerber file for the PCB, and submit it to a PCB manufacturer who can fabricate it for you (The article for my "737 FMC CDU - Ordering the PCB" is a useful guide on how to do this). The PCB costs me USD27 (for 5 pics, i.e. USD5.40 each), plus extra for shipping.

For the moment I don't recommend downloading the Gerber files and ordering a set of PCBs yet. Please wait until I finish testing it properly and have the software going. I will update this paragraph when it's ready.

I've licensed the design of the PCB under the Creative Commons CC-BY-NC-SA 4.0 license. Please read the terms of the license here if you wish to make use of the design in any way. In general, I've made the design freely available, there is no warranty provided, and so you are on your own with regards to problems and liabilities. Please retain any attribution, whether you use it as-is or derive a modified work from it. You agree to license any derivative works within the same terms as the original. And finally, the design is not to be used for any commercial venture (with the exception that if you have any extra unused boards, you may give them away for free or for a cost not exceeding the production cost (USD5), excluding shipping, and that you inform any potential recipients of the licensing terms and also where they may get the original design).

Right, now that is out of the way, we can proceed with the build notes.
Some Thoughts on the Board Design

Below I've noted some the reasons why I designed the board the way I did. If you just want to build one, you can probably skip this section.

737 Overhead I/O Board Block Diagram

The board has been designed as an all-in-one unit, with everything you need to interface a 737 overhead panel to X-Plane. The idea here is that all the switches, annunciators and gauges will be wired directly to this board. I've received many different opinions on this, some agreeing and some disagreeing. The other way of doing this is to distribute the electronics around, making each panel of the overhead removable and autonomous and maintainable, as with the original 737 cockpit. I think which is the best depends not so much on the design but rather what you're own strengths and weaknesses are. For me, this design forces me to finish the overhead panel once and for all before mounting it up.

At the heart of the board, I have opted to use a Raspberry Pi Zero W. Again, there are many different opinions here, with many suggesting to use one or more Arduinos. What can I say, I am more of a software than hardware person, all this hardware tinkering is just a means to an end in my case!

I have also opted to go with through-hole components, as I believe there are more people interested in this board who know how to through-hole solder as opposed tosoldering surface mount components. Where some of the ICs needed are not available as through-hole components, I have used the "module" version of these ICs.

The entire overhead panel requires more I/O pins than a Raspberry Pi (or a single Arduino) has. To provide more I/O capabilities, I have used the MCP23017 GPIO Expander. These are cheap and readily available, and use the I2C bus to connect to the Raspberry Pi. I like the I2C interface a lot, as not only does it just require two wires (SDA and SCL) that are shared throughout the PCB, making the wiring layout easier, but it can also detect what devices are present easily. Each MCP23017 provides an additional 16 GPIO pins that the Raspberry Pi can make use of. The PCB makes use of a total of 5 MCP23017s.

I run the I2C bus components on 5V. I used 5V because I did not want to overtax the Raspberry Pi's 3.3V power supply, which is used to drive its CPU, from which only 50mA is available. Now, the Raspberry Pi's I2C bus is actually working on 3.3V and must never be fed with 5V, so why am I connecting components running at 5V to it? For I2C this is fine, as the slave components on the I2C bus signal the master by pulling the line down to ground. It is the raspberry Pi that pulls the line up to 3.3V via an internal pull-up resistor. Therefore the slave components on the bus will never cause the I2C bus to be raised to 5V.

2 out of 5 MCP23017s are use for the matrix digital input, with one serving as the "Columns/Input" and the other for the "Rows/Outputs", to give you 256 switch inputs (16x16). I dedicated entire MCP23017s as it is efficient to read all 16 input bits in a single I2C instruction. However, I've placed only 192 physical switch inputs on the board, as I felt that this was sufficient for an overhead panel. There is a connector where a daughterboard can be added to provide the additional 64 pins if needed.

For the Annunciators, I have used the DM13A Constant Current LED Driver chip. These are easily available on eBay, although not through mainstream suppliers such as Element14/Farnell, RS, Mouser or Digikey. I think it is because they are made only by a Taiwanese company. I believe they are compatible with other similar drivers which are only available as Surface-Mount-Technology (SMT) ICs. Anyway, if you are building this PCB, do order these early via eBay, as it can take around 3 weeks to arrive.

Each DM13A allows you to control 16 sets of LEDs, and I have placed 8 DM13A ICs on the board, allowing for up to 128 Annunciators. Each Annunciator on the DM13A can sink up to 60mA of current, which means you can probably get away with running 3 LEDs per annunciator. The current (brightness of the LEDs) per pin is controlled by a single trimmer potentiometer for each IC, so you can play around with different current levels by connecting LEDs to different ICs.

The DM13A requires a Enable, Data, Clock, and Latch signal to drive it. It is also possible to daisy chain multiple DM13As together, to reduce the control lines required, at the cost of longer instructions. I've made the Enable and Data signal common through all DM13As on the PCB, and grouped the DM13As into chains of 2, with each chain requiring a dedicated Clock and Latch signal. This means he total required for 8 DM13A chips are (2 + (8/2 * 2)) = 10 GPIO Pins. These are served by a dedicated MCP23017 IC. The extra unused GPIOs are made available on a connector, so that it is possible to add additional annunciator ports on a daughterboard.

There are two types of segment displays supported, numeric (7-segment) and alphanumeric (14-segment). These are used to set Pressurization altitudes, for the AC/DC Metering Panel, and for the IRS panel.

For the numeric segment displays, I have used 6 of the popular MAX7219CNG ICs. Like the DM13A, these require a Data, Clock and Latch signal on each IC. I've used a shared Data signal for all 6 MAX7219CNG ICs. Like the DM13A, MAX7219CNG ICs can also be daisychained, so I've grouped them into pairs of 2. This means a total of 1+(6/2 * 2) = 7 GPIOs are used for the numeric segment displays are used for the numeric segment displays.

The remaining GPIO pins, together with those from another MCP23017, (a total of 24 GPIO pins) are left available for connecting Rotary Encoders (used to set Flight altitude and Landing altitude). Rotary Encoders provide two signals (A and B), and the direction of rotation is determined by the sequence in which the signals are tripped. Therefore, we require precise timing on when the A and B inputs are triggered. For this I have chosen to wire them directly to MCP23017s. The MCP23017 used for this has an Interrupt signal which is linked directly back to the Raspberry Pi's GPIO pins. Whenever the MCP23017 detects a change of state in the pins connected to it, it will signal the Raspberry Pi, which will then signal the running software. Because the MCP23017 runs at 5V and the Raspberry Pi's GPIO pins run at 3.3V, a 1.5K and 1K ohm resistor acts as a voltage divider for this signal.

The Alphanumeric segment displays are driven by a HT16K33 module. This connects directly to the I2C bus, and allows the connection of up to 8 14-segment common cathode alphanumeric segment displays.

To drive servos, I used the PCA9685 module. The PCA9685 is only available as a surface-mount component, so using a pre-build module allows us to avoid having to deal with surface mount soldering. The PCA9685 module lets you drive up to 16 servos, and is controlled from the Raspberry Pi directly via the I2C bus. The module has its own connector pins for servo cables.

There is also an analogue to digital coverter (ADC) in form of a MCP3208 IC. This is a 8-channel 12-bit IC, and connects to the Raspberry Pi via SPI (running at 3.3V). I've created 3-way header pins for each channel consisting on 3V3, Analogue In (AIN), and GND. This allows you to easily connect and read the value of any potentiometer (10KΩ recommended). There isn't much use for this on an overhead panel, except perhaps for the air-conditioning temperature controls. You can leave this IC out if you are not planning to use analogue inputs.

Because the Raspberry Pi will run without a display, I've added some user interface components in the form of a power LED (LED1), a GPIO controllable yellow LED (LED2), a buzzer (leave this out if you want absolute silence!), and two microswitch inputs. These let you interact with the Raspberry Pi to know what the current status is and also to give it rudimentary commands such as to initiate a shutdown. I'll think deeper on how I will make use if these when I work on the software.

The entire PCB is powered by a 5V input, supplied via the PWR IN connector (you do not need to connect a power input for the Raspberry Pi, it is powered through the I/O Controller PCB). Just the Pi and components on the board alone consume around 140mA at 5V. There is also a separate power input for powering the servos. This is because servos usually create a spike in current when they start moving or are blocked and this transient can cause the Pi to hang or reboot. On my production system I use two AC to 5VDC 5A power supplies. Having said that, on my development setup I used a 5V 10A power supply connected to both PWR IN and PWM IN, and did not have any problems. It's not so much about the amps but the ability of the power supply to regulate through the transients.

Bill Of Materials

Here's a list of everything you'll need to assemble the I/O Controller, with rough pricing and source.
You'll need the following tools:
  • (Preferably temperature regulated) Soldering Iron + Solder + Solder Flux Paste
  • IC Puller
  • Small-nosed Pliers
  • Micro Screw drivers
  • USB MicroSD card reader
  • USB Keyboard + USB OTG Cable (optional)
  • HDMI Monitor + Mini-HDMI to HDMI Adapter (optional)

Soldering Work

As with all soldering work, start with the shorter components and work your way to the taller ones. This way you can have the components being soldered flush with the table top when the board is flipped over and you are soldering their legs.

Some of the headers are meant for connecting additional daughterboards or for debugging, and are not currently needed. These are P13, P84, P29, P81 and P82. I also left out P27 and P28, for reasons I will explain in a future post. You can leave them unpopulated. You might also want to cover them with black electrical tape to prevent accidentally making contact with them.

For the 2x16 and 2x4 headers, you can either use naked male header pins, or shrouded "IDC" ones. I used naked male header pins, but the shrouded IDC ones are better if you are using ribbon cables with IDC connectors, as it ensures the cables can only be connected the right way around. When soldering these, make sure the "notch" of the shroud is on the same side as pin 1 (identified with a round circle).

Here's what my board looks like when soldered and populated:


I plan to locate the I/OController Board on my overhead panel itself. To avoid any damage or short circuits to it, I found a suitable enclosure for it -- at my local stationary shop! I purchased an A4 (I guess US Letter will be fine too) Document Case, measuring 310x240x40 mm.

I made holes for mounting the PCB, and used 4 M3x30 bolts. I used two nuts on the inside to raise the PCB to a suitable level.

And the I/O Controller fits nicely within it. I shifted it to one side a little so that I could connect cables to the Pi's USB and HDMI connectors without the case interfering (although for normal operations these ports will remain empty). I plan to make some holes for the input power cables, as well as the cables leading to the components on the overhead panel later.

In my next post I will discuss setting up the software and also how to wire up the components to the I/O Controller.