OpenTx - Key Concepts

Mike Shellim 25 July 2014
Updated: 22 Nov 2016

Introduction

OpenTx is a uniquely capable operating system, however pilots coming from mainstream brands may find the way of working a little unfamiliar. My aim with this article is to banish some of the mystery, and to enable users to design their own setups with confidence.

I'll cover the following topics:

Background

If you're familiar with Futaba, Spektrum and similar, OpenTx may appear a little, well, basic. There are no high-level menus to hold your hand, and no special mixers - mixers in OpenTx are simple generic constructs.

Paradoxically, this sparseness makes OpenTx both supremely flexible and easy to adjust. It can also enable setups of great functionality and elegance.

However, in order to use OpenTx effectively it's necessary to understand a few key concepts.

OpenTx: an overview of processing

The core of OpenTx is the processing loop which is executed several times a second. With each cycle, the positions of all the controls are read, any mixing is applied, and channel outputs calculated:

Starting point: Sources

The input data for the processing loop are the transmitter controls, telemetry streams and Lua scripts. A generic term for these is 'sources'. For this introduction I'll focus on the raw sources - the sticks, sliders and knobs that you move with your fingers.

Each raw source has a fixed identifier assigned by OpenTx. For example the elevator stick is 'Ele', the switch SA is 'SA' and so on.

At the start of each processing loop, OpenTx reads the position of raw source, and assigns a value to the source; +/-100 correspond to the end points, with 0 for centre. For example:

'MAX' is another source which I'll briefly mention here, although it doesn't correspond to a physical control. Instead, MAX supplies a fixed value of +100. It's typically used to simulate the effect of a fixed stick position.

Channels (OUTPUTS menu)

The Taranis can command up to 32 independent channels. The lowest numbered channels will be normally be assigned to devices such as servos, ESCs, flight controller etc. A channel which is not assigned to any device may be left unused, or used as a virtual channel.

Channels are managed in the OUTPUTS menu. For each channel, you can assign an arbitrary name, set the direction, and adjust the centre and absolute limits of the output.

Here's a view of the OUTPUTS menu showing the channel assignment for a 3-channel 'RES' sailplane. I've named the channels 'Rudder', 'Elev' and 'Spoilr' to describe their function:

Note that this menu doesn't say anything about how each channel is driven - or even that it's driven at all! For that, we need to define some mixers...

Mixers (MIXER menu)

Mixers are the wiring between the sources and the channels; they define which channels should respond when you move the sticks/sliders. And how they should respond.

Mixers in OpenTx are simple primitives; a single generic menu is used to edit all mixers. When you can program one, you know how to program them all!

Here's a simple definition:

It follows that in order to drive a servo, a channel must have at least one mixer.

Mixer notation

In the text which follows, I'll use two forms to describe a mix:

The two forms are interchangeble.

Three mixing scenarios

Okay, so let's see how the mixers can be used. First, consider three scenarios which an RC system should support:

In the following sections I'll how each scenario can be implemented using OpenTx's simple mixing model.

Mix scenario 1: One-source -> one-channel

Example: a single channel model with rudder-only control.

There is just one interaction involved, and it can be written as:

When creating the mix, the alternative notation is more useful:

Here's a screen grab of the MIXER menu showing our single mix:

 

Mix scenario 2: One-source to many-channels

In this scenario, a single source drives multiple channels.

Example: the aileron stick driving left and right aileron channels.
Using the 'source->channel' notation we have:

To convert to mixer definitions we simply reverse each line:

This is how it looks in the mixer screen. Note channels 1 and 2 reference the same 'Ail' source.

Note: this is more flexible than a Y-lead, as each channel can be adjusted independently for centre, rotation and travel.

Mix scenario 3: Many-sources to one-channel

In this scenario, several sources drive a single channel.

Example: the flap channel on a sailplane may be driven by a combination of three controls:

Throttle stick (spoiler) )
LS (flap) ) => right flap servo (CH4)
Aileron stick )


The interactions can be written as:

And the MIXER screen looks like this:

Note the '+' sign at the start of the 2nd and 3rd mixes, showing that their contributions to the channel output are additive.

Designing complex mixing schemes

While the mixing for simple models is often easy to identify, more complex models demand a more formal technique. The method I have used for many years, both with OpenTx and the Multiplex 4000, involves five simple stages:

Example: setup for a simple flying wing

We'll use a flying wing as an example. A flying wing has two elevons for combined pitch and roll control. Although quite simple, it illustrates both the many-to-one and one-to-many scenarios in a previous section.

Step 1. List raw sources

The first step is to list all the controls required to fly the model.

