New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Long Range Streaming #2113
base: master
Are you sure you want to change the base?
Long Range Streaming #2113
Conversation
@qqqlab I like the idea behind this PR, can you fix the conflicts with current master. I like the idea of a flag for switching stream mode on if both TX and RX agree. |
@pkendall64 Thanks for the feedback. I've fixed the conflicts with the current master. |
I've improved the structure of the Stream OTA packet to make it more flexible and future proof, see updated PR description. The only ESP32 receiver with PWM pins I could find in targets.json is the Radiomaster ER6-GV, which is apparently not released yet. So, I'm soldering together a DIY ESP32 receiver now, to do further testing with 2 serial ports on a receiver. |
@pkendall64 I think this PR is ready for an initial review, see updated PR comment. I removed PR Draft status. Unfortunately some STM32 targets are failing due to code size. I'm looking forward to your feedback. |
why do you want to split incoming data on the RX side into 2 UARTs? If you transfer data OTA serially (halve duplex even) then it should be possible to feed the data consumer serially using only one UART, shouldn't it? you want an additional UART on the TX be hardwired with a computer to send serial data? BLE is the way, imo |
@flux242 Thanks for your feedback. For my use case I wanted to have a second RX UART to communicate directly with a companion computer on the drone. Of course there are other ways to achieve this, but to me this appeared to be the cleanest solution without needing additional hardware or flight controller modifications. The second UART on the TX (or RX) can for example be used for BLE or WIFI, either externally via a physical UART link or internally by including BLE/WIFI in the ELRS firmware. Adding a physical second UART keeps all options open, at the cost of two additional solder pads. A setup which should work out the box, is this:
(I didn't find the time yet to try this out.) |
@qqqlab that's the point -- you need an additional HW on the RX side, namely an additional UART which is not always easy to get on the FC side. I understand your point to use existing SW framework on the FC side (inav supports it this way I suppose), so splitting the data was the easiest way to implement the feature. The only question of mine is - is this really necessary? Can inav parse incoming data and split it in SW? If yes then no HW changes would be necessary Edit: but anyway - your solution is an improvement of the Airport implementation where 2 radio links are necessary which is obviously an overkill |
@flux242 Yes, the FC could do the splitting and that would save the additional hardware interface. However, I don't think any current FC firmware supports this, so for each FC firmware (inav, ardupilot, px4, betaflight, kiss, dji, you name it) additional programming would be needed. Not to mention that somebody has to dream up a splitting specification, and enforce it. Decent FC hardware has 5+ UARTs, so sacrificing a FC UART and soldering two additional wires appears to me the quicker/easier/more reliable solution. |
with the work being done on the mavlink-rc branch, is this still useful? |
should not be this PR closed? |
ExpressLRS appears to be focused on the "Express" part of the name, i.e. low latency racers. This PR focuses on the "LRS" part: Long Range Streaming.
Technical Details
Streaming Data
The new OTA stream packages that replace the MSP and TLM packages have the following structure:
Main header (one byte):
packetType: 2 bits - the ELRS packet type, to stay compatible with current ERLS implementation
ack: 1 bit - acknowledge the receipt of the previous package, should be added to all package types.
seq: 1 bit - a one bit sequence counter, used to differentiate re-transmits from new transmits.
type: 3 bits - type of the next part of serial data stream (Types are: Command, CRSF, and SERIAL, plus 5 types for future expansion)
more: 1 bit - to indicate that the package contains more parts
Each additional part in the steam package has the following additional one byte header:
len: 4 bits - the length of the part (1-16 bytes)
type: 3 bits - type of the next part
more: 1 bit - more parts follow
To simplify the code, the same headers are used for OTA4 and OTA8. The RC and SYNC packages remain unchanged.
Additional Serial Port
With the defines
GPIO_PIN_STREAM_RX
,GPIO_PIN_STREAM_TX
andSTREAM_BAUD
an additional serial port can be opened on both the TX and RX. Data send to this port is transmitted to the port on the other device. Serial data, RC channel data and CRSF bidirectional telemetry data are transmitted simultaneously.Backwards Compatible With V3.2
A handshake is used to set both TX and RX to stream mode, if both sides have this capability. The TX send stream packets as TLM (type 3), the RX sends stream packets as MSP (type 1). This flow is the opposite direction as used in the V3.2 implementation, and stream packets are completely ignored by V3.2 devices. After connection a V3.3 device sends a couple stream packets; if the other device is also V3.3 they both switch to stream mode.
Future Expansion Options
ack
andseq
flags are in place, need to add code to manage the retries. Add lost connection check so that the transmitter doesn't keep re-transmitting everything when no replies are received. Need to have a close look at non-1:2 telemetry ratio operation.Results
Below the test results when sending concurrent rc data, max CRSF data uplink (ul) and max CRSF data downlink (dl).
Tools for testing:
https://github.com/qqqlab/ExpressLRS/blob/pr_attachments/CRSF-Rate-RX.py connected to receiver UART
https://github.com/qqqlab/ExpressLRS/blob/pr_attachments/CRSF-Rate-E.lua running on EdgeTx Radio
Additional Serial Port
To enable the optional serial data port a second UART is needed both on the TX and RX side. For DIY hardware this is easy to achieve, for commercially available hardware a bit more difficult.
Most commercial TX devices have a debug/backpack UART which could be used for serial data.
For commercial RX it is not so easy as most devices only break out a single UART. I see the following options:
Seeing the rate at which new commercial hardware enters the market, I expect updated hardware soon after new software capabilities are available.
Analysis of ELRS V3.2
The TX sends 3 types of OTA packages: RC, SYNC and MSP. The RX only sends TLM type packages. The RC and SYNC packages are single package messages, the MSP and TLM are multi package messages. The MSP and TLM messages have the following properties:
Limitations:
The current setup works fine for sending occasional telemetry back and forth. However when trying to fully load the link, it sometimes collapses so badly that nothing gets through anymore, see #2088. I've submitted a couple of PRs to patch the current setup, but some issues can't be patched without making incompatible changes. This being the case, I thought it might be a good idea to try a new design.
The new design is similar to the https://github.com/ArduPilot/SiK radio design. It streams data, instead of packetizing data. As the OTA data is CRSF, it can be streamed, no need to re-package it. Additional synchronization is not needed, as the CRSF stream will self-synchonize: CRSF has 18 'sync' bits: 8 bit sync byte, 2 zero bits in length, 8 bit crc, so in a random byte stream there is only a 1/250000 chance of a mismatch.
The internal ELRS commands have to be converted to CRSF messages, or handled separately. I chose the second option, such that an ELRS command is always sent as single OTA package and it jumps the CRSF queue.