Skip to content

Latest commit

ย 

History

26 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

ExpressLRS / TBS Crossfire WiFi Joystick for Windows

Use your ExpressLRS or TBS Crossfire/Tracer radio as a wireless joystick on Windows โ€” with a live visual app

.NET Platform License

ELRS / TBS Crossfire WiFi Joystick app

This app turns your ExpressLRS (ELRS) or TBS Crossfire / Tracer TX module's WiFi output into a virtual joystick (via vJoy), so you can fly flight simulators like VelociDrone, Liftoff, or DRL โ€” wirelessly, no cables โ€” plus anything on Windows that takes joystick input.

Both radios use the same "WiFi joystick" protocol (the one VelociDrone Mobile speaks), so setup is identical: put the module on your WiFi and run the app. The only difference is the discovery beacon โ€” ELRS announces itself as ELRS, Crossfire as VELOCIDRONE โ€” and the app handles both automatically.

v3.0 is a ground-up WPF interface: vector-rendered, so it is pixel-perfect on any display scale (100/125/150/200%), with GPU-composited live axis bars, packet rate + jitter, connection status, and one-click firewall setup. It still auto-discovers your module and just works.

โœจ Features

  • ๐ŸŽฎ Virtual joystick - creates a Windows vJoy device from your radio's WiFi output
  • ๐Ÿ“ก ELRS + Crossfire/Tracer - full support for the ELRS/Crossfire WiFi joystick protocol (16 channels, 15-bit)
  • ๐Ÿ–ฅ๏ธ Live visual app (WPF) - real-time GPU-composited axis bars, packet rate + jitter, and connection status at a glance
  • ๐ŸŒ Auto-discovery - detects and activates ELRS and TBS Crossfire/Tracer modules automatically (or type the IP)
  • ๐Ÿ›ก๏ธ One-click firewall - detects and adds the required Windows Firewall rule for you (the #1 "no data" cause)
  • ๐Ÿ”’ Single-source lock - if two modules are on the network, only one drives the joystick; pick a specific one by IP
  • ๐Ÿ“‰ Accurate metrics - high-resolution jitter/rate measurement
  • โ“ Built-in Help - a Help button with short tutorials for every feature
  • ๐Ÿชถ Light & CPU-friendly - minimize to the system tray to pause the on-screen bars and drop CPU to ~1% (the joystick keeps working); single-instance
  • ๐Ÿ“ฆ No install - self-contained single-file .exe, runs on Windows 7 SP1 through Windows 11 (64-bit)
  • โŒจ๏ธ CLI edition too - ELRSWifiJoystickCli.exe (~9 MB, instant start): the same engine and features in a console app - live channel readout, stats, firewall handling, --tx, plus interactive keys while running (s start/stop, t module IP/connect, p port, f firewall, q quit; also scriptable via stdin)
  • ๐Ÿ–ฅ๏ธ DPI-perfect - WPF vector rendering: crisp on every display scale (100/125/150/200%), including per-monitor DPI

๐Ÿš€ Quick Start

Option 1: Download Pre-built Release (Recommended)

  1. Download the latest release from the Releases page
  2. Install vJoy from vjoystick.sourceforge.net
  3. Extract the ZIP file and run ELRSWifiJoystick.exe
  4. Connect your ELRS TX module to WiFi

Note: The release package includes everything needed - no .NET installation required!

Option 2: Build from Source

Prerequisites

Build Steps

  1. Clone this repository

  2. Setup vJoy Libraries

    • Install vJoy from the official website
    • Copy vJoyInterfaceWrap.dll from C:\Program Files\vJoy\x64\ to the lib\ folder
  3. Build the Application

    Option A: Using Build Scripts (Recommended)

    # Development build (multiple files, good for testing)
    .\build.bat
    
    # Production build (single executable, good for distribution)
    .\publish.bat

    Option B: Manual Commands

    # Development build
    dotnet build -c Release
    
    # Production build (single executable)
    dotnet publish -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true

Build Scripts Explained

Script Purpose Output Use Case
build.bat Development build Multiple files (DLLs, runtime, etc.) Testing, debugging, development
publish.bat Production build (GUI) Single executable + ZIP distribution Distribution, deployment
publish-cli.bat Production build (CLI) Trimmed ~9 MB console exe + ZIP Lightweight/headless use

build.bat creates a development build with separate files, making it easier to debug and modify.
publish.bat creates a single-file executable perfect for distribution to end users.

Running the Tests

The engine and the view model have a full xUnit test suite (ELRSWifiJoystick.Tests/) covering the protocol (beacons, channel frames, malformed packets), the source-lock state machine, activation throttling, rate/jitter math, socket-level lifecycle (restart, port-in-use, clean shutdown), and the UI state mapping (banner, axis bars, log capping). Tests inject a fake clock/output/activator, so they need neither vJoy nor a module:

dotnet test ELRSWifiJoystick.Tests -c Release

๐Ÿ”ง Configuration

vJoy Setup

  1. Install vJoy from vjoystick.sourceforge.net

ExpressLRS TX Module Setup

  1. Connect to WiFi:

    • Put your ELRS TX module in WiFi mode
    • Connect to the TX module's WiFi access point OR connect it to your local WiFi network
  2. Access Web Interface:

    • Open http://10.0.0.1 or http://elrs_tx.local in your browser
    • ELRS should automaticaly send data for WIFI gamepad if connected

TBS Crossfire / Tracer Setup

Setup is the same as ELRS โ€” the module just needs to be on the same WiFi network. This uses the "Velocidrone Mobile" support built into the TBS WiFi module.

๐Ÿ›‘ Check your firmware first

Component Works Broken
Crossfire TX (XF) 6.31, 6.36 6.42 public, 6.48 beta, 6.48 public
WiFi module v2.17 up to v3.10 (v2.25.49mb recommended) v3.20

On a broken version the module streams normally but never sends stick data โ€” this app, VelociDrone Mobile, and every other client see the same dead stream, and nothing on the PC side can fix it. Details and source: firmware compatibility.

  1. Connect to WiFi:

    • Enable WiFi on the Crossfire/Tracer TX (WiFi module powered).
    • Either connect the module to your local WiFi network (recommended), or connect your PC to the module's own access point (tbs_crossfire_XXXXXXXXXXXX / 192.168.4.1).
    • Your PC and the module must be on the same network.
  2. Run the app โ€” no extra configuration needed:

    • The module continuously broadcasts a VELOCIDRONE discovery beacon (~every 8 s). The app detects it and automatically sends the activation request, then starts receiving channel data.
    • To skip the beacon wait and activate instantly, pass the module's IP: ELRSWifiJoystick.exe --tx 192.168.2.138 (find the IP on the module's WiFi web page).

How it works: the app POSTs action=joystick_begin to the module's /udpcontrol endpoint โ€” the same request ELRS uses โ€” and the module streams RC channels over UDP on port 11000. No radio-to-FC wiring, MAVLink, or ground-control software is involved; the WiFi module sends stick data directly.

๐ŸŽฎ Usage

  1. Run ELRSWifiJoystick.exe. The app opens, initializes vJoy, and starts listening automatically. The first time, accept the one-time Windows permission (UAC) prompt so the firewall lets the joystick data through.

  2. Watch the status banner:

    • ๐ŸŸ  Searching for moduleโ€ฆ โ€” make sure your module is on the same WiFi.
    • ๐ŸŸข Connected โ€” streaming โ€” the axis bars move with your sticks, and you'll see the packet rate and jitter.
  3. Use in your flight simulator: open VelociDrone / Liftoff / DRL etc., select "vJoy Device" as the controller, and calibrate the axes.

  4. Optional controls:

    • Module IP โ€” leave blank for auto-discovery, or type your module's IP and press Connect to target a specific module (skips the beacon wait; find the IP on the module's WiFi web page).
    • Port โ€” the UDP port (default 11000); change it while stopped.
    • Fix Firewall โ€” appears only if the firewall is blocking data.
    • Help โ€” opens short tutorials for every feature.
    • Minimizing to the tray pauses the on-screen bars and drops CPU to ~1% โ€” the joystick keeps working, so minimize while flying for best performance.
    • Closing the window centers the vJoy axes and releases the device.

