Skip to content

fix(dshot): pick bit width per timer clock for accurate rate#27402

Open
dakejahl wants to merge 1 commit into
PX4:mainfrom
dakejahl:fix-dshot-bit-width-derive-from-clock
Open

fix(dshot): pick bit width per timer clock for accurate rate#27402
dakejahl wants to merge 1 commit into
PX4:mainfrom
dakejahl:fix-dshot-bit-width-derive-from-clock

Conversation

@dakejahl
Copy link
Copy Markdown
Contributor

@dakejahl dakejahl commented May 20, 2026

Summary

Auto-selects DSHOT_MOTOR_PWM_BIT_WIDTH per timer clock at compile time so ARK FPV emits DSHOT at the same bit period as the rest of the fleet. Supersedes #27401.

Problem

io_timer_set_dshot_burst_mode() sets ARR = WIDTH and PSC = floor(CLK/DSHOT_FREQ)/WIDTH - 1 with hardcoded WIDTH = 20. The actual bit period is (PSC+1) * (ARR+1) timer-clock ticks. ARK FPV's 160 MHz APB1 (PLL1N=40) gives floor(160e6/600e3) = 266, not divisible by 20 — BIT_1/BIT_0 duty cycles end up at 66.7%/33.3% vs DSHOT600 spec 75%/37.5%.

#27401 fixed this with hardcoded WIDTH = 19, but that breaks every F4/F7 board with an 84/108 MHz timer clock.

Solution

Compile-time ladder against STM32_APB1_TIM5_CLKIN: try WIDTH ∈ {20, 19, 18} and pick the first where floor(CLK/600000) % W == 0. Falls back to 20 otherwise. ARK FPV lands on W=19; every other DSHOT-capable board keeps W=20 unchanged.

Scope traces on ARK FPV (160 MHz APB):

DSHOT600 spec Before (W=20) After (W=19)
Bit period 1667 ns 1706 ns 1750 ns
BIT_1 HIGH 1250 ns (75%) 1138 ns (66.7%) 1225 ns (70%)
BIT_0 HIGH 625 ns (37.5%) 568 ns (33.3%) 612 ns (35%)

ARK FPV's post-fix 1.75 us bit period matches all 240 MHz boards (FMU-v6X/v6S/PI6X, durandal, kakuteh7*, ctrl-zero-h7, etc.). 200 MHz boards (CubeOrange/Orange+, spracing/h7extreme) keep W=20 (unchanged — none of {20, 19, 18} divides 333; fix needs W=22 with scaled BIT_1/BIT_0, out of scope).

A #warning flags boards where APB1 and APB2 timer clocks would emit DSHOT at different rates (currently only fmu-v4pro: APB1=90 MHz, APB2=180 MHz — pre-existing on master, not regressed by this PR).

Builds verified on ark_fpv_default, ark_fmu-v6x_default, ark_cannode_default, cubepilot_cubeorange_default.

@github-actions github-actions Bot added the kind:bug Something is broken or behaving incorrectly. label May 20, 2026
@dakejahl dakejahl marked this pull request as draft May 20, 2026 01:10
@dakejahl dakejahl force-pushed the fix-dshot-bit-width-derive-from-clock branch 2 times, most recently from 2e652ac to 9881efb Compare May 20, 2026 17:43
Auto-selects DSHOT_MOTOR_PWM_BIT_WIDTH per timer clock at compile time
so ARK FPV emits DSHOT at the same bit period as the rest of the fleet.
The hardcoded WIDTH=20 truncates the prescaler on ARK FPV's 160 MHz APB1
(PLL1N=40, floor(160e6/600e3)=266 not divisible by 20), giving a 1.706us
bit period and 66.7%/33.3% duty cycles (vs DSHOT600 spec 75%/37.5%).

The new ladder tries WIDTH in {20, 19, 18} and picks the first that
divides cleanly. ARK FPV lands on W=19, matching the 1.75us bit period
of the 240 MHz boards. Duty cycles improve to 70%/35%. 240/96/108/84 MHz
boards keep W=20 (unchanged). 200 MHz boards (CubeOrange/Orange+,
h7extreme) fall through to W=20 (unchanged, fix needs W=22 with scaled
BIT_1/BIT_0 -- out of scope).

A #pragma message (not #warning, which -Werror=cpp would treat as an
error) flags boards where APB1 and APB2 timer clocks would emit DSHOT
at different rates -- currently only fmu-v4pro (APB1=90, APB2=180 MHz).
The whole block is guarded on STM32_APB2_TIM8_CLKIN so STM32F1 IO
co-processor boards (no TIM8, header still pulled in by io_timer.c)
keep W=20 silently.

Supersedes PX4#27401.
@dakejahl dakejahl force-pushed the fix-dshot-bit-width-derive-from-clock branch from 9881efb to edbb0af Compare May 20, 2026 18:08
@dakejahl dakejahl marked this pull request as ready for review May 20, 2026 18:11
@dakejahl dakejahl requested a review from julianoes May 20, 2026 18:11
Copy link
Copy Markdown
Contributor

@julianoes julianoes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we do this properly generically without hard-coding to 20 and the exception added here?

@dakejahl
Copy link
Copy Markdown
Contributor Author

Could we do this properly generically without hard-coding to 20 and the exception added here?

Would you mind spending some tokens on it?

@julianoes
Copy link
Copy Markdown
Contributor

I can give it a try next week.

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

Labels

kind:bug Something is broken or behaving incorrectly.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants