Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
This section provides more specifics on the OpenTX Lua implementation. Here you will find syntax rules for interface tables and functions.
TODO: Need to determine status of wizard in 2.2
This section describes the Lua libraries, functions and constants that are provided by OpenTX.
This section includes Acknowledgments and Getting Started.
This section introduces the types of Lua scripts supported by OpenTX and how they may be used.
If defined, init function is called right after the script is loaded from SD card and begins execution. Init is called only once before the run function is called for the first time.
local function <init_function_name>()
-- code here runs only once when the model is loaded
endInput Parameters:
none
Return values:
none
OpenTX Companion 2.2 is available for download at http://www.open-tx.org/downloads.html
If you intend to use mixer scripts, when updating the firmware on your transmitter you need to make sure the lua option is checked in the settings for your radio profile (Main menu -> Settings ->Settings...) as shown below. This is not required if you only intend to run telemetry, one-time and function scripts, support for those is included by default.
Also note that the SD Structure path should contain a valid path to a copy of your transmitter's SD card contents, although that's not specific to Lua.
One-Time scripts start when called upon by a specific radio function or when the user selects them from a contextual menu. They do their task and are then terminated and unloaded. Please note that all persistent scripts are halted during the execution of one time scripts. They are automatically restarted once the one time script is finished. This is done to provide enough system resources to execute the one time script.
The return statment is the last statement in an OpenTX Lua script. It defines the input/output table values and functions used to run the script.
Parameters init, input and output are optional. If a script doesn't use them, they can be omitted from return statement.
Example without init and output:
The OpenTX team has no intention of making a profit from their work. OpenTX is free and open source and will remain free and open source. But OpenTX is more expensive to maintain than most open source projects. The reason is that there is a never ending flood of hardware to integrate and maintain code for. Hardware that costs.
Another reason is that OpenTX maintains a build server that serves firmware compiled on demand. This is where OpenTX Companion orders your customized firmware. The server is not for free and the bandwidth is ever increasing with tens of thousands of firmware downloads each month.
The OpenTX team is grateful to those who have donated to the project. You have helped making OpenTX and OpenTX Companion great.
The is updated at each OpenTX release.
If you would like to contribute to OpenTX, donations are welcome and appreciated:
Pops a received SPORT packet from the queue. Please note that only packets using a data ID within 0x5000 to 0x50FF (frame ID == 0x10), as well as packets with a frame ID equal 0x32 (regardless of the data ID) will be passed to the LUA telemetry receive queue.
@status current Introduced in 2.2.0
none
This functions allows for sending SPORT telemetry data toward the receiver, and more generally, to anything connected SPORT bus on the receiver or transmitter.
When called without parameters, it will only return the status of the output buffer without sending anything.
@status current Introduced in 2.2.0, retval nil added in 2.3.4
This functions allows for sending SPORT / ACCESS telemetry data toward the receiver, and more generally, to anything connected SPORT bus on the receiver or transmitter.
When called without parameters, it will only return the status of the output buffer without sending anything.
@status current Introduced in 2.3
Running a One-Time script will suspend execution of all other currently loaded Lua scripts (Mix, Telemetry, and Functions)
Place them anywhere on SD card, the folder /SCRIPTS/ is recommended. The only exception is official model wizard script, that should be put into /SCRIPTS/WIZARD/ folder that way it will start automatically when new model is created.
Script is executed when user selects Execute on a script file from SD card browser screen.
Script executes until:
it returns value different from 0
is forcefully closed by user by long press of EXIT key
is forcefully closed by system if if it misbehaves (too long runtime, error in code, low
memory)
command commanddata table of data bytes
boolean data queued in output buffer or not.
nil incorrect telemetry protocol.
unit (number) unit identifier [Full list]((../appendix/units.html))
attributes (unsigned number) possible values:
0 or not present plays integral part of the number (for a number 123 it plays 123)
PREC1 plays a number with one decimal place (for a number 123 it plays 12.3)
PREC2 plays a number with two decimal places (for a number 123 it plays 1.23)
none
number Number of 10ms ticks since the radio was started Example:
run time: 12.54 seconds, return value: 1254
table with elements:
gtimer (number) radio global timer in seconds
session (number) radio session in seconds
ttimer (number) radio throttle timer in seconds
tptimer (number) radio throttle percent timer in seconds
number Number of seconds elapsed since 1. Jan 1970
nil queue does not contain any (or enough) bytes to form a whole packet
multiple returns 4 values:
sensor ID (number)
frame ID (number)
data ID (number)
value (number)
pause (number) length of the silence after haptic feedback in milliseconds
flags (number):
0 or not present play with normal priority
PLAY_NOW play immediately
none
table model information:
name (string) model name
bitmap (string) bitmap name (not present on X7)
nil
number representing RAS value. Value bellow 0x33 (51 decimal) are all ok, value above 0x33 indicate a hardware antenna issue.
This is just a hardware pass/fail measure and does not represent the quality of the radio link
RAS was called SWR in the past
none
line (unsigned number) mix number (use 0 for first line(mix))
none
none
value module parameters, see model.getModule()
none
If a parameter is missing from the value, then that parameter remains unchanged.
sensorId physical sensor IDframeId frame ID
dataId data ID
value value
boolean data queued in output buffer or not.
nil incorrect telemetry protocol.
if set to 'session', radio session timer is reset too
if set to 'ttimer', radio throttle timer is reset too
if set to 'tptimer', radio throttle percent timer is reset too
none
usage (number) a value from 0 to 100 (percent)
value (table) custom function parameters, see model.getCustomFunction() for table format
none
If a parameter is missing from the value, then that parameter remains unchanged.
params see model.getFlightMode return format for table format.
none
line (unsigned number) input line (use 0 for first line)
value (table) input data, see model.getInput()
none
hourFormat (number):
0 or not present play format: minutes and seconds.
!= 0 play format: hours, minutes and seconds.
none
module module index (0 = internal, 1 = external)rxUid receiver index
sensorId physical sensor ID
frameId frame ID
dataId data ID
value value
boolean data queued in output buffer or not.
Play a file from the SD card
@status current Introduced in 2.0.0, changed in 2.1.0
path (string) full path to wav file (i.e. “/SOUNDS/en/system/tada.wav”)
Introduced in 2.1.0: If you use a relative path, the current language is appended
to the path (example: for English language: /SOUNDS/en is appended)
none
Raises a pop-up on screen that shows a warning
@status current Introduced in 2.2.0
title (string) text to display
event (number) the event variable that is passed in from the run function (key pressed)
"CANCEL" user pushed EXIT key
Use only from stand-alone and telemetry scripts.
TODO: describe how theme scripts work on Horus type transmitters.
Set Logical Switch parameters
@status current Introduced in 2.0.0
switch (unsigned number) logical switch number (use 0 for LS1)
value (table) see model.getLogicalSwitch() for table format
none
If a parameter is missing from the value, then that parameter remains unchanged.
To set the and member (which is Lua keyword) use the following syntax: model.setLogicalSwitch(30, {func=4,v1=1,v2=-99, ["and"]=24})
Reads characters from the serial port. The string is allowed to contain any character, including 0. Note that the returned string may not end in a newline if this character is not present in the buffer.
@status current Introduced in 2.3.8
num (optional): maximum number of bytes to read.
If non-zero, serialRead will read up to num characters from the buffer.
If 0 or left out, serialRead will read up to and including the first newline character or the end of the buffer.
string Empty if no new characters were available.
Go to https://doc.open-tx.org/opentx-2-3-lua-reference-guide/ for the latest published version of this guide.
This guide covers the development of user-written scripts for R/C transmitters running the OpenTX 2.3 operating system with Lua support. Readers should be familiar with OpenTX, the OpenTX Companion, and know how to transfer files the SD card in the transmitter.
Part I of the guide shows how to enable Lua support for Taranis and includes basic examples of each types of script.
Part II is a programming guide that introduces the types of OpenTX Lua scripts and how to use them.
Part III is the OpenTX Lua API Reference
Part IV addresses common issues in converting Lua scripts that were originally written for OpenTX 2.0
Part V addresses common issues in converting Lua scripts that were originally written for OpenTX 2.1
Part VI covers advanced topics with examples
last updated on 2021/01/09 17:57:00 UTC
local inputs = { { "Aileron", SOURCE }, { "Ail. ratio", VALUE, -100, 100, 0 } }
local function run_func(ail, ratio)
-- do some stuff
if (ail > 50) and ( ratio < 40) then
playFile("foo.wav")
end
end
-- script that only uses input and run
return { run=run_func, input=inputs }Telemetry scripts are used for building customized screens. Each model can have up to three active scripts as configured on the model's telemetry configuration page. The same script can be assigned to multiple models.
Scripts are located on the SD card in the folder /SCRIPTS/TELEMETRY/<name>.lua. File name length (without extension) must be 6 characters or less (this limit was 8 characters in OpenTX 2.1).
Telemetry scripts are started when the model is loaded.
script init function is called
script background function is periodically called when custom telemetry screen is not visible. Notice:
In OpenTX 2.0 this function is not called when the custom telemetry screen is visible.
Every script must include a return statement at the end, that defines its interface to the rest of OpenTX code. This statement defines:
script init function (optional)
script background function
script run function
init_func() function is called once when script is loaded and begins execution.
bg_func() is called periodically, the screen visibility does not matter.
run_func(event) function is called periodically when custom telemetry screen is visible. The event
Get Curve parameters
Note that functions returns the tables starting with index 0 contrary to LUA's usual index starting with 1
@status current Introduced in 2.0.12
curve (unsigned number) curve number (use 0 for Curve1)
nil requested curve does not exist
table curve data:
name (string) name
Return input data for given input and line number
@status current Introduced in 2.0.0, curveType/curveValue/carryTrim added in 2.3, inputName added 2.3.10, flighmode reworked in 2.3.11
input (unsigned number) input number (use 0 for Input1)
line (unsigned number) input line (use 0 for first line)
nil requested input or line does not exist
table input data:
name (string) input line name
@status current Introduced in 2.2.0
id Id of the sensor, valid range is from 0 to 0xFFFF
subID subID of the sensor, usually 0, valid range is from 0 to 7
instance instance of the sensor (SensorID), valid range is from 0 to 0xFF
value fed to the sensor
unit unit of the sensor
precision the precision of the sensor
0 or not present no decimal precision.
!= 0 value is divided by 10^precision, e.g. value=1000, prec=2 => 10.00.
name (string) Name of the sensor if it does not yet exist (4 chars).
not present Name defaults to the Id.
present Sensor takes name of the argument. Argument must have name surrounded by quotes: e.g., "Name"
true, if the sensor was just added. In this case the value is ignored (subsequent call will set the value)
All three parameters id, subID and instance can't be zero at the same time. At least one of them must be different from zero.
Play a tone
@status current Introduced in 2.1.0
frequency (number) tone frequency in Hz (from 150 to 15000)
duration (number) length of the tone in milliseconds
pause (number) length of the silence after the tone in milliseconds
flags (number):
0 or not present play with normal priority.
PLAY_BACKGROUND play in background (built in vario function uses this context)
freqIncr (number) positive number increases the tone pitch (frequency with time), negative number decreases it. The frequency changes every 10 milliseconds, the change is freqIncr * 10Hz. The valid range is from -127 to 127.
none
Get configuration for specified Mix
@status current Introduced in 2.0.0, parameters below multiplex added in 2.0.13
channel (unsigned number) channel number (use 0 for CH1)
line (unsigned number) mix number (use 0 for first line(mix))
nil requested channel or line does not exist
table mix data:
name (string) mix line name
The run function is the function that is periodically called for the lifetime of script execution. Syntax of the run function is different between mix scripts and telemetry scripts.
Input parameters:
zero or more input values, their names are arbitrary, their meaning and order is defined by the input table. (see )
Return values:
none - if output table is empty (i.e. script has no output)
values
or -
Input parameters:
The key-event parameter indicates which transmitter button has been pressed (see )
Return values:
A non-zero return value will halt the script
Returns (some of) the general radio settings
@status current Introduced in 2.0.6, imperial added in TODO, language and voice added in 2.2.0, gtimer added in 2.2.2.
none
table with elements:
battWarn (number) radio battery range - warning value
battMin (number) radio battery range - minimum value
Get RF module parameters
Type values:
0 NONE
1 PPM
local function <run_function_name>([first input, [second input], …])
-- if mix has no return values
return
-- if mix has two return values
return value1, value2
end'numsat' (number) current number of sats locked in by the GPS sensor
'fix' (boolean) fix status
'alt' (number) internal GPS altitude in 0.1m
'speed' (number) internal GPSspeed in 0.1m/s
'heading' (number) internal GPS ground course estimation in degrees * 10
'hdop' (number) internal GPS horizontal dilution of precision
day (number) day of month
hour (number) hours
hour12 (number) hours in US format
min (number) minutes
sec (number) seconds
suffix (text) am or pm
type (number) type
smooth (boolean) smooth
points (number) number of points
y (table) table of Y values:
key is point number (zero based)
value is y value
x (table) only included for custom curve type:
key is point number (zero based)
value is x value
inputName (string) input input name
source (number) input source index
weight (number) input weight
offset (number) input offset
switch (number) input switch index
curveType (number) curve type (function, expo, custom curve)
curveValue (number) curve index
carryTrim (boolean) input trims applied
'flightModes' (number) bit-mask of active flight modes
PLAY_NOW play immediately
source (number) source index
weight (number) weight (1024 == 100%) value or GVAR1..9 = 4096..4011, -GVAR1..9 = 4095..4087
offset (number) offset value or GVAR1..9 = 4096..4011, -GVAR1..9 = 4095..4087
switch (number) switch index
multiplex (number) multiplex (0 = ADD, 1 = MULTIPLY, 2 = REPLACE)
curveType (number) curve type (function, expo, custom curve)
curveValue (number) curve index
flightModes (number) bit-mask of active flight modes
carryTrim (boolean) carry trim
mixWarn (number) warning (0 = off, 1 = 1 beep, .. 3 = 3 beeps)
delayUp (number) delay up (time in 1/10 s)
delayDown (number) delay down
speedUp (number) speed up
speedDown (number) speed down
battMax (number) radio battery range - maximum value
imperial (number) set to a value different from 0 if the radio is set to the
IMPERIAL units
language (string) radio language (used for menus)
voice (string) voice language (used for speech)
gtimer (number) radio global timer in seconds (does not include current session)
v1 (number) V1 value (index)
v2 (number) V2 value (index or value)
v3 (number) V3 value (index or value)
and (number) AND switch index
delay (number) delay (time in 1/10 s)
duration (number) duration (time in 1/10 s)
packet (table) data bytes
nil requested timer does not exist
table timer parameters:
mode (number) timer trigger source: off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw
start (number) start value [seconds], 0 for up timer, 0> down timer
value (number) current value [seconds]
countdownBeep (number) countdown beep (0 = silent, 1 = beeps, 2 = voice)
minuteBeep (boolean) minute beep
persistent (number) persistent timer
name (string) timer name
3 ISRM_PXX2
4 DSM2
5 CROSSFIRE
6 MULTIMODULE
7 R9M_PXX1
8 R9M_PXX2
9 R9M_LITE_PXX1
10 R9M_LITE_PXX2
11 R9M_LITE_PRO_PXX1
12 R9M_LITE_PRO_PXX2
13 SBUS
14 XJT_LITE_PXX2
subType values for XJT_PXX1:
-1 OFF
0 D16
1 D8
2 LR12
@status current Introduced in TODO
index (number) module index (0 for internal, 1 for external)
nil requested module does not exist
table module parameters:
subType (number) protocol index
modelId (number) receiver number
firstChannel (number) start channel (0 is CH1)
channelsCount (number) number of channels sent to module
Type (number) module type
if the module type is Multi additional information are available
protocol (number) protocol number
subProtocol (number) sub-protocol number
channelsOrder (number) first 4 channels expected order
event (number) the event variable that is passed in from the run function (key pressed)
input (number) value that can be adjusted by the +/- keys
min (number) min value that input can reach (by pressing the - key)
max (number) max value that input can reach
number result of the input adjustment
"OK" user pushed ENT key
"CANCEL" user pushed EXIT key
Use only from stand-alone and telemetry scripts.
line (unsigned number) mix number (use 0 for first line(mix))
value (table) see model.getMix() for table format
none
line (unsigned number) input line (use 0 for first line)
none
nil requested sensor does not exist
table with sensor data:
type (number) 0 = custom, 1 = calculated
name (string) Name
unit (number) See list of units in the appendix of the OpenTX Lua Reference Guide
prec (number) Number of decimals
id (number) Only custom sensors
instance (number) Only custom sensors
formula (number) Only calculated sensors. 0 = Add etc. see list of formula choices in Companion popup
nil requested custom function does not exist
table custom function data:
switch (number) switch index
func (number) function index
name (string) Name of track to play (only returned only returned if action is play track, sound or script)
value (number) value (only returned only returned if action is not play track, sound or script)
mode (number) mode (only returned only returned if action is not play track, sound or script)
param (number) parameter (only returned only returned if action is not play track, sound or script)
active (number) 0 = disabled, 1 = enabled
flight_mode Flight mode number (0 = FM0, 8 = FM8)
value new value for global variable. Permitted range is from -1024 to 1024.
none
Global variable can only store integer values, any floating point value is converted into integer value by truncating everything behind a floating point.
none
nil requested output does not exist
table output parameters:
name (string) name
min (number) Minimum % * 10
max (number) Maximum % * 10
offset (number) Subtrim * 10
ppmCenter (number) offset from PPM Center. 0 = 1500
symetrical (number) linear Subtrim 0 = Off, 1 = On
revert (number) irection 0 = ---, 1 = INV
curve
(number) Curve number (0 for Curve1)
or nil if no curve set
value timer parameters, see model.getTimer()
none
If a parameter is missing from the value, then that parameter remains unchanged.
none
Return flight mode data.
@status current Introduced in 2.1.7
mode (number) flight mode number to return (0 - 8). If mode parameter
is not specified (or contains invalid value), then the current flight mode data is returned.
multiple returns 2 values:
(number) (current) flight mode number (0 - 8)
(string) (current) flight mode name
string
since OpenTX 2.1.7
bit32
since OpenTX 2.1.0
math
since OpenTX 2.0.0
debug
-
Lua Standard Libraries
Included
package
-
coroutine
-
table
-
since OpenTX 2.1.0 (with limitations)
os
-
Starting from OpenTX 2.1 this function is always called no matter if the custom screen is visible or not.
script run function is periodically called when custom telemetry screen is visible
script is stopped and disabled if it misbehaves (too long runtime, error in code, low memory)
all telemetry scripts are stopped while one-time script is running (see Lua One-time scripts)
return 0 on radio without rotary encodercomma separated list of output values, their order and meaning is defined by the output table. (see Output Table Syntax)
Output name is limited to four characters.
A maximum of 6 outputs are supported
Number Format Outputs are 16 bit signed integers when they leave Lua script and are then divided by 10.24 to produce output value in percent:
Script Return Value
Mix Value in OpenTX
0
0%
996
97.2%
1024
100%
-1024
-100%
none
string OpenTX version (ie "2.1.5")
multiple (available since 2.1.7) returns 5 values:
(string) OpenTX version (ie "2.1.5")
(string) radio type: x12s, x10, x9e, x9d+, x9d or x7.
If running in simulator the "-simu" is added
(number) major version (ie 2 if version 2.1.5)
(number) minor version (ie 1 if version 2.1.5)
(number) revision number (ie 5 if version 2.1.5)
flight_mode Flight mode number (0 = FM0, 8 = FM8)
nil requested global variable does not exist
number current value of global variable
a simple warning or notice
-- get GV3 (index = 2) from Flight mode 0 (FM0)
val = model.getGlobalVariable(2, 0)curve (unsigned number) curve number (use 0 for Curve1)
params see model.getCurve return format for table format. setCurve uses standard lua array indexing and arrays start at index 1
`` 0 - Everything okay
1 - Wrong number of points
2 - Invalid Curve number
3 - Cuve does not fit anymore
4 - point of out of index
5 - x value not monotonically increasing
6 - y value not in range [-100;100]
7 - extra values for y are set
8 - extra values for x are set params = {}
params["x"] = {-100, -34, 77, 100}
params["y"] = {-70, 20, -89, -100}
params["smooth"] = true
params["type"] = 1
val = model.setCurve(2, params)local function init_func()
-- init_func is called once when model is loaded
end
local function bg_func()
-- bg_func is called periodically (always, the screen visibility does not matter)
end
local function run_func(event)
-- run_func is called periodically only when screen is visible
end
return { run=run_func, background=bg_func, init=init_func }local function <run_function_name>(key-event)
return 0 -- values other than zero will halt the script
end{ "<name1>", "<name2>" }local output { "Val1", "Val2" }
local function run()
return 0, -1024 -- these values will be available in OpenTX as Val1 and Val2
end
return {output=output, run=run}local function run(event)
local ver, radio, maj, minor, rev = getVersion()
print("version: "..ver)
if radio then print ("radio: "..radio) end
if maj then print ("maj: "..maj) end
if minor then print ("minor: "..minor) end
if rev then print ("rev: "..rev) end
return 1
end
return { run=run }version: 2.1.7
radio: taranis-simu
maj: 2
minor: 1
rev: 7 val = model.setCurve(3, {smooth=true, y={-100, -50, 0, 50, 100, 80}})Returns the value of a source.
The list of fixed sources:
OpenTX Version
Radio
2.0
2.1
,
2.2
, ,
In OpenTX 2.1.x the telemetry sources no longer have a predefined name. To get a telemetry value simply use it's sensor name. For example:
Altitude sensor has a name "Alt"
to get the current altitude use the source "Alt"
to get the minimum altitude use the source "Alt-", to get the maximum use "Alt+"
@status current Introduced in 2.0.0, changed in 2.1.0, Cels+ and Cels- added in 2.1.9
source can be an identifier (number) (which was obtained by the getFieldInfo())
or a name (string) of the source.
value current source value (number). Zero is returned for:
non-existing sources
for all telemetry source when the telemetry stream is not received
Getting a value by its numerical identifier is faster then by its name. While Cels sensor returns current values of all cells in a table, a Cels+ or Cels- will return a single value - the maximum or minimum Cels value.
The input table defines what values are available as input(s) to mix scripts. There are two forms of input table entries.
SOURCE syntax
{ "<name>", SOURCE }SOURCE inputs provide the current value of a selected OpenTX variable. The source must set by the user when the mix script is configured. Source can be any value OpenTX knows about (inputs, channels, telemetry values, switches, custom functions,...). Note: typical range is -1024 thru +1024. Simply divide the input value by 10.24 to interpret as a percentage from -100% to +100%.
VALUE syntax
VALUE inputs provide a constant value that is set by the user when the mix script is configured.
name - maximum length of 8 characters
min - minimum value of -128
Maximum of 6 inputs per script (warning : was 8 in 2.1)
Return detailed information about field (source)
The list of valid sources is available:
OpenTX Version
Radio
2.0
2.1
,
2.2
, ,
@status current Introduced in 2.0.8, 'unit' field added in 2.2.0
name (string) name of the field
table information about requested field, table elements:
id (number) field identifier
name (string) field name
Load a Lua script file. This is similar to Lua's own loadfile() API method, but it uses OpenTx's optional pre-compilation feature to save memory and time during load.
Return values are same as from Lua API loadfile() method: If the script was loaded w/out errors then the loaded script (or "chunk") is returned as a function. Otherwise, returns nil plus the error message.
@status current Introduced in 2.2.0
file (string) Full path and file name of script. The file extension is optional and ignored (see mode param to control which extension will be used). However, if an extension is specified, it should be ".lua" (or ".luac"), otherwise it is treated as part of the file name and the .lua/.luac will be appended to that.
mode (string) (optional) Controls whether to force loading the text (.lua) or pre-compiled binary (.luac) version of the script. By default OTx will load the newest version and compile a new binary if necessary (overwriting any existing .luac version of the same script, and stripping some debug info like line numbers). You can use mode to control the loading behavior more specifically. Possible values are:
function The loaded script, or nil if there was an error (e.g. file not found or syntax error).
string Error message(s), if any. Blank if no error occurred.
Note that you will get an error if you specify mode as "b" or "t" and that specific version of the file does not exist (eg. no .luac file when "b" is used). Also note that mode is NOT passed on to Lua's loader function, so unlike with loadfile() the actual file content is not checked (as if no mode or "bt" were passed to loadfile()).
WARNING - Do not use Lua mix scripts for controlling any aspect of your model that could cause a crash if script stops executing.
Each model can have several mix scripts associated with it. These scripts are run periodically for entire time that model is selected. These scripts behave similar to standard OpenTX mixers but at the same time provide much more flexible and powerful tool.
Mix scripts take one or more values as inputs, do some calculation or logic processing based on them and output one or more values. Each run of a script should be as short as possible. Exceeding the script execution runtime limit will result in the script being forcefully stopped and disabled.
fun, err = loadScript("/SCRIPTS/FUNCTIONS/print.lua")
if (fun ~= nil) then
fun("Hello from loadScript()")
else
print(err)
endb only binary.
t only text.
T (default on simulator) prefer text but load binary if that is the only version available.
bt (default on radio) either binary or text, whichever is newer (binary preferred when timestamps are equal).
Add x to avoid automatic compilation of source file to .luac version.
Eg: "tx", "bx", or "btx".
Add c to force compilation of source file to .luac version (even if existing version is newer than source file).
Eg: "tc" or "btc" (forces "t", overrides "x").
Add d to keep extra debug info in the compiled binary.
Eg: "td", "btd", or "tcd" (no effect with just "b" or with "x").
env (integer) See documentation for Lua function loadfile().
switch (number) input switch index
fadeIn (number) fade in value (in 0.1s)
fadeOut (number) fade out value (in 0.1s)
trimsValues (table) table of trim values:
key is trim number (zero based)
value is trim value
trimsModes (table) table of trim mode:
key is trim number (zero based)
value is trim mode
table GPS position is returned in a table:
lat (number) latitude, positive is North
lon (number) longitude, positive is East
pilot-lat (number) pilot latitude, positive is North
pilot-lon (number) pilot longitude, positive is East
table GPS date/time, see getDateTime()
table Cells are returned in a table (except where no cells were detected in which case the returned value is 0):
table has one item for each detected cell:
key (number) cell number (1 to number of cells)
value (number) current cell voltage
2.3
X9D and X9D+, X9E, X7, Horus
desc (string) field description
'unit' (number) unit identifier Full list
nil the requested field was not found
2.3
X9D and X9D+, X9E, X7, Horus

max - maximum value of 127
default - must be within the valid range specified
{ "<name>", VALUE, <min>, <max>, <default> }local input =
{
{ "Strength", SOURCE}, -- user selects source (typically slider or knob)
{ "Interval", VALUE, 0, 100, 0 } -- interval value, default = 0.
}
local function run(strength, interval)
-- variable strength will contain the current slider value
-- variable interval is set by the user and constant through script lifetime
-- this script has no return value but may use playFile() to alert user
return
end
return {input=input, run=run}replacement for complex mixes that are not critical to model function
complex processing of inputs and reaction to their current state and/or their history
filtering of telemetry values
cannot update LCD screen or perform user input.
should not exceed allowed run-time/ number of instructions.
mix scripts are run with less priority than built-in mixes. Their execution period is around 30ms and is not guaranteed!
can be disabled/killed anytime due to logic errors in script, not enough free memory, etc...)
Place them on SD card in folder /SCRIPTS/MIXES/. File name length (without extension) must be 6 characters or less (this limit was 8 characters in OpenTX 2.1).
script is loaded from SD card when model is selected
script init function is called
script run function is periodically called (inside GUI thread, period cca 30ms)
script is killed (stopped and disabled) if it misbehaves (too long runtime, error in code, low memory)
all mix scripts are stopped while one-time script is running (see Lua One-time scripts)
If as script output is used as a mixer source and the script is killed for what ever reason, then the whole mixer line is disabled! This can be used for example to provide a fall-back in case Lua mixer script gets killed.
Example where Lua mix script is used to drive ailerons in some clever way, but control falls back to the standard aileron mix if script is killed. Second mixer line replaces the first one when the script is alive:
Every script must include a return statement at the end, that defines its interface to the rest of OpenTX code. This statement defines:
script input table (optional, see Input Table Syntax)
script output table (optional, see Output Table Syntax)
script init function (optional, see Init Function Syntax)
script run function (see )
inputs table defines input parameters (name and source) to run function (see Input Table Syntax)
outputs table defines names for values returned by run function (see Output Table Syntax)
init_func() function is called once when script is loaded.
run_func() function is called periodically
CH1 [I4]Ail Weight(+100%)
:= LUA4b Weight(+100%)local input {}
local output {}
local function init_func()
end
local function run_func()
end
return { input=input, output=output, run=run_func, init=init_func }This page describes the value that is passed to scripts in the event parameter. It is used in Telemetry and One-Time scripts.
Each time a key is pressed, held and released a number of events get generated. Here is a typical flow:
when a key is pressed a FIRST event is generated
if the key continues to be pressed, then after a while a LONG event is generated
if the key continues to be pressed, then a REPEAT events are being generated
when the key is released a BREAK event is generated
Couple of examples:
a short press on key would generate: FIRST, BREAK
a longer pres on key would generate: FIRST, LONG, BREAK
This normal key event sequence can be altered with the function. Any time this function is called (after the FIRST event) all further key events for this key will be suppressed until the next key press of this key. Examples:
kill immediately after the key press would generate: FIRST
kill after the long key press would generate: FIRST, LONG
The event parameter in the and scripts run function actually carries two pieces of information:
key number
type of event
The two fields are combined into one single number. Some of these combinations are defined as constants and are available to Lua scripts:
Radios with rotary encoder (X7 and Horus) have also:
Given the large number of radios supported by OpenTX, and the large difference in keys available on those, a set of VIRTUAL KEYS has been defined and are mapped to best fit available hardware
Widgets are small scripts that show some info in a 'zone' in one of the model specific user defined (telemetry) screens. You can define those screens within the telemetry menu on the HORUS.
Each model can have up to five custom screens, with up to 8 widgets per screen, depending on their size and layout. Each instance of a widget has his own custom settings.
Widgets are located on the SD card, each in their specific folder /WIDGETS/<name>/main.lua (name must be in 8 characters or less).
Widgets need to be registered through the telemetry setup menu.
widget create function is called
widget update function is called upon registration and at change of settings in the telemetry setup menu.
widget background function is periodically called when custom telemetry screen is not visible. Notice:
Once registered, widgets are started when the model is loaded.
Every widget must include a return statement at the end, that defines its interface to the rest of OpenTX code. This statement defines:
widget name (name must be a string of 10 characters or less)
widget options array (maximum five options are allowed, 10 character names max, no spaces!)
widget create function
options are only passed through to OpenTX to be used on widget creation. Don't change them during operation, this has no effect.
create() function is called once when widget is loaded and begins execution.
update() function is called once when widget is loaded and begins execution.
FIRST, LONG, REPEAT,REPEAT, ..., BREAKEXIT key release
EVT_PLUS_BREAK
+ key release
EVT_MINUS_BREAK
- key release
EVT_PLUS_FIRST
+ key press
EVT_MINUS_FIRST
- key press
EVT_PLUS_REPT
+ key repeat
EVT_MINUS_REPT
- key repeat
EVT_VIRTUAL_NEXT
for FIELDS navigation
EVT_VIRTUAL_NEXT_REPT
for FIELDS navigation
EVT_VIRTUAL_PREVIOUS
for FIELDS navigation
EVT_VIRTUAL_PREV_REPT
for FIELDS navigation
EVT_VIRTUAL_INC
for VALUES navigation
EVT_VIRTUAL_INC_REPT
for VALUES navigation
EVT_VIRTUAL_DEC
for VALUES navigation
EVT_VIRTUAL_DEC_REPT
for VALUES navigation
Key Event Name
Comments
EVT_MENU_BREAK
MENU key release
EVT_PAGE_BREAK
PAGE key release
EVT_PAGE_LONG
MENU key long press
EVT_ENTER_BREAK
ENT key release
EVT_ENTER_LONG
ENT key long press
Key Event Name
Comments
EVT_ROT_BREAK
rotary encoder release
EVT_ROT_LONG
rotary encoder long press
EVT_ROT_LEFT
rotary encoder rotated left
EVT_ROT_RIGHT
rotary encoder rotated right
Virtual Key Event Name
Comments
EVT_VIRTUAL_NEXT_PAGE
for PAGE navigation
EVT_VIRTUAL_PREVIOUS_PAGE
for PAGE navigation
EVT_VIRTUAL_ENTER
EVT_VIRTUAL_ENTER_LONG
EVT_VIRTUAL_MENU
EVT_EXIT_BREAK
EVT_VIRTUAL_MENU_LONG
widget refresh function is periodically called when custom telemetry screen is visible
widget is stopped and disabled if it misbehaves (too long runtime, error in code, low memory)
all widgets are stopped while one-time script is running (see Lua One-time scripts)
script background function
script refresh function
refresh() function is called periodically when custom telemetry screen containing wodget is visible.
in the example given, you can see that no global variables or functions are needed to operate the widget.
variables that are used throughout the widget, can best be declared inside the create function as local variables
those local variablkes can then be passed through to the other functions as an element of the widget array that is returned
local defaultOptions = {
{ "ControlX", SOURCE, 1 },
{ "ScrollZ", BOOL, 1 }, -- BOOL is actually not a boolean, but toggles between 0 and 1
{ "StepZ", VALUE, 1, 0, 10},
{ "COLOR", COLOR, RED },
}
local function createWidget(zone, options)
lcd.setColor( CUSTOM_COLOR, options.COLOR )
-- the CUSTOM_COLOR is foreseen to have one color that is not radio template related, but it can be used by other widgets as well!
local someVariable = 0
local anotherVariable = {xWidget=0, yWidget = 0}
return { zone=zone, options=options , someVariable = someVariable, anotherVariable=anotherVariable }
end
local function updateWidget(widgetToUpdate, newOptions)
widgetToUpdate.options = newOptions
lcd.setColor( CUSTOM_COLOR, widgetToUpdate.options.COLOR )
-- the CUSTOM_COLOR is foreseen to have one color that is not radio template related, but it can be used by other widgets as well!
end
local function backgroundProcessWidget(widgetToProcessInBackground)
local function process(...)
return ... + 1
end
widgetToProcessInBackground.someVariable = process (widgetToProcessInBackground.someVariable)
end
local function refreshWidget(widgetToRefresh)
local counterLength = 50
local counterHeight = 30
--backgroundProcessWidget(widgetToRefresh)
--background is not called automatically in display mode, so do it here if you need it.
local function anotherProcess(parameter,step,maxParameter)
return (parameter + step) % maxParameter
end
widgetToRefresh.anotherVariable.xWidget
= anotherProcess ( widgetToRefresh.anotherVariable.xWidget
,getValue(widgetToRefresh.options.ControlX)/10.24/20
,widgetToRefresh.zone.w-counterLength)
widgetToRefresh.anotherVariable.yWidget
= anotherProcess ( widgetToRefresh.anotherVariable.yWidget
,(widgetToRefresh.options.ScrollZ==1) and widgetToRefresh.options.StepZ or 0
,widgetToRefresh.zone.h-counterHeight)
lcd.drawNumber(widgetToRefresh.anotherVariable.xWidget + widgetToRefresh.zone.x
, widgetToRefresh.anotherVariable.yWidget + widgetToRefresh.zone.y
, widgetToRefresh.someVariable
, LEFT + DBLSIZE + CUSTOM_COLOR);
end
return { name="MovingCntr", options=defaultOptions, create=createWidget, update=updateWidget
, refresh=refreshWidget, background=backgroundProcessWidget }specialized handling in response to switch position changes
customized announcements
should not exceed allowed run-time/ number of instructions.
all function scripts are stopped while one-time script is running (see Lua One-time scripts)
Function scripts DO NOT HAVE ACCESS TO LCD DISPLAY
Place them on SD card in folder /SCRIPTS/FUNCTIONS/
script init function is called once when model is loaded
script run function is periodically called as long as switch condition is true
script is stopped and disabled if it misbehaves (too long runtime, error in code, low memory)
Every script must include a return statement at the end, that defines its interface to the rest of OpenTX code. This statement defines:
script init function (optional, see Init Function Syntax)
script run function (see Run Function Syntax)
local variables retain their values for as long as the model is loaded regardless of switch condition value
The script below is an example of customized countdown announcements. Note that the init function determines which version of OpenTX is running and sets the unit parameter for playNumber() accordingly.
local function init_func()
end
local function run_func()
end
return { run=run_func, init=init_func }local lstannounce
local target
local running = false
local duration = 120 -- two minute countdown
local announcements = { 120, 105, 90, 75, 60, 55, 50, 45, 40, 35, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}
local annIndex
local minUnit
local function init()
local version = getVersion()
if version < "2.1" then
minUnit = 16 -- unit for minutes in OpenTX 2.0
elseif version < "2.2" then
minUnit = 23 -- unit for minutes in OpenTX 2.1
else
minUnit = 25 -- unit for minutes in OpenTX 2.2
end
end
local function run()
local timenow = getTime() -- 10ms tick count
local remaining
local minutes
local seconds
if not running then
running = true
target = timenow + (duration * 100)
annIndex = 1
end
remaining = math.floor(((target - timenow) / 100) + .7) -- +.7 adjust for announcement lag
if remaining < 0 then
running = false -- we were 'paused' and missed zero
return
end
while remaining < announcements[annIndex] do
annIndex = annIndex + 1 -- catch up in case we were paused
end
if remaining == announcements[annIndex] then
minutes = math.floor(remaining / 60)
seconds = remaining % 60
if minutes > 0 then
playNumber(minutes, minUnit, 0)
end
if seconds > 0 then
playNumber(seconds, 0, 0)
end
annIndex = annIndex + 1
end
if remaining <= 0 then
playNumber(0,0,0)
running = false
end
end
return { init=init, run=run }

