Beginner's guide to input multiplexers - MobiFlight/MobiFlight-Connector GitHub Wiki

What is the purpose of multiplexers in MobiFlight?

In MobiFlight, multiplexers are currently used as multipliers of digital inputs. In other words, they allow to read up to 16 physical inputs with the expense of a single Arduino pin.

What are multiplexers anyway?

Multiplexers are a sort of “electrically controlled” rotary switches; they have a set of switched terminals (usually 8 or 16), only one of which is connected to a single (common) terminal on the other end.

In order to determine which terminal is connected, a set of selector inputs is provided: the signals on these inputs form a binary code corresponding to the input number. For a 1-to-16 multiplexer (the most common type for our application), the binary code requires 4 bits, therefore there are 4 selector lines.

The selector lines select the channel; they can be seen as the position indicator for our "rotary switch".

It is important to know that:

  • all unselected, switched terminals remain unconnected.
  • Multiplexers have no polarity: all terminals can be both inputs and outputs.
    If the common terminal is an input, then switched terminals are outputs, and vice-versa.

How are they used by MobiFlight?

As mentioned, they are used to connect many physical inputs to a single Arduino pin.
Switched terminals are used as input lines from physical buttons and switches, while the common terminal is connected to an Arduino pin configured as input; of course, the MobiFlight software takes care of driving the selector lines as necessary.

This is currently the only mode supported by MobiFlight, with the additional limit that these inputs can not be used to connect "fast" inputs like encoders (though this limitation will probably be removed in the near future);
however, multiplexers can be used to "multiply" other types of inputs (e.g. analog ones) or devices (e.g. LED or display drivers). If you're interested to know more, please refer to the document Generics about Multiplexers in-MobiFlight.

What are the advantages over other devices, e.g. shift registers?

This application of multiplexers looks similar to the purpose of a shift register - and indeed it is; in fact, in practice they could be considered almost equivalent alternatives.
However, a shift register also seems to require less control lines: 3 pins vs. the 4+1 pins (4 selectors + 1 input) required by a multiplexer. So, what's the deal?

  • First of all, multiplexers have a distinct advantage over shift registers (not mentioning the fact that they're not limited to digital inputs): their inputs can be addressed directly, so groups of them - or individual inputs - can be read more frequently than others, or at request, allowing faster and special inputs to be processed.
    Currently, this advantage is not exploited in Mobiflight, but it will be probably soon, e.g. for encoders.

  • The selector lines can be shared by any number of multiplexers; any added device only requires one more Arduino pin (for the additional input). The Arduino pin occupation can then become comparable (if not better) to that required for an equivalent number of shift register chains. This might become no longer true if shared pins are introduced in MobiFlight also for shift registers and display drivers.

  • Multiplexers are very popular because they are used in a home cockpit system (RealSimControl, formerly named SimVim) as its only means of input expansion; a fairly large number of home cockpits use this system, and a better support of these devices by Mobiflight would offer an alternative with interesting new features (for instance, the native compatibility with several flight simulators, or a higher support for customization).

How do I connect them?

In practice, the most commonly used multiplexer is the 4067 (the exact part number is usually 74HC4067); this is available both as bare component or as breakout board where the component is mounted. The breakout board version is more easily available, cheap and generally convenient; it contains very little more than the component itself, so there is little difference in usage. This is the schematic for a common breakout board:

Schematic

This is how it is connected:

Connection

Data, S0, S1, S2, and S3 can be any available pins on the Arduino; as always, it is recommended to avoid pin D13 (connected to the onboard LED) to prevent malfunction issues.
To add more than one multiplexer module, only one additional pin is required for each (the respective "Data" pin); selector pins S0... S3 are shared between all multiplexer modules.

Currently, there's a limit of 4 multiplexers for the Arduino Mega and RaspberryPi Pico, and 3 for the other Arduinos; however this is mostly an arbitrary limit that can be easily increased (and will likely be soon).

Some important notes:

  • There is no such thing as a "daisy chain", or series, connection for multiplexers: rather, they are connected in parallel, sharing the four selector lines and using just one more reserved pin each for their output (i.e. Arduino input).
  • As inputs, multiplexers draw very little current; their power supply (5V and GND terminals) can therefore be connected directly to the Arduino board.
  • The EN terminal must be connected to GND (directly or through a resistor) for the device to be enabled.
    On breakout boards, a 10k resistor is already mounted for this purpose, but keep it in mind if you happen to be using the "naked" component.
  • Since the buttons, switches or other input controls work by short-circuiting the respective input to GND, the corresponding Arduino input (in this case, the common terminal of the multiplexer) requires a pull-up resistor.
    This is already integrated in the Arduino board (and activated by MobiFlight); however, for (electrically) noisy environments or long connection wires, it can be useful to connect an additional pull-up resistor ("R" in the picture). This can be soldered directly on the board pads.
  • Multiplexers also handle "push-pull" inputs (even mixed with the "regular" ones), i.e. inputs that do not short to GND but supply a voltage both for the high and the low level (like outputs of logic ICs or e.g. other Arduinos). However, inputs that only supply a voltage for the high level but are disconnected for the low level cannot be mixed.

Inputs

Finally, this is how a multiplexer input module should be configured: the labels in the pin selection boxes correspond to the connections picture above.

Panel1b

Remember that, if there is more than one multiplexer, the selector lines are in common: therefore, while the S0..S3 pins appear in the panel of every multiplexer (for reference), they can only be modified in the panel of the first one. A button, highlighted in the picture, will take you there quickly; changes will automatically be reflected in the other panels.

Panel2b

v1.0 - 2023-03 by Giorgio Croci Candiani (@GioCC) for Mobiflight