ExpressLRS integration for Orqa FPV.Connect

Motivation

Since starting to fly FPV drones about two years ago I steadily upgraded my gear. I settled on ExpressLRS for my radio link because of the superb featureset, speed and range as well as a super low price for individual components. One of the features that ExpressLRS offers is the support of so called Backpacks, that integrate the video receiver with the system to enable automatic band and channel switching.

For my FPV goggles I decided on the excellent Orqa FPV.One Pilot that I fitted with a Rapidfire module. The right module bay of the Orqa goggles can be fitted with the FPV.Connect module, that adds WiFi connectivity to the goggles as well as a port to fit an ImmersionRC Ghost Atto receiver to integrate the goggles with that RC-system. Orqa offers documentation on this feature in their Blog.

Inspired by this I wanted to get the best of both worlds and started reverse engineering the protocol used to communicate band and channel switches to the goggles.

First attempts

Initially I assumed that the goggles would just act as a IRC-Tramp slave device and ignored the transmit power and pit mode parts of the information received. To test this I connected a flight controller to the Tramp and GND pads of the FPV.Connect module. This turned out to not be the case and didn’t work.

Getting to know the protocol

While researching the topic I stumbled upon a Blog Post by Igor Mišić about the ImmersionRC Ghost protocol. I contacted him and he kindly provided me with logic analyzer recordings of a working Ghost integration from his own Orqa goggles. Again: Thank you very much for your awesome support!

Turns out, the Atto Rx sends Ghost frames to the goggles, but using 100 kBaud on the Tramp pin when bound as a Goggles1 receiver.

The messages of type 0x20 contain the frequency to tune to, the band and the channel and the receiver also relays the stick positions to the goggles (?) as well. For my implementation I didn’t bother with RSSI and stick position messages and just stuck with the 0x20 messages instead.

Implementing a solution

After forking the Backpack project, I created a new target definition for the Orqa FPV.Connect integration and implemented the protocol. A little translation was needed to map the Bands and channels from their ELRS representation (index into a frequency table with 48 entries) to the Ghost representation (band, channel and frequency in separate fields). I also needed to add a function call to the Backpack main loop to periodically transmit the Ghost messages every 20ms to mimic the Atto receiver, this could potentially be slowed down or omitted entirely and needs some more testing (maybe the goggles don’t care and you can just send messages when the value actually changes).

The hardware

I struggled a bit when it came to the hardware. I planned on using a spare HappyModel EP2 receiver I had lying around but it didn’t work at all when I connected it to the FPV.Connect module. Turns out the Atto just needs 3.3V and the module doesn’t provide 5V on that pin. I grabbed a multimeter and found a place where I could grab 5V from a capacitor I could solder to. Additionally the Tramp pin would be connected to the Rx pin of the EP2 if connected straight through. A little Googeling later I gave up on trying to swap Rx and Tx pins and just soldered a small bridge from the EP2s Tx pin to the Tramp pin on the FPV.Connect module.

Photo of a HappyModel EP2 receiver mounted on FPV.Connect module
Photo of a HappyModel EP2 receiver mounted on FPV.Connect module

Pull request

After some testing I decided to create an initial pull request that adds my functionality to the Backpack codebase. If I can optimize some of my crutches (like the use of an Orqa::Loop() function) away I will push them as well.