Command-line (optional): ELRSWifiJoystick.exe [port] [--tx <module-ip>] โ€” e.g. ELRSWifiJoystick.exe --tx 192.168.2.138 pre-fills the module IP on launch.

Stopping the module's stream: the ELRS/Crossfire WiFi module has no remote stop command โ€” once activated it keeps broadcasting channel data until it is powered off, rebooted, or its WiFi drops. Closing this app only stops reading the stream; it does not (and cannot) stop the module from sending. This is a module-firmware behaviour, not an app limitation.

๐Ÿ“‹ Channel Mapping

The application maps ExpressLRS channels to vJoy axes:

ExpressLRS Channel vJoy Axis Description
0 (Roll) X Aileron/Roll control
1 (Pitch) Y Elevator/Pitch control
2 (Throttle) RX Throttle control
3 (Yaw) RY Rudder/Yaw control
4 RZ Auxiliary control
5 Z Auxiliary control
6 Slider 0 Auxiliary control
7 Slider 1 Auxiliary control

Note: Values are passed directly from the module (15-bit range: 0-32767) to vJoy without scaling or filtering for maximum precision and minimal latency. This applies to both ELRS and Crossfire, which share the same channel encoding.

๐Ÿ”ง Troubleshooting

Common Issues

Issue Solution
"vJoy driver not enabled" Install vJoy driver and enable device #1 in "Configure vJoy"
"vJoy Device 1 is already owned" Close other applications using vJoy device #1
"Waiting for joystick data..." Ensure the TX module is connected to WiFi; for Crossfire, wait for the VELOCIDRONE beacon or pass --tx <module-ip>
No joystick input in simulator Verify vJoy device is enabled and simulator recognizes "vJoy Device"
Crossfire not detected Confirm the module is on the same network (ping its IP); check the firmware versions below. Try --tx <ip> to activate directly
Crossfire axes look wrong/half-throw Channels are passed through as 15-bit like ELRS. If your radio's output differs, recalibrate the axes in the simulator
Connected but no data / axes don't move Windows Firewall is blocking the incoming UDP stream. The app adds a rule automatically (accept the one-time UAC prompt); if you declined it, click Fix Firewall in the app.
"module found, but it is sending no stick data" Unsupported Crossfire firmware โ€” see firmware compatibility

๐Ÿ›‘ Crossfire firmware compatibility (important)

Some TBS firmware versions break the WiFi joystick feature entirely. The module still streams frames at full rate, but they never contain stick data โ€” every channel holds a frozen placeholder (0xF26A = 62058 on all 16). This affects every client identically, including TBS's own reference client VelociDrone Mobile, so no PC-side software can work around it.

Component Works Broken
Crossfire TX (XF) 6.31, 6.36 6.42 public, 6.48 beta, 6.48 public
WiFi module v2.17 up to v3.10 v3.20

VelociDrone's developers confirmed the TX regression and reported it to TBS โ€” see TBS firmware breaks VelociDrone mobile wi-fi support. Downgrade with TBS Agent (desktop or Agent Lite on the radio); the TX and WiFi-module firmwares are updated separately.

How this app behaves on an affected version: a placeholder frame isn't channel data, so it never takes the source lock and never reaches vJoy. The status stays Searching with the detail "module found, but it is sending no stick data", and the log names the firmware fix once. The values are deliberately not clamped into range โ€” that would show every axis at 100% and hand your simulator full throttle.

โš ๏ธ Most common issue: "activated OK but no data" = Firewall

If the module activates (the app shows it found the module) but the axes never move, the inbound joystick stream is being dropped by Windows Firewall. Activation works because that's an outbound request; the joystick stream is inbound UDP, which Windows blocks by default.

