-
Notifications
You must be signed in to change notification settings - Fork 15k
dshot: Extended Telemetry and EEPROM support #26263
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
base: main
Are you sure you want to change the base?
Conversation
|
This pull request has been mentioned on Discussion Forum for PX4, Pixhawk, QGroundControl, MAVSDK, MAVLink. There might be relevant details there: https://discuss.px4.io/t/px4-dev-call-jan-14-2026-team-sync-and-community-q-a/48289/1 |
🔎 FLASH Analysispx4_fmu-v5x [Total VM Diff: 8396 byte (0.4 %)]px4_fmu-v6x [Total VM Diff: 8428 byte (0.41 %)]Updated: 2026-01-28T06:35:08 |
|
Reviewers maybe we should coordinate and split the review so its faster and easier on everyone, please coordinate on the maintainer channel on discord so we can get this moving! |
How much latency does this introduce? And why not do it in parallel per timer? For the boards that I recently worked with there seemed enough DMA channels available anyway. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need uint8_t in dshot_motor_data_set for imxrt in https://github.com/PX4/PX4-Autopilot/pull/26263/files#diff-ee11cd0da359496d5246d1e4759d08dee22fa735d4c4aed71afe1547eb55d56fR616
See above plot from the bdshot_analyzer.py. The inter channel gap mean is 78us and the max is 138us. This is negligible in the context of 800Hz control loop. For comparison, a 4KHz control loop rate is 250us intervals. The IMU_GYRO_RATEMAX param only goes as high as 2KHz.
There is a race condition. Both timers finish burst complete at about the same time. The callback which sets up capture for the first timer takes too long. By the time the capture is set up for the second timer, the response frame has already started. So the second timer capture/compare consistently misses the first part of the response. |
That's with 8 outputs or 4? And At fastest DShot 600 I assume? |
It's with 2 timers and dshot300. The "inter channel gap" is the time delta between Timer1 capture complete and Timer2 burst start. It doesn't matter if it's dshot150/300/600, the time delta is composed of the delay in |
|
But wouldn't the capture complete be later/slower depending on the DShot variant. I guess I'm still confused. |
DShot150 frame length is twice as long as DShot300 (~100us vs ~50us). Same goes for capture (~70u vs ~140us). At DShot150 you can expect a 240us delta between Timer1_Burst and Timer2_Burst. This is negligible for motor control. The interval between Timer1_Burst_N and Timer1_Burst_N+1 and Timer2_Burst_N and Timer2_Burst_N+1 is consistent and within the min/max as show in the image above (Channel A/B Frame Intervals) |
|
Having some trouble getting ESC_EEPROM stream to show up in QGC / mavsdk. FC: imxrt based / V6X-RT Tested with both EDT enabled and EDT disabled (although EDT seems to be not implemented for imxrt currently: https://github.com/PX4/PX4-Autopilot/pull/26263/files#diff-ee11cd0da359496d5246d1e4759d08dee22fa735d4c4aed71afe1547eb55d56fR534). Is the understanding correct that ESC_EEPROM / ESC settings should show up fine with standard BDSHOT telemetry (without EDT, without serial telemetry)? |
You need serial telemetry because that's how the ESC settings are sent. The settings are requested from one ESC at a time via .dshot command and sent over the serial line. You don't need EDT. Also set DSHOT_ESC_TYPE=1 for AM32. |
If you can't use the telemetry wire on your drone/esc setup you can also flash this |
Thanks for the pointer, will give this a spin. Was hoping to avoid external configurators =>> might end up with CAN ESCs instead. |
Is it? That was definitely not my assumption based on the fact that people fly 1kHz or 2kHz loops, just to get the gyro loop response time down. |
I mean the devil is in the details. If you are trying to run 2kHz loop rate, dshot150, and using 3+ timers then yes you're going to have problems. Not every combination can be perfectly supported, I think we should optimize for the 99% case. I think the 99% case looks like 800Hz to 2kHz, 1 to 2 timers, and dshot300 or dshot600. Another thing to consider is most people running high loop rates are likely flying freestyle quads, and these should have all 4 motors on the first timer (I know not all do... but the hardware designer should think about these things) Alternatively we can try to fix the race condition by optimizing timer reconfiguration time and maybe even stagger the bursts ever so slightly rather than stagger them sequentially. @julianoes what would you suggest? Or what is your preference? |
|
@dakejahl do I understand correctly that we have to make a trade-off either in response latency, so how quickly the burst ends up on the wire, or whether we can get the RPM feedback of all motors or only one channel per timer per round? If so, then I would strongly lead towards having no latency to the motor output and RPM feedback at a slower rate. |
7e0038b to
73052cc
Compare
|
The core issue is that when you burst both timers at the same time the telemetry response frame also comes at the same time. There is only 30us between burst complete and the response frame being received. It takes longer than 30us to setup capture-compare on the first timer (because of all the timer code overhead). This means by the time the capture-compare setup for the second timer takes place, we've already missed some of the response frame bits. On this branch it's 100% error rate. On your other branch it's 10-20% error rate. Triggering the timer burst sequentially (or even just staggering them by 5-10us) solves the problem. Triggering sequentially comes with the added benefit of reducing the required number of available DMA streams, with the tradeoff of added latency from output calculation to on-the-wire for each timer after the first (+75us nominal) |
|
@dakejahl Oh, ok I'm starting to understand. Let me think about it. |
|
This pull request has been mentioned on Discussion Forum for PX4, Pixhawk, QGroundControl, MAVSDK, MAVLink. There might be relevant details there: https://discuss.px4.io/t/px4-dev-call-jan-21-2026-team-sync-and-community-q-a/48330/2 |
|
Testing 4 outputs over 2 timers on CubeOrange: @dakejahl any idea why Ch2 is showing errors? |
|
And here is a test on just the first 4 motor outputs on the Holybro Kakute H743-Wing: |
…ly if a board has serial config
…s to work around race condition
Co-authored-by: Julian Oes <[email protected]>
Co-authored-by: Julian Oes <[email protected]>
Some timer channels such as timer 4 channel 4 don't support DMA, so we can only use them to burst/update but not to capture.
412d553 to
b26b3ac
Compare
hamishwillee
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to assume docs will magically appear at some point. Happy to help.
This makes it consistent with the 12 motor output functions.
For some boards, we can have DShot on 12 to 14 timer channels, so we need to support up to 16 to have them covered.



Summary
Major refactoring of the DShot driver adding Extended DShot Telemetry (EDT) support, ESC EEPROM read/write, and significant robustness improvements to bidirectional DShot decoding.
Key Changes
Extended DShot Telemetry (EDT)
up_bdshot_get_extended_telemetry()API for retrieving EDT values by typedshot statusESC EEPROM Architecture
ESCSettingsInterfaceabstract base class for firmware-agnostic ESC settings handlingAM32Settingsimplementation with full 48-byte EEPROM structure supportesc_eeprom_readandesc_eeprom_writewith selective byte write maskingESC_EEPROMstream for bidirectional EEPROM access via GCSBDShot Robustness Improvements
convert_edge_intervals_to_bitstream()with flexible frame validation (18-24 bits)DShot Driver Refactoring
EscDatastructureOther Changes
isMotor()helper in mixer_module for motor output detectionTesting Notes
Parameters
DSHOT_ESC_TYPE=1 (for AM32, for ESC settings testing)
DSHOT_BIDIR_EDT=1 (for EDT testing)
DShot Sequential Timer triggering timing analysis
Timing analysis script for use with Saleae to validate sequential bdshot trigger timing.
ESC_EEPROM Support in QGC
New UI in QGC for configuring AM32 ESCs. Feature branch is still WIP https://github.com/dakejahl/qgroundcontrol/pull/3/changes