OpenTx - Key Concepts

Mike Shellim 25 July 2014
Updated: 13 May 2017

Introduction

OpenTx is a uniquely flexible operating system, however if you've come from a brand like Futaba or Spektrum then you may find the way of working a little unfamiliar. My aim with this article is to shed some light on its programming features, and to enable you to design your own setups with confidence.

I'll cover the following topics:

Background

Compared with other operating systems, OpenTx may appear a little, well, basic. In place of the myriad high level menus on a typical Futaba or Spektrum system, OpenTx has just seven menus, and each of them is completely generic. This concept of generic simplicity extends to the mixers.

Don't be fooled though. Rather like Lego, OpenTx enables you to create highly flexible, easily adjustable setups which, with a little knowledge, will easily surpass what is possible with the mainstresm transmitters - even the high end sets. Let's take a closer look...

OpenTx: an overview of processing

At the core of OpenTx is the main processing loop. With each cycle, the position of all the controls are read, mixing is applied, channel outputs are calculated and the final values are forwarded to the RF module:

flow

Let's look at each stage in more detail.

The starting point: Sources

The input data for OpenTx comes from your transmitter controls. These are termed sources. Sources appear in several of the OpenTx menus.

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

At the start of the processing loop, OpenTx determines the displacement of each source from its centre position, and assigns a value between -100 and 100:

The process is repeated several time each second, so these values will vary in real time as you move the controls.

(Note: Sources can also be Lua scripts and telemetry data, however these won't be considered for the purposes of this intro).

Channels (MIXERS and OUTPUTS menu)

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

Management of channels is split between the MIXERS and OUTPUTS menus. The OUTPUTS menu is where you give a channel a meaningful name, and configure the direction, limits and centre. You only need to configure those channels which actually drive a servo.

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

Outputs

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 channels; they define which channels should respond as you move the controls. And how they should respond.

Mixers in OpenTx are very simple:

It follows that in order to drive a servo, a channel must have at least one mixer (it may have several mixers as we'll see later).

Mixer notation

In order to describe a mix, I'll use the following notation:

The two forms are interchangeable.

Three mixing scenarios

There are three basic scenarios which must be supported by any high end radio:

  1. One source (e.g stick) affects one channel
  2. One source affects multiple channels
  3. Multiple sources affect one channel

A real-life setup will normally include a combation of these scenarios. Let's see how OpenTx implements each scenario using its simple mixing scheme.

Scenario 1: One source affects one channel

Example: Rudder stick drives rudder channel.

This interaction can be written as:

I chose CH3 as the rudder channel, but of course it could be any free channel. To convert this description to the mixer-friendly format, we simply reverse the terms, and alter the direction of the arrow. It now reads as 'CH3 is affected by the rudder stick':

And here's how it's entered in the MIXER menu:

Mixers

 

Scenario 2: One source affects multiple channels

In this scenario, a single source drives more than one channel at the same time.

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

To convert to mixer definitions we reverse the terms on each line:

Once in this form it can be entered directly in the mixer menu.

onetomany

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

Scenario 3: Multiple sources affect 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 )


Again I've chosen CH4, but it could be any free channel.

The interactions can be written in mixer-friendly form:

And the MIXER screen looks like this:

many to one

Note that this time all the inputs are assigned to the same channel. The '+' sign at the start of the 2nd and 3rd mixes shows that their contributions are additive.

Designing real mixing schemes!

The scenarios in the previous section form the basic building blocks of a setup. However it's not always obvious how they should be applied, especially for more complex models like F3X sailplanes.

Fortunately there's a simple design method which can be applied to virtually any model. It's one which I've used for many years, both on the Taranis and the Multiplex 4000. It breaks the design process into a few simple steps:

and finally:

As you assimilate the logic, you'll be able to perform these steps without pen and paper.

Example: setup for a simple flying wing

A flying wing has two elevons. Each elevon may be driven by the elevator and/or aileron sticks simultaneously. Elevator commands cause both surfaces to move in the same direction, aileron commands drives them in opposing directions.

We'll follow the steps described in the previous section:

Step 1. List the sources (control sticks)

The first step is to list the control sticks used to fly the model. These will be the sources of the mixes:

Note that 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 - we'll use channels 1 and 2. We'll give them names 'RtEvon' and 'LtEvon' (names are limited to 6 characters). These can be entered directly into the OUTPUTS menu:

Outputs

Step 3. Identify interactions

In this key step, we identify every possible interaction between all the sources (i.e. sticks) and the servos.

On our flying wing, the first source is the aileron stick (Ail). As it's displaced, both elevons must move. The interactions are therefore:

Same for the elevator stick (Ele):

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

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

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".

Step 5: Reorder interactions by channel number

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

Step 6: Enter definitions into the Mixers menu

Finally, enter the interactions from Step 5 into the Mixers menu:

mixers

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. There are three menus where the adjustments influence the control surface movements - Mixers, Inputs and Outputs. For now, I'll just consider the mixers.

On our flying wing , the elevons must be more sensitive to roll commands than pitch. In other words, the aileron input must have a higher 'weight' than elevator. We'll set weight=90 for the aileron mixes and 30 for the elevator mixes.

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, we have to alter 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. Fortunately we can get round this by using Inputs.

Inputs were introduced in OpenTx v. 2.0. Think of an Input as a source which has been pre-conditioned. Here's an example of an input based on the aileron stick, with weight 90% and 10% expo.

INPUTS menu

[I1]Ail

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

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

Managing inputs

Inputs are managed in the INPUTS menu. OpenTx provides 32 inputs. Each input has:

In order to do anything useful, an input must have at least one line containing src, weight etc. (Inputs can have more than one line, each dedicated to specific switch and/or flight mode. However for this article I will only consider inputs with a single line.)

When you create a new model, OpenTx generates 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. 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 stick as source where it's more appropriate.

Using inputs (flying wing example)

Let's modify our flying wing example to use inputs as mixer sources (instead of sticks).

The first task is to define a couple of inputs. Any inputs will do, let's use [I1] and [I2] .

The sources will the aileron and elevator sticks. We'll name the inputs 'Ail' and 'Ele'. Finally, we 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%

So now we can use [I1]Ail instead of Ail as the mixer source. Similarly, we use [I2]Ele instead of Ele.

Also, the rates are now specified in the inputs, so we should reset the mixer rates to 100%.

Here's the completed 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%

Screen captures of the INPUTS, OUTPUTS and MIXERS:

inputs

channels

mixers

Now we can alter the aileron and elevator rates with a single adjustment for each.

Choosing between Inputs and sticks

We've seen how the source of a mix can be specified either as a preconditioned Input (e.g. '[I1]Ail'), or as a raw input ('Ail') . So which to choose? A good rule of thumb is as follows:

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

Mixer and channel outputs

In this section we'll look in more detail how OpenTx converts stick movements into position commands. An understanding will be useful when debugging your setup.

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
  2. Secondly, aggregates the effects of all the mixers for each channel

Let's look at each stage in detail:

Mixer output

For each mix, OpenTx calculates the mixer output according the weight (and other parameters we'll look at later). Taking our flying wing example, at any moment 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%

Channel output

For each channel, OpenTx sums the mixer outputs. The result 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, we can see how the outputs vary with stick inputs. Recall that stick values vary between -100 and +100, with zero in the centre.
S T I C K S C H A N N E L S
Aileron Elevator CH1 CH2
(centre) 0  (centre) 0 0 0
(full  right) 100% (centre) 0 90+0=90 -90+0=-90
(full left) -100%  (centre) 0  -90+0=-90 90+0=90
(centre) 0 (full forward) 100% 0+30=30 0+30=30
(half right) 50% (half forward) 50%  45+15=60 -45+15=-30
(full  right) 100% (full forward) 100% 90+30=120 -90+30=-60

The last line shows the effect of "stick in the corner" - note the commanded position for CH1 is 120. OpenTx automatically clips servo commands to +/- 100, in order to keep servo travel within defined bounds. More on that later.

More about mixers

OpenTx offers a number of mechanisms for conditioning the output of a mix. We've looked at weight, however this is just the simplest example. Other parameters include offset, expo or diff, functions and curves.

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 commonly used for throttle and spoiler controls. These differ from the main flight controls because their 'idle' position corresponds to an end point of the control. This mix must therefore output zero (instead of +/-100) at one end point. We can achieve this by using offsets.

Example: motor-to-elevator compensation on an electric model.

The elevator channel in an electric mode will typically have two mixes:

MIXERS menu

CH2 (elevator)

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

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

In this example, setting wt=offset=20% will vary the mix from 0 to 40 as the throttle is moved from the idle position. To reverse the range, we would change the sign of weight.

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

Diff, expo, functions and curves

In addition to weight & offset, the mixer editor in OpenTx allows you to specify one additional option from the following:

The 'Curve' option provides the most granularity - it can implement all the other options, but requires the most data entry.

How to implement aileron diff

There are one or two gotchas to be aware of when implementing aileron diff

INPUTS menu

[I1]Ail

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

 

[I2]Ail

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

 

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%

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. This is because diff in inputs produces an asymmetric stick response. We want the servo response to be asymmetric, so it diff must be specified at the channel level.

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

[Note: to avoid having to enter the same diff value twice, use a GVAR.]

Including/excluding trims

By default, trim values are included in 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.

Order of processing

When calculating the output of a mix, OpenTx first applies source trims (if enabled for the mix). Then it applies the function (diff, function, curve, expo), followed by weight, and finally adds the offset. Order may be important when combining operators especially where offsets are involved.

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, only channel values. Also, channel values are only clipped when passed to the Outputs layer, they not clipped when used as mixer sources.]

Channel scaling (OUTPUTS menu)

Outputs is the final stage in the processing pipeline. Outputs apply 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:

outputs

The key fields are MIN, MAX and SUBTRIM, and CURVE

By setting appropriate end points, 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:

  1. Start by calibrating your control surface movements in the OUTPUTS menu (setting up end points, centres and equalising movements). Calibration should be done with inputs and mixer weights at their defaults (100%), and all trims to centre. The aim is to define the widest possible operating range of your control surfaces consistent with left/right and up/down symmetry.
  2. Reduce control surface travel via INPUTS.
  3. Any remaining interactions can be adjusted in the MIXERS menu.

 

Slight more advanced...

Mixer operators: 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

Src = I1, op=ADD

Src = I2, op=REPL

Src = I3, op=MULT

output = I2 * I3

Src = I1, op=ADD (disabled)

output = 0

The 'MAX' source

MAX is a special source which doesn't correspond to a physical control. Instead, MAX supplies a fixed value of +100. In conjunction with weight, it can be used to simulate the effect of a fixed stick position.

Src = MAX, wt =100 -- output = 100%

Src = MAX, wt=50 -- output = 50%

Src = MAX, wt=-100 -- output = -100%

Here's a simple example, showing a crude motor arming system. The motor is armed when SA is down.

MIXERS menu

CH7 (motor)

Src = MAX, wt=-100%

Src = Thr, wt=100%, switch=SA-DOWN, multiplex = REPL

Links

LapinFou has produced some useful data flow diagrams which describe the internal workings of OpenTx (Note: at the time of writing, there are one or two errors in the order of processing of curves).