Betaflight fork with ADRC (active disturbance rejection control)
  • C 92.5%
  • Assembly 4.6%
  • C++ 1.7%
  • HTML 0.4%
  • Linker Script 0.4%
  • Other 0.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
danusha2345 6cff3559a2 docs: add the two 8ksal8 tune-comparison flight logs (40/70, 92/120) referenced by addendum 2
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 17:32:49 +03:00
.devcontainer feat(devcontainer): add Gazebo SITL simulation container (#15212) 2026-05-14 11:08:39 +10:00
.github docs: point the repo Sponsor button at this fork's Boosty 2026-07-09 20:57:25 +03:00
docs docs: add the two 8ksal8 tune-comparison flight logs (40/70, 92/120) referenced by addendum 2 2026-09-04 17:32:49 +03:00
images Fix picture and update links (#12244) 2023-01-29 10:55:49 +11:00
lib Xcore32m7 platform support (#15287) 2026-06-18 20:00:08 +10:00
mk telemetry/mavlink: MISSION protocol upload/download (#15224) 2026-05-30 06:03:44 +10:00
src test: fix pid_unittest link failure under ADRC 2026-07-07 16:01:51 +03:00
.coderabbit.yaml Update .coderabbit.yaml 2026-04-13 02:30:36 +10:00
.gitattributes Added unified '.gitattributes' file. 2019-10-02 01:05:29 +13:00
.gitignore chore(gitignore): opt real build/ and target/ source dirs back into code indexers 2026-08-06 00:12:14 +03:00
.gitmodules Move submodules from lib/main to lib/modules (#15241) 2026-05-22 19:21:26 +10:00
ADRC_FIXES.md docs: tighten round-3 numbers after independent re-review 2026-07-10 21:17:55 +03:00
ADRC_FIXES.ru.md docs: tighten round-3 numbers after independent re-review 2026-07-10 21:17:55 +03:00
CODE_OF_CONDUCT.md Update Code of Conduct 2022-02-19 02:18:55 +01:00
CONTRIBUTING.md Remove docs and fix links (#12222) 2023-01-25 19:34:17 +11:00
DEFAULT_LICENSE.md Extend build info with defined flags (#13333) 2024-03-21 18:29:22 +01:00
LICENSE Updated more documentation to match the template. 2020-03-09 13:00:35 +13:00
Makefile Speed up make clean-stale-deps (#15283) 2026-06-18 19:59:22 +10:00
README.md docs(adrc): publish b10.1 verification 2026-08-28 18:53:05 +03:00
README.ru.md docs(adrc): publish b10.1 verification 2026-08-28 18:53:05 +03:00

na

Betaflight ADRC Controller (Active Disturbance Rejection Control)

Boosty

English | Русский

This repository implements Active Disturbance Rejection Control (ADRC) on Betaflight, completely replacing the traditional PID loop. ADRC acts as a "PID Killer"—providing incredible stability, robust wind resistance, and smooth handling even with uncalibrated parameters, changing propeller sizes, or extreme, unbalanced dynamic payloads.

⚠️ Experimental fork with ADRC robustness fixes — more flight testers wanted! This fork carries a series of small, independent ADRC robustness fixes on top of Boyyt357/ADRC-betaflight: anti-windup on the disturbance estimate, saturation-aware observer feedback, ADRC-tuned defaults, zero-throttle observer handling, a liftoff gate for the observer, a per-craft System-Gain multiplier, and blackbox logging of the observer states. Several are validated in real flights (5" and 65 mm whoop, one independent pilot — takeoff bounce fixed, leaf-blower/stick-strike/prop-cut survival, blackbox-confirmed); hardware diversity is still tiny, so results from other stacks are the most valuable thing you can contribute. Each fix is its own commit (git revert <sha> to A/B). Details and flight evidence in ADRC_FIXES.md. Report in issue #1 — Call for flight testers. 🙏

🚀 Heading upstream: betaflight/betaflight#15400 — ADRC is on its way into official Betaflight as an opt-in feature (pid_type = ADRC per profile, classic PID untouched), a draft PR by @bvandevliet carrying this fork's fixes with attribution plus a joint review/fix round. This fork remains the fast-iteration testbed and its releases stay the easiest way to fly ADRC today; everything validated here feeds straight into that PR.

📦 Don't want to compile? Prebuilt hex files are in Releases — b10.1 contains 615 supported ARM/hex board configs plus 15 generic images; 14 configs needing another SDK/output path are listed as skips. F446 images are classic-PID-only because ADRC does not fit in their flash budget. Flash via Configurator → Load Firmware [Local].


For more Info

ADRC Betaflight


Key Features

  • No Heavy Tuning Required: Flies exceptionally well even out of the box with rough, uncalibrated values.
  • Unbalanced Payload Handling: Actively estimates and cancels external forces dynamically, allowing stable flight even with swinging weights attached to a single motor arm.
  • Propeller Versatility: Dynamically handles transitions between different prop sizes on the fly without changing parameters.

How it Works: Repurposing the PID Fields

Instead of standard Proportional, Integral, and Derivative gains, this implementation repurposes the Betaflight PID configuration fields to control the ADRC system:

Field ADRC Parameter Description
P Control Bandwidth Dictates the response speed to errors. Higher values yield faster correction; lower values correct errors more slowly.
I Observer Bandwidth Controls the speed of the Extended State Observer (ESO). It dictates how fast the controller estimates and cancels external forces (e.g., wind, prop wash). Note: Setting this too high can amplify gyro noise and heat up motors.
D System Gain Informs the controller how powerful the motors are based on acceleration and KV rating. Decreasing this increases overall gain (for fast-accelerating motors); increasing it decreases overall gain (for smoother control).

Where to enter the values (Betaflight Configurator, PID Tuning tab)

There is no separate "ADRC" screen — you type the ADRC parameters into the ordinary P / I / D cells of the PID Tuning tab, per axis, exactly where PID gains normally live:

Axis P cell → Control Bandwidth (ω_c) I cell → Observer Bandwidth (ω_o) D cell → System Gain (b0 ÷ 10)
ROLL 30 100 200
PITCH 30 100 200
YAW 30 80 200

(example values = the community 5" tune below; the firmware defaults are 10 / 110 / 100 for roll & pitch and 10 / 80 / 100 for yaw — yaw runs a slightly lower observer bandwidth by default)

Two things to know before you hit Save:

  1. Switch the Simplified Tuning sliders OFF first (PID Tuning tab → slider mode → OFF / expert mode). If the sliders are active, the Configurator recomputes the P/I/D cells from the sliders on save and silently overwrites your ADRC values. For the same reason, don't touch the Master multiplier — under ADRC, scaling all cells together is meaningless.
  2. The other fields keep (or lose) their meaning as follows:
    • Feedforward (F) — unchanged: still the standard Betaflight stick feedforward, applied on top of ADRC. Keep the defaults.
    • D Max — ignored (ADRC reads only the D cell, as System Gain).
    • TPA — effectively inert (it scales the legacy Kp/Kd coefficients, which ADRC does not use).
    • Anti-gravity / I-term relax / I-term rotation — legacy PID helpers; ADRC recomputes its I-term from the observer every loop, so they don't apply (the anti-gravity P-boost is explicitly disabled in this fork — fix #7a).

CLI equivalent, if you prefer it over the GUI: set p_roll = 30, set i_roll = 100, set d_roll = 200 (same for _pitch / _yaw), then save.

If the D cell maxes out (typical on high thrust/weight builds — tiny whoops): don't chase more D. Set the per-craft System-Gain multiplier once in the CLI — set adrc_b0_scale = 20 (default 10, range 1100; b0 = D × scale) — then keep tuning the ordinary D cell in the GUI. The setting lives in the profile and shows up in diff/dump backups. When sharing your tune, mention the scale: the same D means a different b0 at a different scale.

Experimental extras (see ADRC_FIXES #10/#11 — safe to leave at defaults): adrc_hover_throttle (%, default 35) tells the throttle-scaled b0 where your hover point is — b0 is scaled (throttle/hover)² above hover so the model stays calibrated across the throttle range; set it near your actual hover throttle, most useful on high thrust/weight builds. Note the square is deliberately conservative: it may feel slightly soft/less snappy near full throttle (real motor authority likely scales closer to linear) — if you dislike that, raise adrc_hover_throttle toward your top throttle to shrink the effect. adrc_sigma_decay (default 3) is a mild leak that bleeds a transient disturbance estimate back to zero instead of letting it linger; set 0 for the classic pure integrator. Leave adrc_sigma_decay_sched at 0 — its scheduling is not yet validated.

While your tune is unproven you can disable PID at minimum throttle so a wrong tune cannot thrash the motors on arm (CLI: set pid_at_min_throttle = off). Know the trade-off: with it off the controller is fully asleep at idle throttle — sticks and tilts produce no motor response at all until you raise the throttle, which reads as "the sticks don't work" on a bench test, and the controller wakes with a step when the throttle crosses the threshold. Since fix #8/#10 the fork has its own ground protection (the liftoff gate + re-arm), so the stock ON is safe and behaves like the Betaflight you are used to — pick one deliberately.

Example Parameters

Drone type Control Bandwidth (P) Observer Bandwidth (I) System Gain (D)
10" drone (author's video) 10 50 20
5" drone (jmsweng, 2300 kV) 40 160 200
5" drone (jmsweng, 1750 kV) 40 160 250
5" drone (jmsweng, 1750 kV, airfield re-tune 2026-07-01) 30 100 200
5" drone (jmsweng, 1750 kV, round-2 ωc sweep 2026-07-05/06) 60 100 200
65 mm whoop (jmsweng, Air65 clone, 1S, 30000 kV) 33 65 160 (with adrc_b0_scale = 20)
5" drone (maintainer, 2207 1300 kV, 6S, 51477 props — short indoor hover only) 40 120 200 (with adrc_b0_scale = 20)

Note on the two 1750 kV rows: they are the same craft before and after the round-2 control-bandwidth sweep, and the later one supersedes the earlier. Prefer 60/100/200 where they disagree — that sweep is what the upstream PR ships as its default tune (adrc_wc = 60, adrc_wo = 100, adrc_b0 = 2000, i.e. D 200 × the default scale 10). Details in ADRC_FIXES.md ("Round-2 5" flight logs").

Note on the maintainer's row: the adrc_b0_scale = 20 there is not a validated 5" recommendation — it was raised from the default 10 chasing a bench limit cycle that later traced to a stick / pid_at_min_throttle artefact, not b0. The other 5" rows run the default scale 10. On a 5" start at scale 10; the ×20 headroom is really for authority-limited whoops that hit the D ceiling.

Tuning procedure (community, from @jmsweng)

A sensible step-by-step instead of guessing, starting from 10 / 50 / 20 (P/I/D):

  1. System Gain (D): raise until the quad takes off stably (~70 on a 5"), keep raising until it makes a stuttering noise in hover, then back off ~20%. (Overestimating b0 is fairly harmless; underestimating causes instability.)
  2. Observer Bandwidth (I): raise until stuttering/chatter appears in hover, then back off ~20%. (Too high and the observer starts tracking gyro noise.)
  3. Control Bandwidth (P): set to ~¼ of the Observer Bandwidth (the wo ≈ 35×wc rule of thumb) as a starting point, then treat it like a master responsiveness knob — raise it for a crisper feel until the motors start "singing" (a horn/chatter that gets louder on throttle-up), then back off. Round-2 5" logs show that noise is the control law amplifying residual gyro noise (kd = 2·ωc grows with ωc, and higher RPM feeds it more), so ωc has a practical ceiling set by your gyro noise / filtering, not by stability. Too low instead feels floaty/sluggish.

Example end state on a 5" (640 g, DAKEFPVF405, 4S, 2300 kV, Gemfan Hurricane 51433-3): 40 / 160 / 200 — in tests this resisted a leaf-blower and being hit with a stick mid-air, and flew with 2040% of AUW hung off one motor arm. On faster/lighter setups scale System Gain roughly with kV·mass. The System Gain (D) input maxes out at 255 in this fork (raised from 250); if you genuinely need a larger b0 (high thrust/weight builds), raise adrc_b0_scale instead (see above) — but chattering usually means the Observer Bandwidth (I) / gyro filtering needs retuning rather than more gain.

On a 5" (2300 kV, 4S) the round-2 sweet spot came out at 60 / 100 / 200: crisp, no oscillation on hard turns/flips, and quiet — one notch below where throttle-up chatter set in (ωc 70+ started singing). The same firmware flew controllably with bent props on three of four motors, a good illustration of the disturbance rejection.

Refinement (blackbox method): after swapping to 1750 kV motors jmsweng re-tuned by comparing blackbox traces of the same takeoff+hover under several candidate tunes and picking the one with the least oscillation — ending at 30 / 100 / 200. Maintainer analysis of those logs confirms the separation is real (takeoff pitch-error RMS differed ~4× between candidate tunes), so a few logged takeoffs are a cheap, quantitative way to choose between tunes that all "feel fine". This method is packaged as a ready-to-run script: docs/flight-test-analysis/adrc_tune_score.py (stdlib-only Python; feed it the CSVs from blackbox_decode and it ranks your candidate tunes). Its companion adrc_log_plot.py draws the same logs (tracking error, the observer's disturbance estimate, motors, and — with set debug_mode = ADRC — the ESO states and the fix #8 liftoff latch); needs pip install matplotlib.

Takeoff note: on the original code, throttle-up shows a brief (sub-second) oscillation/bounce — blackbox analysis traced it to the observer winding up while the craft is still ground-constrained, and fixes #2 and #8 in this fork remove it (hardware-confirmed). set pid_at_min_throttle = off (above, with its bench-test trade-off) is an option while your tune is unproven. A residual sideways drift right after liftoff with a badly offset CG is the observer honestly learning that torque — it shrinks with a healthy Observer Bandwidth.


Prebuilt firmware (no compiling)

The latest tester release on the Releases page ships ready-to-flash .hex files built by CI from its exact source tag:

  • 615 board-specific builds across the supported ARM/hex config subset, with each board's config baked in. Fourteen SITL/RP2350/separate-SDK or output-format configs are reported as explicit skips, not silently counted as builds.
  • Generic per-MCU images for everything else — pick the hex matching your board's MCU (STM32F722 for any F722 board, STM32F405, STM32G474, STM32H743, AT32F435M/G, …), flash it, and accept Apply custom defaults when the Configurator offers it (same scheme official Betaflight releases use).

F446 exception: the F446 board and generic images are working classic-PID firmware, but do not contain ADRC. set pid_type = ADRC is intentionally unavailable on F446 because its 512 KiB flash region is already almost full.

b10.1 is a maintenance rebuild of b10's major base upgrade to Betaflight 2026.12-alpha. Upgrading from b10 preserves PID profiles. Upgrading from b9 intentionally resets them because the stored layouts are incompatible. Also, legacy serial ... lines are now read-only: restore an old diff all selectively, then verify each per-feature UART setting and your chosen motor protocol. Released Configurator 2026.6.1 predates firmware API 1.49; use a current development Configurator (with betaflight/betaflight-configurator#5420, betaflight/betaflight-configurator#5451 and betaflight/betaflight-configurator#5452) or the CLI. On API 1.49 the Ports tab is intentionally read-only and assignments live on each feature's own tab. Read the b10.1 release notes before flashing.

Flash via Configurator → Firmware Flasher → Load Firmware [Local]Flash Firmware (full chip erase on the first flash). Want a board added to the baked-in list? Ask in an issue.

Compiling ADRC-Betaflight

Compiles exactly like standard Betaflight (full docs here). On a normal x86_64 Linux / macOS / WSL host:

git clone https://github.com/danusha2345/ADRC-betaflight
cd ADRC-betaflight
make arm_sdk_install   # one-time: downloads the pinned arm-none-eabi GCC (13.3.1)
make configs           # one-time: hydrate the board configs submodule
make DAKEFPVF405       # build your target — replace DAKEFPVF405 with your board

The .hex lands in obj/. (Verified: builds clean for DAKEFPVF405 / STM32F405 with GCC 13.3.1.)

Building on an ARM host (e.g. Raspberry Pi)

The toolchain make arm_sdk_install fetches is x86_64-only, so on an ARM host use the system toolchain instead. Tested on a Raspberry Pi 3B running Raspbian Trixie 13.5:

  1. Install the toolchain
sudo apt update && sudo apt upgrade
sudo apt install gcc-arm-none-eabi libnewlib-arm-none-eabi build-essential
  1. Clone and enter the repo
git clone https://github.com/danusha2345/ADRC-betaflight
cd ADRC-betaflight
  1. Comment out the $(error No toolchain URL defined ...) line in mk/tools.mk (line 43) so the build uses the system toolchain instead of downloading one.
  2. Point the build at the system compiler version
echo "GCC_REQUIRED_VERSION = $(arm-none-eabi-gcc -dumpversion)" >> mk/local.mk
  1. Hydrate configs and build
make configs
make DAKEFPVF405

🧪 Help test these fixes — testers wanted!

This fork's ADRC robustness fixes (see ADRC_FIXES.md) have so far been flight-validated by one independent pilot on two crafts (5" freestyle quad and a 65 mm whoop), with a second developer independently confirming the same LADRC core (stable hover + angle mode on a 2" cinewhoop, running their own implementation and reusing this fork's adrc_b0_scale and liftoff gate). The results are strong (takeoff bounce fixed, flight with a cut-off prop blade, single-motor balancing), but this is still a tiny sample. Different FCs, gyros, sizes and flying styles are exactly what's missing.

How to help:

  1. Grab a prebuilt hex from Releases (see above) — or build the fork yourself (Compiling above); each fix is a separate commit, so you can git revert <sha> to build with or without any one of them.
  2. Test safely — props off first, then an open area away from people.
  3. Report in issue #1 — Call for flight testers, including:
    • Craft (size, weight, motors/props, FC target) and your ADRC P/I/D (wc/wo/b0).
    • Which commits you built with (or "all").
    • Behavior: arm/spool-up, hover, hard maneuvers, prop wash, wind, recovery after throttle chops, any oscillation or motor heating.
    • A blackbox log if you can grab one.

Even a quick "flew fine on a 5" with all fixes" or "got oscillation on yaw" is hugely useful. Thank you! 🙏


Hardware Issues

Betaflight does not manufacture or distribute their own hardware. While we are collaborating with and supported by a number of manufacturers, we do not do any kind of hardware support.

If you encounter any hardware issues with your flight controller or another component, please contact the manufacturer or supplier of your hardware, or check Discord to see if others with the same problem have found a solution.

Releases

ADRC firmware releases (this fork): github.com/danusha2345/ADRC-betaflight/releases. Stock (PID) Betaflight releases live here, with detailed release notes at betaflight.com.

Open Source / Contributors

Betaflight is software that is open source and is available free of charge without warranty to all users.

For a complete list of contributors (past and present) see Github.