The app handles this for you: on first run it detects the missing rule and adds it via a one-time Windows permission (UAC) prompt โ€” just click Yes. If you dismissed it, press the Fix Firewall button in the app.

Prefer to do it manually? Run this once in an Administrator terminal:

netsh advfirewall firewall add rule name="ELRS WiFi Joystick" dir=in action=allow protocol=UDP localport=11000

โ€ฆor Windows Defender Firewall โ†’ Allow an appโ€ฆ โ†’ add ELRSWifiJoystick.exe for both Private and Public.

Other network issues

  • Network: Ensure the PC and the TX module are on the same network/subnet. The app prints your PC's IPv4 address(es) at startup โ€” the module must be reachable from one of them.
  • Multiple adapters: VPNs and VMware/Hyper-V virtual adapters can confuse routing. If the app lists several IPs, try temporarily disabling unused adapters.
  • Port: Confirm UDP port 11000 isn't blocked by another firewall/antivirus.
  • WiFi: Verify the TX module actually joined the network and has an IP (check your router's device list). The ESP WiFi module is 2.4 GHz only.

vJoy Issues

  • Installation: Download vJoy from the official website
  • Permissions: Run as administrator if vJoy access is denied

๐Ÿ“Š Technical Details

Protocol Specification

  • Protocol: ELRS / TBS Crossfire WiFi Joystick Protocol ("Velocidrone Mobile" link)
  • Discovery: module broadcasts a beacon on UDP 11000 โ€” ELRS (ExpressLRS) or VELOCIDRONE (TBS Crossfire/Tracer). The app detects it and activates the module.
  • Activation: HTTP POST http://<module-ip>/udpcontrol with form body action=joystick_begin&interval=10000&channels=8. The module replies ok and begins streaming. (Activation POSTs are throttled to once per 5 s per module.)
  • Transport: UDP packets on port 11000
  • Packet Format:
    • Byte 0: Frame type (1 = channels)
    • Byte 1: Channel count (4-16; Crossfire always sends 16)
    • Bytes 2+: Channel data (16-bit little-endian per channel)
  • Value Range: 0-32767 (15-bit precision)
  • No-data / corrupt frames: a channel with no data holds the placeholder 0xF26A (62058) โ€” a value a real channel can never reach. All 16 channels sit at it while the module has no input (unsupported firmware, radio off), and under fast stick movement the module occasionally emits a corrupt frame mixing placeholders with garbage. Any frame containing the placeholder is dropped โ€” it never takes the source lock and never reaches vJoy (mid-stream, the last good values are held for the ~11 ms gap). Values slightly above 32767 without the placeholder are legitimate stick overshoot past a wide endpoint and are clamped to full deflection.
  • Update Rate: ~90-100 Hz typical
  • Single-source lock: the app binds to the first module that streams real channel data and ignores any other source until the bound one is silent for 3 s, so two radios on the same network can't interfere.

Performance Characteristics

  • Latency: < 10ms from TX to vJoy
  • CPU Usage: Minimal (< 1% on modern systems)
  • Memory: ~10MB runtime memory usage
  • Network: ~1KB/s bandwidth usage

vJoy Integration

  • Library: vJoyInterfaceWrap.dll for Windows virtual joystick creation
  • Axes: Supports up to 8 axes per vJoy device
  • Processing: Direct pass-through of values for minimal latency
  • Filtering: No smoothing or filtering applied (raw input for precise control)

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿค Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

Reporting Issues

When reporting issues, please include:

  • Windows version
  • vJoy version
  • ELRS firmware version
  • Steps to reproduce
  • Console output/logs

๐Ÿ™ Acknowledgments

  • ExpressLRS - The amazing open-source RC link system
  • vJoy - Virtual joystick driver for Windows
  • .NET Community - For the excellent development platform

Made with โค๏ธ for the ExpressLRS community

โญ Star this repository if you find it helpful!

About

Turn an ExpressLRS (ELRS) or TBS Crossfire/Tracer WiFi module into a vJoy virtual joystick on Windows for FPV simulators like VelociDrone and Liftoff. No cables, no MAVLink.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages