Skip to content

User Defines

Software Banner

With more features being added consistently, ./src/user_defines.txt has gotten complicated 🤷‍♂️. So we will break it down! 🔨


This is the full list of currently supported User Defines and would help you should you intend to compile the firmware using the Toolchain or manual mode on the ExpressLRS Configurator.

Defines 101

  • If these are used in Configurator Manual Mode or user_defines.txt, the value must begin with -D. Example: NO_SYNC_ON_ARM would be -DNO_SYNC_ON_ARM.
  • A user definition that begins with # is "commented out", i.e. not active.

Binding Phrase

MY_BINDING_PHRASE="default ExpressLRS binding phrase"


This step is simple but important. Both the TX and RX NEED to have the same binding phrase or ExpressLRS WILL NOT WORK. Anyone using the same binding phrase as you will be able to control your model, so be unique. Set something memorable, and limit to alphanumeric phrases conforming to the Latin alphabet*.

Receivers flashed with firmware builds that do not have binding phrases enabled will support and require the traditional binding method. 📜 For ESP/ESP32 hardware, this value can also be changed through the WebUI.

This feature can, but should not be used as a model match feature (to lock a single specific transmitter to a single specific receiver). For that use, the Model Match option.

* This phrase gets md5 hashed and gets built into the binary you will be flashing.

Regulatory Domain

This is a relatively simple one - enable whatever regulatory domain you are in. EU 868 🇪🇺 is compliant to the frequency but is not LBT compliant 👂 . Every other band is near compliant 👿 but may not be fully compliant for your regulatory domain.

The TX module sends the LinkStats telemetry to the OpenTX frequently to let the handset know the connection is still active and reduce "Telemetry Lost" warnings. Reducing this value may reduce warnings caused by handset errors at higher baud rates. This only affects the connection from the TX module to the handset and does not do anything with the telemetry connection from the receiver. The default value is 240LU. When changing this value, suffix your milliseconds value with LU. For example, to specify a 100ms LinkStats update rate, you have to enter it like this: 100LU.

Output Power Limit

By default the max power of the hardware is limited to what it can safely output without extra cooling. Some hardware supports increasing the power by enabling the following option. Check the supported hardware page to see if this is available and what cooling modifications can be made. By enabling this, you are risking permanent damage to your hardware, sometimes even when you add extra cooling. For example, R9M modules will burn out without cooling.

Performance Options

RF Mode Locking - When the RX is waiting for a connection, it cycles through all available rates waiting for a connection on each one. By default, ExpressLRS will go back to this mode after a disconnect (failsafe). If LOCK_ON_FIRST_CONNECTION is used, ELRS will not cycle after a disconnect, but instead, just stay at whatever rate the last connection was. This makes connection re-establishment quick, because the RX is always listening at the proper rate. This is generally what everyone wants, but there is utility in being able to switch the TX to the lowest rate to get more range to re-establish a link with a downed model, which can't happen if the RX is locked at the previous rate.

When cycling through the rates, the RX starts with the fastest packet rate and works down to the slowest, then repeats. It waits PACKET_INTERVAL * PACKS_PER_HOP * HOP_COUNT * 1.1 at each rate. Example: 4ms * 4 * 80 * 1.1 = 1.408s for 250Hz. The duration is extended 10x if a valid packet is received during that time. Even with LOCK_ON_FIRST_CONNECTION, the rate can be changed by changing the TX rate using ELRS.lua while connected, or by power cycling the RX.

For TX devices with fans, FAN_MIN_RUNTIME keeps the fan running even after the power level has dropped below the configured Fan Threshold. This prevents the fan from turning on and off every few seconds if the power level is constantly changing. The default is 30 seconds if not defined, the value can be 0-254. There is always a short delay before the fan is activated, which can not be disabled.

Compatibility Options

This only works with ESP32 based TXes (will not work with modules without built-in inversion/uninversion), but enables compatibility with radios that output inverted CRSF, such as the FrSky QX7, TBS Tango 2, RadioMaster TX16S. You want to keep this enabled in most cases. If your radio is T8SG V2 or you use Deviation firmware turn this setting off.

This only works with ESP8266/ESP8285 based RXes. Invert the TX pin in the receiver code to allow an inverted RX pin on the flight controller to be used (usually labeled SBUS input or RXI). Inverted CRSF output. RX pin (telemetry) is unaffected. Update via_BetaflightPassthrough will not work, only via_Wifi. Note that just because this description includes the word SBUS, it doesn't mean the RX will output SBUS. It is still a CRSF protocol, only inverted, so CRSF should still be the receiver protocol selected in the flight controller software.

Use a custom baud rate on the receiver instead of the default 420000 baud. This is useful for a KISS v1 FC (which runs at 400000) or any other oddball baud, like 115200 for interfacing with an Arduino.

This does not turn on SBUS protocol it simply changes the pin used for communication from those two side pins (A9 and A10) to use the pin labeled "SBUS" on the RX, which is inverted. This is useful for F4 FCs which only have an inverted receiver input UART RX. 🔼. This is only one way, so you lose the telemetry downlink to your radio as well as passthrough flashing. Enabling this turns on CRSF protocol output on the S.BUS 🚌 pin on your R9MM/R9Mini. set serialrx_inverted = ON may also be needed within Betaflight 🐝 for compatibility

Network Options

⚠️ Must be defined if you plan to update your RX over WiFi without using a button on the RX ⚠️ This will automatically turn the WiFi 📶 on for any module that has an ESP8285 on it if no TX connection is established after N seconds from boot (the 30 is the time). This enables pushing firmware updates to the RX by connecting to its WiFi network and visiting


These options set Home Network Access for your WiFi-enabled hardware. With these sets, the devices will try connecting to your existing WiFi Network when you click on "(WiFi) Update" on the ExpressLRS Lua script (for some TX Modules) or automatically after your set interval time. Once the devices connect to your Home WiFi, the Update page can be accessed anywhere, from any device on the same network. The TX Module WiFi update page can be reached using the address http://elrs_tx.local, while the receivers' update page can be reached via http://elrs_rx.local.

WiFi mode will first try to connect to the network specified before falling back and creating a new WiFi network. The Home Network can also be modified from the website.

Other Options

MY_STARTUP_MELODY="<music string>|<bpm>|<semitone offset>" -or-
MY_STARTUP_MELODY="<rtttl string>"
For TXes like the R9M, this sets if the TX only beeps one-time versus playing a startup song. Currently, it is set to play the startup song 🎼 , but if you don't prefer it, uncomment this to turn it off. ✖️

For all your customization needs, use DMY_STARTUP_MELODY to define your own startup melody using the BLHeli32 or RTTTL syntax. For BLHeli32, the parameters music string and bpm are required, whereas semitone offset is optional to transpose the entire melody up or down by the defined amount of semitones.

For example, BLHeli32 melodies are available on Rox Wolf's youtube channel, some experimentation may be required though. 🎵 To write your own melody, this (Sheet Music 101) and this (BLHeli Piano) are useful resources.

The build process also supports RTTTL-formatted ringtone strings. RTTTL melodies are delimited by colons : and start with a description versus the BLHeli style with pipes |. e.g. Mario:d=4,o=5,b=100:32p,16e6,16e6,16p,16e6,16p,16c6,16e6,16p,16g6,8p,16p,16g

Disables beep sequence at startup of TX, but the TX will still beep when the CRSF connection is acquired

Disables all TX buzzer beeps at any state

Enables code for talking to a connected ESP8266 backpack on the TX module, and associated Lua params. The device target should enable this automatically for devices that come with this built-in, but can be added to any device. The TX backpack allows wireless integration with VRX modules and planned telemetry mirroring over WiFi.

Debug Options

Turn on debug messages, sent to the TX Backpack UART if available or else right out the main CRSF UART (such as on the receiver).

Use to see verbose debug logging (spammy stuff)

Print a letter for each packet received or missed (receiver debugging)

Don't send CRSF messages over the CRSF UART (receiver only). Used to only see logging and not logging mixed with CRSF.

Prints a log line for every channels packet received at the RX ID,Antenna,RSSI,LQ,SNR,PWR,FHSS,TimingOffset. The ID is generated on the TX side and overwrites CH1-CH4 and increments once for every channel packet. Writes directly to Serial, and does not require DEBUG_LOG. Flash both TX & RX with this enabled to use it if the ID is required.

Enable reporting of RF FreqCorrection in receiver's SNR LinkStatistics, also decreases packet rate on Team2.4 for the additional time needed to include the packet header / enable FreqCorrection. The current FreqCorrection value will be reported in RSNR in the LinkStats scaled -127 to +127, where 127 is the maximum allowable deviation. 200kHz for Team2.4, 100kHz for Team900. Dynamic power must be OFF, or else it will adjust based on the FreqCorrection reported in SNR. Both the TX and RX must have this definition enabled otherwise they will not bind.

Obsolete user_defines

See Obsolete user_defines