Flying wing example: The raw sources for our flying wing are:

Note that the trims are included by default, so there is no need to list these separately. You can also ignore switches, flight modes etc.

Step 2. List servo channels

The second step is to assign servo channel numbers. These correspond to the numbered outputs which you'll use in the receiver. You can enter these directly into the OUTPUTS menu.

Flying wing example: We'll use channels 1 and 2:

Step 3. Identify interactions

In this key step, we identify every possible interaction between the sources and channels identified above. Here's the procedure:

It's important to model all the interactions in this step. Later you can selectively disable particular mixes depending on a switch position and/or active flight mode.

Note that we're not interested in how the channels are affected, just the fact that the interactions exist.

Flying wing example:
The first source in the list is the aileron stick (Ail). As it's displaced, both elevons should move. The interactions are as follows:

Same for the elevator stick (Ele):

Step 4: Convert interactions into mixer definitions

Next, swap the left and right sides of each interaction so that they read as "channel is affected by source".

Flying wing example:

Step 5: Reorder interactions by channel number

Finally, re-order the mixer definitions so that they're grouped by channel (because mixer lines are ordered by channel in the Mixers menu).

Flying wing example:

Step 6: Enter definitions into the Mixers menu

Once in this form the interactions can be entered directly the MIXERS menu:

The same design approach can be applied to very complex setups. If you're familiar with F3X sailplanes, you may wish to look at interactions and mixes for F3X sailplanes.

Note: while the mixing scheme produced by this method will work fine, more complex setups will invariably benefit from some optimisation using Inputs (described later in this article), GVARs and high mixes.

Setting mixer rates

So far we've said nothing about control surface movements. In OpenTx, the slightly confusing term for these is 'rates'.

To set the rates, we use our knowledge of the model's flying characteristics. On a flying wing, the elevons must be more sensitive (i.e. move further) in response to aileron commands. In other words, the aileron has a higher rate compared with elevator.

Using our flying wing example, we'll set a mixer weight of 90 for the aileron mixes and just 30 for the elevator mixes. The values can be fine tuned later.

Also, the elevons must move in opposite directions in response to roll commands, so for the second Ail mix, we make the weight negative.

MIXERS menu

CH1 (right elevon)

Src = 'Ail', weight=90%
Src = 'Ele', weight=30%

 

CH2 (left elevon)

Src = 'Ail', weight=-90%
Src = 'Ele, weight=30%

That's our basic setup completed. However, it can be improved...

Using Inputs (INPUTS menu)

Our flying wing will work fine. However, in order to adjust the aileron (or elevator) rate, it's necessary to modify the mixer weight in two places, once in CH1 and once in CH2:

MIXERS menu

CH1 (right elevon)

Src = 'Ail', weight=90%
Src = 'Ele', weight=30%

 

CH2 (left elevon)

Src = 'Ail', weight=-90%
Src = 'Ele, weight=30

This kind of redundancy is undesirable because it's twice the work, with twice the chance of error. We can get round this by using Inputs. These were introduced in OpenTx v. 2.0. Inputs can be used in place of raw sources in most contexts, and incorporate rate and expo parameters. Here's an example:

INPUTS menu

[I1]Flp

Src=LS, wt=90%, expo=10%

This defines an input [I1] which we call 'Flp' (for Flap). The raw source of the input is the left slider LS. The input has a weight of 90% and expo of 10%. We could then use this input in a mix in place of LS.

We'll see later how inputs can be applied to our flying wing example. First let's see how to create and manage inputs in more detail:

Managing inputs

OpenTx provides 32 inputs.

Inputs are managed in the INPUTS menu. Each input has:

When you create a new model, OpenTx automatically generates four inputs for the main flight controls: [I1]Ail, [I2]Ele, [I3]Thr, [I4]Rud. However you can define your own inputs, and clear any which are not needed.

Note that the use of inputs is optional; just because they're available doesn't mean you have to use them - you can still use the raw source where it's more appropriate.

Inputs example (flying wing)

In this section, we'll modify our flying wing example so that it uses inputs instead of raw sources as the source of the mixes.

The first task is to define inputs [I1] and [I2]. We'll assign them names 'Ail' and 'Ele', and we'll base them on the raw sources Ail and Ele. We also set appropriate values for weight and expo:

INPUTS menu

[I1]Ail

Src=Ail, wt=90%, expo=10%

 

[I2]Ele

Src=Ele, wt=30%, expo=15%

Next, we must modify the mixers. Previously they referenced raw sources Ail and Ele. They must now reference [I1]Ail and [I2]Ele. In addition, we reset the mixer rates to the 100%, since the rates are now specified in the inputs.

Here's the modified setup:

INPUTS menu

[I1]Ail

Src=Ail, wt=90%, expo=10%

 

[I2]Ele

Src=Ele, wt=30%, expo=15%

 

MIXERS menu

CH1 (right elevon)

Src = [I1], wt=100%
Src = [I2], wt=100%

 

CH2 (left elevon)

Src = [I1], wt=-100%
Src = [I2], wt=100%

This shows the INPUTS, OUTPUTS and MIXERS:

Note that rate or expo can now be altered by adjusting a single parameter in the relevant input.

Choosing between Inputs and raw sources

As we've just seen, the source of a mix can be specified as an input (e.g. '[I1]Ail') or as the raw source ('Ail'). A good rule of thumb is as follows:

It's good practice to clear unused inputs so they don't clutter up the INPUTS screen.

Mixer and channel outputs

In this section we'll investigate how OpenTx converts stick movements into position commands. It might seem like heavy going, but stick with it!

OpenTx performs two stages of calculation, first at the level of the mixers, and then for the channel as a whole:

  1. First, OpenTx calculates the contribution from each mix (mixer outputs)
  2. Secondly, aggregates the effects of all the mixers for each channel (channel outputs)

Let's look at each stage in detail:

Mixer outputs

For each mixer, OpenTx calculates the mixer output value. Taking our flying wing example, at any particular moment in time the mixer outputs are as follows:

Channel 1

mix_output_1 = Ail_stick_value x 90%

mix_output_2 = Ele_stick_value x 30%

 

Channel 2

mix_output_1 = Ail_stick_value x -90%

mix_output_2 = Ele_stick_value x 30%

So for example, for Channel 1:

Each mix provides a contribution to the channel output.

Channel output

OpenTx adds the mixer outputs to produce the channel outputs. The channel output represents the commanded servo position:

ch1_output = (Ail_stick_val x 90%)+(Ele_stick_val x 30%)
ch2_output = (Ail_stick_val x -90%)+(Ele_stick_val x 30%)

Using our elevon example, let's see how the outputs for CH's 1 and 2 vary with stick inputs. Recall that the stick values vary between -100 (full left or full back) to +100 (full right or full forward), with zero in the centre.
S T I C K S C H A N N E L S
Aileron Elevator CH1 CH2
0 (centre) 0 (centre) 0 0
100% (full  right) 0 (centre) 90+0=90 -90+0=-90
-100% (full left) 0 (centre) -90+0=-90 90+0=90
0(centre) 100% (full forward) 0+30=30 0+30=30
50% (half right) 50% (half forward) 45+15=60 -45+15=-30
100% (full  right) 100% (full forward) 90+30=120 -90+30=-60

The last line shows the effect of full right aileron and full down elevator together. Note the channel value of 120 for CH1. We'll see later how channel values which exceed +/- 100 are clipped to prevent servo overtravel.

Mixer functions

We've seen how the mixer weight determines the output of a mix. In fact this was a bit of a simplification - Opentx offers a lot more flexibility. For each mix, you can additionally specify (a) an offset and (b) either expo, diff, a function or a curve. OpenTx takes these into account when calculating the output of each mix.

Let's look in more detail, starting with the offset parameter.

Offsets

The offset parameter adds a positive or negative value after the weight has been applied. The governing equation is:

Output = (Source * weight) + Offset

In the following mixer line, the output varies from -80 to +120 as S1 is rotated.

Src = 'S1', wt=100%, offset=20

When you create a new mix, default are: weight=100% and offset=0 i.e. the source value is passed through unchanged.

Using offsets to bias Throttle and Spoiler

Offsets are used most in mixes involving throttle and spoiler. These controls differ from the main flight controls, because the 'idle' position is at the top or bottom stick limit. A mix based on throttle or spoiler should therefore output zero at one end of its travel instead. We can achieve this by using offsets.

Example: electric models often use motor-to-elevator compensation in order to trim out pitch changes due to motor thrust. The elevator channel will typically have two mixes as follows:

MIXERS menu

CH2 (elevator)

Src=Ele, wt=100%, offset = 0

Src=Thr, wt=20%, offset=20

The output of the Throttle mix varies from 0 to 40 as the throttle is moved from the idle position. To reverse the range, change the sign of weight.

Note: mixer offsets should be used sparingly. Never use them to make ad-hoc adjustments for servo centres - use Subtrim for that!

Specifying a second mixer function

In addition to weight & offset, the mixer editor in OpenTx allows you to specify one additional function. You can choose between the following:

The 'Curve' option provides the most flexibility, but requires more data entry.

When calculating the mixer output, OpenTx combines the effect with weight and offset.

Diff example: for our flying wing, let's set the aileron diff to 20%:

INPUTS menu

[I1]Ail

Src=Ail, wt=90%, expo=10

 

[I2]Ail

Src=Ele, wt=30%, expo=15

 

MIXERS menu

CH1 (right elevon)

Src = [I1], wt=100%, diff=20%
Src = [I2], wt=100%

 

CH2 (left elevon)

Src = [I1], wt=-100%, diff=20%
Src = [I2], wt=100%

Stick diff v. servo diff

In the above example you will see that we applied diff separately for each aileron mix, even though the INPUTS editor also offers a diff setting. Why? Because diff at the inputs level will result an asymmetric stick response. Not what we want!

To summarise: to implement aileron diff, specify diff separately for each aileron channel. Do not specify diff at the Input level.

Including/excluding trims

By default, trim offsets are included in mixer source values. You can exclude trims on a per-mixer basis. You do this by unchecking "Include Trim" in the mixer dialog.

For our flying wing example, both aileron and elevator trims must be active, so we'll use the default settings.

Channel clipping

We've seen how the channel output is calculated as the sum of all these the mixer outputs:

CHxOutput = SUM (CHxMixerOutput1, CHxMixerOutput2, ...)

If a channel has several mixers active, then the sum of all the mixer outputs could potentially exceed safe limits. This might happen if you apply aggressive control inputs.

To avoid this, OpenTx limits channel values to +/- 100 before passing them to the Outputs. If the sum of the mixer outputs is outside the limits, the channel value is clipped. Clipping manifests itself as deadband at the transmitter control.

Example:

[Note: individual mixer outputs are not clipped. Also, channel values are not clipped when used as sources to mixers.]

Channel scaling (OUTPUTS menu)

Outputs is the final stage in the processing pipeline. It applies a scaling to the channel values, so that each servo (a) moves within defined limits, and (b) centres where you want.

Here's a screenshot of the Outputs menu:

The key fields are MIN, MAX and SUBTRIM.

By setting MIN and MAX appropriately, you can prevent damage to your linkages from excess servo movement.

Where to adjust weights

At any moment in time, each of the three processing layers (Inputs, Mixers, and Outputs) can be considered to apply a nominal rate to their inputs. These rates are applied cumulatively, so that the final servo command is the product of three rates:

OutputValue = SourceValue x Rateinput x Ratemix x Rateoutput

Clearly there is an infinite combination of rates which will produce the same movement at the servo. So how should you go about making the adjustments? Here's the procedure which I recommend:

First, calibrate the servos. This is done in the OUTPUTS menu:

  1. Initialise all input, mixer and output rates to their defaults (100%), and set all trims to the centre.
  2. In the OUTPUTS menu, adjust Min/Max for max possible movement, such that (a) paired control surfaces have equal travel and (b) travel is within the mechanical limits of your linkages.

Finally, set your rates using the INPUTS and MIXERS menus:

  1. Adjust weights in the INPUTS. This should deal with the majority of the setttings.
  2. Any remaining interactions should be adjusted in the MIXERS menu.

 

Slightly More Advanced Stuff!

Mixer ops: ADD, REPL, MULT

So far, we've assumed that mixer outputs are always added together in order to calculate the channel output.

In fact OpenTx is a good deal more flexible - it also permits multiplication and replace operations on mixer outputs. These can be extremely useful. For example, multiplication is key to implementing in-flight adjusters, and 'replace' can be used to implement throttle safety switches.

The mixer operation is specified in the mixer's MULTIPLEX parameter. The options are 'ADD' (the default), 'REPL' and 'MULT'. When calculating a channel value, OpenTx steps through the active mixers, starting with the first mix in the channel:

Note:

Example: The following mixer lines illustrate the effect of the various MULTIPLEX parameters and the importance of mixer order.

Src = I1, op=ADD

Src = I2, op=ADD

output = I1 + I2

Src = I1, op=ADD

Src = I2, op=ADD

Src = I3, op=MULT

output = (I1 + I2) * I3

Src = I1, op=ADD

Src = I2, op=MULT

Src = I3, op=ADD

output = (I1 * I2) + I3

Src = I1, op=ADD

Src = I2, op=MULT (disabled)

Src = I3, op=ADD

output = I1 + I3

Src = I1, op=ADD

Src = I2, op=REPL

Src = I3, op=ADD

output = I2 + I3

Data flow diagrams by Lapin Fou

LapinFou has produced some excellent data flow diagrams which describe the internal workings of OpenTx in detail.