Skip to content

Add support for SRXL2 as ESC protocol #11184

Description

@RobertoD91

Current Behavior

I installed INAV on an E-flite Super Timber 1.7, which includes a "Spektrum Avian Smart Lite ESC".
This ESC can be controlled using:

  • classic PWM, without telemetry or reverse
  • "Smart Throttle", which is SRXL2 and includes telemetry (battery, RPM, current, etc.) and motor reverse

This amazing project dgatf/msrc#152 discovered that it uses SRXL2 and programmed an RP2040 to act as a converter, allowing this and other ESCs to be used with non-Spektrum receivers.

Desired Behavior // Suggested Solution

Adding SRXL2 as an ESC protocol in iNav

Who does this impact? Who is this for?

Adding SRXL2 as an ESC protocol would allow the use of Spektrum ESCs without an external RP2040.
This could be very useful for flight controllers like the RadioMaster Nexus.

Additional context

This is not critical; it may be a "nice to have".
Thank you for this awesome work :)

Activity

  1. silicongarage commented on May 16, 2026

    @silicongarage

    @RobertoD91 I'm adding my vote for this feature. This is a pathway for newer PWM flight controllers that don't route the battery voltage through themselves but are powered indirectly via BEC (ie; Nexus-XR) to have access to parameters like Current.

  2. RobertoD91 commented on Jul 29, 2026

    @RobertoD91
    ContributorAuthor

    I'm doing a quick MVP using AI on my fork. Throttle via SRXL2 works 🥳. Telemetry and reverse are still to be tested.

    Tested with a MATEKF405SE.

    A couple of questions:

    • Since adding the SRXL2 ESC protocol also requires configurator changes, I should target INAV 10 (maintenance-10.x), correct?
    • For reverse, I don't think reusing the "reversible motors" (3D) feature is the right choice. It seems more suited to 3D drone flight or rovers/boats. The idea is to add a dedicated AUX mode that drives the ESC's SRXL2 reverse channel instead. Does this make sense?
    • The current implementation doesn't use the classic PWM/DSHOT pins. It uses a serial port.
    • The current scope is a single ESC on motor 1, which is typical for fixed-wing aircraft.

    Of course, before opening a PR, I'll do a complete cleanup. If it turns out not to be suitable for the project, I would understand and leave it as a starting point for more experienced developers.

  3. RobertoD91 commented on Jul 30, 2026

    @RobertoD91
    ContributorAuthor

    Ok, seems to work. Tested with:
    ESC: Avian Lite 85A (SPMXAE85A)
    MOTOR: Spektrum SPM-1003 5055-500Kv, 14 pole

    Based on maintenance-10.x.

    Throttle and reverse work (added a "reverse" modes in the configurator).
    Telemetry reports voltage, current and RPM (I have no way to verify
    the RPM value is accurate, though).

    Bug: if the FC reboots, the handshake with the ESC fails and the ESC
    needs a power cycle to reconnect.

  4. RobertoD91 commented on Sep 6, 2026

    @RobertoD91
    ContributorAuthor

    related discussion: #10255

  5. UltraFly commented on Sep 6, 2026

    @UltraFly

    Hello, I had a look at your implementation, I'm very interested in you findings and working on this subject also. As i understand you "hard code" reverse on channel 7. I'm interested in forwarding all controls on the SRXL2 bus so that the reverse function works whatever revere channel was selected and in the goal of getting TexGen to work as well for remote ESC configuration (bec voltage, timing etc...). I'll say more about this when i make progress

  6. RobertoD91 commented on Sep 7, 2026

    @RobertoD91
    ContributorAuthor

    @UltraFly this code is based on msrc dgatf/msrc#152 . And as i can see also ArduPilot ported it, maybe it would be useful to give a look to the ardupilot version? ArduPilot/ardupilot#27603

  7. RobertoD91 commented on Sep 7, 2026

    @RobertoD91
    ContributorAuthor

    Some note by claude:

    Useful details from our bench work (MATEKF405SE + Avian Lite 85A SPMXAE85A):

    Reverse channel: yes, hardcoded — mask 0x41 = throttle ch1 + reverse ch7 (mapping from the msrc project, confirmed working on the Avian). The channelData payload is mask + one uint16 per set bit in ascending channel order, so forwarding all channels is a small extension of srxl2EscSendControlPacket() in src/main/drivers/srxl2_esc.c. Note the architecture: here the FC is the SRXL2 bus master and no Spektrum receiver is on the bus (RC is CRSF on another UART) — "forwarding" means building mask/values from the FC's RC channels, not passing receiver frames through.

    Pitfalls that cost us real time:

    • Channel values: full 16-bit = ±150% travel, 32768 = center. Raw 0 as throttle is invalid (−150%): the ESC answers telemetry polls but keeps beeping "no signal". Use the ±100% band 0x2AA0..0xD554.
    • Handshake: the ESC accepts channel data only after the final broadcast handshake (destID 0xFF). Also answer its unprompted handshake (src 0x40, dest 0x00, sent after 50ms of silence). Keep baudSupported = 0 unless you actually switch to 400k — advertising 1 makes the ESC change baud on the broadcast.
    • Electrical (STM32): plain half-duplex open-drain + pull-up on TX (like Betaflight's SRXL2 driver); push-pull floats the line between frames. We wait ~300µs after the last RX byte before transmitting.
    • Telemetry: poll with replyID 0x40 every Nth control frame; RPM in the XBUS ESC block is electrical — divide by pole pairs.
    • debug_mode = SRXL2 in the branch exposes frame/CRC/handshake counters in the Sensors tab — that's what cracked most of the above.

    Known open bug: FC warm-reboot with the ESC still powered → re-handshake never completes, ESC needs a power cycle. After 50ms of silence the ESC resets and becomes a master candidate (unprompted handshakes); that sequence doesn't converge yet. Under investigation.

    TextGen: menus ride the polled telemetry replies, but the config direction is the SRXL2 Parameter packet (0x50) — marked "TODO: Add later" in the official spm_srxl code, so that's unexplored ground. If you get 0x50 working I'd be very interested.

    More detail in https://github.com/RobertoD91/inav/blob/claude/esc-spektrum-protocol-check-i5b6jx/docs/SRXL2_ESC.md

  8. MrScothh commented on Sep 16, 2026

    @MrScothh
    Contributor

    There is now a PR for this: #11947, open against maintenance-10.x, with the Configurator side in iNavFlight/inav-configurator#2770.

    It adds motor_pwm_protocol = SRXL2 - motor output over the ESC's Smart Throttle wire, ESC telemetry feeding the existing sensor layer and the RPM filter, thrust reverse as a THRUST REVERSE mode, throttle-range calibration from the Outputs tab or esc_calibrate, and one ESC per serial port for multi-motor models. Written against the published specification and validated against Spektrum's own library compiled as the device side, then on an Avian 70 A.

    Some of what came up on the bench answers things said in this thread.

    The reboot problem is real, and it is not fixable in software. One of the notes above reports that the handshake fails if the FC reboots and the ESC needs a power cycle - that matches exactly what we measured. An Avian announces itself six times in the 300 ms after it powers up and is mute from then on: against a running one, 128 handshakes to its address, 128 broadcasts, 128 spread across 0x40..0x4F and 319 control frames requesting telemetry all drew zero replies. So the link is made at power-up or not at all, and a board that reboots under a connected battery never gets it back. The PR therefore refuses to arm while the link is missing, rather than arming into a motor that is not listening - which looks identical to a working model right up to the point the throttle does nothing.

    @UltraFly - two things you raised:

    Reverse channel. It is a setting, not hardcoded: esc_srxl2_reverse_channel, which must match the channel the ESC's own Thrust Rev. menu names. Spektrum document 5 to 9 with 7 as the factory default, and anything outside that is normalised to "off" at boot rather than offering a mode the ESC cannot act on.

    Forwarding all channels. We went the other way, and the measurement is worth having because it corrected our own earlier belief. Holding the telemetry request rate fixed, frames carrying one channel, two adjacent, two spread apart, four and eight all produced the same throttle and the same rpm from the same command - the ESC reads CH1 and the channel its Thrust Rev. setting names, and ignores the rest. So the frame carries just those two, which is twelve bytes a frame less on a wire the telemetry reply has to share. If a model turns up that needs more, widening the mask is a one-line change to how it is built.

    TextGen. The ESC's text menu is readable and writable over the same wire - that is how its fifteen parameters can be set without a Spektrum transmitter. We kept it out of the firmware and put it in a separate tool (https://github.com/MrScothh/smart-esc-tool) which talks either to a USB adapter or through INAV's MSP passthrough, so the flight code stays on the flying path. If someone wants it in the firmware instead, the framing is all in the PR already.

    One more thing anyone implementing this will hit: do not request telemetry on every control frame. At 50 Hz the ESC keeps the link and keeps answering, and quietly stops obeying the throttle - 0.0 % reported from every stick position. Asking every second frame restores it immediately, with no power cycle. It cost us a day to find, so it is worth knowing in advance.

  9. UltraFly commented on Sep 22, 2026

    @UltraFly

    I'm interested in testing this new feature, i have a avian lite 6s 85A, an avian 6s 100A and and avian 6s 130A

  10. MrScothh commented on Sep 23, 2026

    @MrScothh
    Contributor

    @UltraFly thanks, that would help a lot. So far it has run on an Avian 70 A and on @RobertoD91's Avian Lite 85 A, so your 100 A and 130 A are the ones nobody has tried yet, and a second Lite 85 A is welcome too.

    It's merged into maintenance-10.x, and there's no 10.0 release candidate yet, so the nightlies are the way to get it: firmware v10.0.0-20260922.434 or newer (enabled by default on F405, H7 and AT32 targets), and Configurator v9.1.2-20260922.229 or newer, which has the Ports and Outputs settings for it. The nightly page recommends a full chip erase.

    Setup is in docs/Spektrum Smart ESC.md: the ESC's signal wire goes to the TX pad of a UART set to Spektrum Smart ESC (SRXL2), and the motor protocol is SRXL2. One correction to that page first: the red wire is the ESC's BEC output, and its voltage is set in the ESC (6.0 V on my 70 A), so don't connect it to the flight controller's 5 V pad. The wiring table says otherwise; #12017 fixes it.

    Before flying, please:

    • keep the propeller off for all bench work;
    • run the throttle range calibration: uncalibrated, the 70 A used only 59% of the channel;
    • if you use reverse, check with the prop off that the motor doesn't spin backwards at minimum throttle.

    What would help most, for each ESC: whether the link comes up when you plug in the battery, whether voltage, current, rpm and temperatures look right, whether calibration and reverse behave as described, and a diff all with a short Blackbox log if something is off.

    Two things you may hit that are already known: telemetry drops out for up to a second now and then, which #12002 fixes and isn't merged yet; and if the flight controller reboots with the battery still connected, the ESC won't answer until you unplug and replug the battery, which is the ESC's behaviour, not something the firmware can work around.

    To read or change the ESC's own settings without a Spektrum transmitter there's https://github.com/MrScothh/smart-esc-tool, which works through the flight controller.

    As far as I know nobody has flown it yet, so please treat the first flights with that in mind.

  11. MrScothh commented on Sep 23, 2026

    @MrScothh
    Contributor

    @UltraFly one correction to the builds I pointed you to: the Configurator nightly still accepts only firmware below 10.0.0, and the firmware nightlies have been numbered 10.0.0 since 22 September, so that pair connects in CLI only ("firmware not supported"). Use the last firmware nightly before the version bump instead, v9.1.1-20260922.433, which already has SRXL2, with the same Configurator nightly. Sorry about that.

    @sensei-hacker for when you have a minute: the Configurator's maintenance-10.x has the same limit. maxFirmwareVersionAccepted in js/data_storage.js is still '10.0.0' after the bump in iNavFlight/inav-configurator#2793, so it refuses its own 10.0.0 firmware. Happy to send the one-line change if that helps.

  12. sensei-hacker commented on Sep 23, 2026

    @sensei-hacker
    Member

    @sensei-hacker for when you have a minute: the Configurator's maintenance-10.x has the same limit. maxFirmwareVersionAccepted in js/data_storage.js is still '10.0.0' after the bump in iNavFlight/inav-configurator#2793, so it refuses its own 10.0.0 firmware. Happy to send the one-line change if that helps.

    Thanks for that. That should be fixed permanently in iNavFlight/inav-configurator#2800

  13. UltraFly commented on Sep 28, 2026

    @UltraFly

    I can confirm that ESC telemetry is coming through from my Spektrum Avian Lite 85A on a RadioMaster NEXUS-XR. I also have a 4000 mAh Spektrum Smart Battery that I’ll be testing.
    A few questions:

    1. Simultaneous power-up: When the FC and ESC start together from the ESC’s BEC, the link fails to establish. Powering the FC over USB first, then powering the ESC, works. Is this a known limitation? Could INAV’s startup delay cause it to miss the ESC’s initial discovery window?
    2. Normal ESC connector: Does upstream support Smart ESC operation through the NEXUS-XR connector marked ESC/S5, or does it currently require moving the signal to a UART TX pad? S5 uses PA9, which supports UART1 TX. Is support for this normal connector planned?
    3. Separate BEC voltage: Is there a plan to expose VBEC, measured locally by the FC on its electronics/servo supply, separately from VBAT, the flight-pack voltage? This would be particularly useful when VBAT comes from ESC telemetry. I mean the actual supply measured at the FC, independently of any BEC voltage reported by the ESC.
      For context, I’m compiling recent INAV and Configurator sources, with local NEXUS-XR target changes on the firmware side.
  14. RobertoD91 commented on Sep 29, 2026

    @RobertoD91
    ContributorAuthor

    I also have a 4000 mAh Spektrum Smart Battery that I’ll be testing.

    Hi @UltraFly, slightly OT, but this could actually be very useful.

    The Smart Battery was the last missing piece in the original MSRC work that inspired this issue. If I remember correctly, some of the battery-specific telemetry fields were never fully analyzed because we didn't have a Smart Battery available to capture the SRXL2 traffic.

    If you have an RP2040, you can flash MSRC, and it would be great if you could capture the missing telemetry fields while using the 4000 mAh Smart Battery. It could help complete the analysis of the battery telemetry data.

    For reference: dgatf/msrc#152

  15. UltraFly commented on Sep 30, 2026

    @UltraFly

    Hello @RobertoD91 I don't have a MSRC. I'm developing on a Radiomaster Nexus XR with inav flashed on it. I have a merge request pending for adding spektrum smart battery support, you might be able to get the info you need from that:
    #12077 (comment)

  16. MrScothh commented on Sep 30, 2026

    @MrScothh
    Contributor

    @UltraFly thanks for testing. Answers to your three questions, and two PRs for the first two.

    1. Simultaneous power-up. Yes, a bug on the INAV side, and your guess about the startup delay is right. I reproduced it with an Avian 70A and a Lucid H7 Wing on one bench supply:

    • the Avian sends its handshakes between 42 and 243 ms after the board's reset, and one left unanswered never speaks again, whatever it is sent afterwards;
    • INAV opened the SRXL2 port only at 325 ms, after the USB init's waits, and the driver first ran from its task at about 5.8 s.

    #12085 fixes it: a board set to SRXL2 opens its ports before the USB init and keeps the ESC fed with frames until it answers, which on the bench took 349 ms. It also keeps answering during the fixed waits later in the start-up, so an ESC powered up to about 1.3 s after the board links too. What is left is an ESC powered while the rest of INAV starts up (sensors, SD card, OSD, a few seconds on my board): that one still needs a battery replug.

    That rest of the start-up leaves the ESC without frames for about 4 s, and I checked what that does with the motor turning: an Avian still starting when its frames stop starts over, so with #12085 arming is allowed about 16 s after the battery goes in, when the motor really answers. The same measurement showed that the arming check let a model arm before the Avian obeys the throttle, which it does only about 9 s after it powers up: #12084 raises that wait to 10 s, and #12085 is stacked on it.

    One correction to what I wrote above on 23 September: a flight controller that reboots with the battery connected does get the ESC back. A linked Avian that loses its frames announces itself again, and the board links it; I measured that over a restart of about 6 s and over a firmware flash.

    2. The ESC connector. #12087 adds it, with iNavFlight/inav-configurator#2814 for the Configurator: on the NEXUS X/XR, the NEXUS and the Vantac RF007, a new option puts the Smart ESC on the ESC connector as motor 1, by moving UART1's TX to that pin. It is off by default. The FlyDragon Pro's ESC connector is UART4's TX already, so there the PR only adds the driver. To try it on your XR:

    1. Ports tab: turn MSP off on UART1. INAV turns it on there by default when the board has USB, and the connector only uses a UART with no function.
    2. Outputs tab: ESC protocol SRXL2, then turn on "ESC on the board's ESC connector (uses UART1)". Save and reboot.

    Without the Configurator part, the CLI does the same: serial 0 0 115200 115200 0 115200, set motor_pwm_protocol = SRXL2, set esc_srxl2_connector = ON, save. I tested it on a Lucid with a connector defined only for the bench, not on a NEXUS, so your XR would be the first real one.

    3. VBEC. Planned next. Your XR, like the NEXUS, the RF007 and the FlyDragon Pro, has the BEC rail on an ADC pin that INAV reads nothing from; I'll open it separately.

    Your #12077 touches the same files: it merges cleanly with the power-up PR, conflicts with the connector one on a single line, and with #12086 (the driver's state moved out of the main RAM) in the ESC struct, where smartBattery goes back among the 4-byte fields. I'll rebase mine if yours goes in first. It also changes the flight controller's ID to 0x21; my power-up measurements were made with 0x31, so I'll run them again with 0x21.

  17. MrScothh commented on Oct 1, 2026

    @MrScothh
    Contributor

    @UltraFly the separate BEC voltage you asked about is in #12089, with iNavFlight/inav-configurator#2816 for the Configurator. The NEXUS X/XR, like the NEXUS, the RF007 and the FlyDragon Pro, now measures its servo rail on PC1 with Rotorflight's scale (620 on the X/XR). It shows in status, in the Configuration tab and in an OSD element that blinks below a warning voltage you set.

    On taking it from the Smart ESC instead: my Avian 70A leaves the BEC fields of its telemetry empty, so #12089 only measures on the board. For your Avians I opened draft #12090, a test build with both, the board's measurement and the fallback. The steps are in its description. What I need is the status output with each ESC powered, and a multimeter reading of the servo rail if you have one: the 620 scale comes from Rotorflight and nobody has checked it on INAV yet. The 100A and the 130A interest me most, since your #12077 counts my 70A among the Lite ESCs, like the 85A. If one of them fills the field, the fallback becomes a PR of its own.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions