Betaflight | Глубокое погружение в BetaFlight (Deep Dive into BetaFlight)
Введение
Цель этой страницы — указать на источники с подробной информацией о внутреннем устройстве прошивки BetaFlight. Эта информация хранится на таких ресурсах, как:
- Форум BetaFlight на RC Groups (авторство указано, где это возможно).
- YouTube-каналы, предоставившие соответствующий контент (почти не работает в РФ - ищите альтернативный доступ).
Содержание
- 1. Как работает разработка программного обеспечения с открытым исходным кодом
- 2. Реализация цикла на основе гироскопа (Gyro-based loop implementation)
- 3. Настройка delta_from_gyro и всё о значениях D в ПИД-регуляторе (PID Controller D values)
- 4. Фильтрация, наложение спектров и синхронизация гироскопа — объяснение (Filtering, Aliasing and Gyro Sync explained)
- 5. Таблицы преобразования скоростей/коэффициентов rc rate в градусы в секунду (Rates/rc rate translations into deg/sec Tables)
- 6. Обновление сигналов на двигатели (Motor update)
1. Как работает разработка программного обеспечения с открытым исходным кодом
Это видео охватывает тему, почему в хобби существует несколько версий одного и того же программного обеспечения (CleanFlight/BetaFlight/RaceFlight и т.д.) и как разработчики обмениваются идеями и переносят код между проектами.
http://www.youtube.com/watch?v=kZvoei1dzNQ (английский)
2. Реализация цикла на основе гироскопа (Gyro-based loop implementation)
Гироскоп (Gyro) — датчик, измеряющий угловую скорость вращения квадрокоптера вокруг его осей.
Цикл управления (Control loop) — повторяющийся процесс получения данных с датчиков, вычисления управляющих воздействий и отправки команд на исполнительные устройства (моторы).
Обновление данных с гироскопа определяет начало цикла. Цикл начинается после срабатывания прерывания по поступлению нового показания гироскопа. При этом, ПИД-регулятор всегда будет производить вычисления на основе поступления самого свежего значения гироскопа.
Частота опроса гироскопа 1 кГц определяет длительность импульсов управления - 1000 мкс ( или, например, 500 мкс в зависимости от конфигурации и возможностей целевой платформы). Это делает настройку времени цикла (looptime) ненужной, так как именно гироскоп определяет момент запуска цикла.
Настройка ПИД будет оставаться стабильной, т.к. между гироскопом и циклом управления отсутствует рассинхронизация. Проблем с наложением спектров (Aliasing*) возникать не должно.
*Aliasing — искажение сигнала, возникающее при недостаточной частоте дискретизации, когда высокочастотные компоненты сигнала «маскируются» под низкочастотные.
Это помогает фильтрам лучше справляться со своей задачей, обеспечивая более чистые графики показаний гироскопа.
3. Настройка delta_from_gyro и всё о значениях D в ПИД-регуляторе (The delta_from_gyro setting and all about the PID Controller D values)
ПИД-регулятор (PID Controller) — алгоритм управления, который использует сумму трёх компонент: пропорциональной (P), интегральной (I) и дифференциальной (D) для минимизации ошибки между заданным и текущим состоянием системы.
D-составляющая (D-term) — дифференциальная часть ПИД-регулятора, реагирующая на скорость изменения ошибки (или измерения), обеспечивая демпфирование и стабильность.
Boris B написал:
On = delta from measurement / gyro (дельта от измерения/гироскопа)
Off = delta from error (дельта от ошибки)
Это действительно трудно объяснить без глубокого изучения принципов работы ПИД-регуляторов и их математики. Но я попробую дать быстрое и «простое» объяснение:
Прежде чем объяснить, я сначала скажу, что определяет D-составляющую (Dterm) в сумме ПИД.
- Это производная, или, иными словами, скорость изменения.
По сути, это скорость чего-либо. Допустим, вы едете с постоянной скоростью 50 км/ч, тогда производная вашей скорости равна 0. Но если вы нажмете педаль и продолжите ускоряться, увеличивая скорость на 5 км/ч в секунду, то производная вашей скорости будет равна 5. Когда вы начнете замедляться, производная вашей скорости станет отрицательной.
Delta from error (дельта от ошибки)
Это классический подход к производной. Она отражает скорость изменения ошибки. Ошибка определяется входным сигналом со стика. Как только вы двигаете стик, вы создаете ошибку, и ПИД-регулятор должен её исправить. Чем быстрее растёт ошибка, тем больше становится производная. Это помогает циклу ПИД быстрее достичь целевого значения. Это ускоряет реакцию системы, что создаёт эффект демпфирования.
Delta from measurement/gyro (дельта от измерения/гироскопа)
Это математически упрощённая формула производной от ошибки, при условии, что ошибка равна нулю. Когда вы исключаете ошибку из формулы, поскольку она и так равна нулю, остаётся только -(изменение измерения). А это — скорость изменения сигнала с гироскопа. Чем быстрее сигнал гироскопа растёт в положительном направлении, тем выше будет D-составляющая в противоположном направлении. Это оказывает прямое демпфирующее воздействие на P-составляющую.
Основное различие заключается в том, что «дельта от ошибки» как бы ускоряет ваше движение стиком, но при этом создаёт так называемый «удар производной» (derivative kick), поскольку следует за сигналом стика, который обновляется с более низкой частотой. В то время как «дельта от гироскопа» вообще не ускоряет движение стиком и не создаёт «удара производной».
ctzsnooze написал:
На самом деле D-составляющая в режиме гироскопа обратно пропорциональна скорости изменения сигнала гироскопа. Она всегда противодействует изменениям сигнала гироскопа. Инерция рамы задерживает реакцию гироскопов на изменения P-составляющей, но поскольку D-составляющая всегда противодействует изменениям гироскопа, она обычно имеет противоположный знак по отношению к P-составляющей (и определённо противоположный знак по отношению к D-составляющей).
Когда P-составляющая увеличивается из-за положительного сигнала со стика, инерция квадрокоптера сначала приводит к большому ошибочному сигналу P-составляющей. Сначала квадрокоптер не двигается из-за инерционной массы. При отсутствии движения D-составляющая равна нулю, а P-составляющая довольно велика. Очень быстро моторы раскручиваются и начинают вращать квадрокоптер, уменьшая P-составляющую по мере достижения целевой скорости вращения (то есть по мере уменьшения ошибки). D-составляющая замедляет начало вращения, сглаживая как начало, так и окончание движения. Но P-составляющая всегда сильнее, поэтому квадрокоптер в итоге достигает желаемой скорости вращения. Поскольку скорость вращения теперь постоянна, и P-составляющая, и D-составляющая стремятся к нулю.
Инерция может заставить раму продолжать вращаться немного дальше точки, в которой она должна была остановиться. P-составляющая слабо противодействует этому, поскольку обычно величина отклонения из-за ошибок инерции мала, но D-составляющая очень чувствительна к высокой скорости перерегулирования P-составляющей и подавляет их гораздо быстрее, чем может P-составляющая.
При отсутствии движения стика P-составляющая противодействует внешней силе, действующей на раму. Величина реакции P-составляющей всегда пропорциональна ошибке между желаемой скоростью вращения и измеренной скоростью вращения (например, нежелательному вращению при попадании в порыв ветра).
Когда происходит положительное движение стика, положительный rcCommand** приведёт к резкому отрицательному значению ошибки, потому что рама не будет вращаться так быстро, как требует новое значение rcCommand — по крайней мере, сразу не будет. Это вызывает небольшой всплеск P-составляющей, который можно увидеть при каждом резком изменении rcCommand. Именно это и означает, что P-составляющая основана на ошибке. В результате P-составляющая изменяется в том же направлении, что и rcCommand при движении стика. Как только рама начинает вращаться с желаемой скоростью, ошибка P-составляющей падает и достигает нуля, когда скорость вращения достигает требуемого значения.
**rcCommand — это значение, рассчитанное на основе положения стиков пульта управления, которое определяет требуемую скорость вращения квадрокоптера вокруг осей (крен, тангаж, рыскание). Это «команда» от пилота, поступающая в ПИД-регулятор для сравнения с текущим значением с гироскопа.
Когда D-составляющая основана на гироскопе, она пропорциональна скорости изменения сигнала гироскопа и имеет противоположный знак. D-составляющая, не основанная на ошибке, не зависит от движения стиков. Она просто противодействует скорости изменения сигнала гироскопа, сглаживая резкие изменения скорости, независимо от их происхождения. Хотя математически это производная, она действует как демпфирующий механизм для колебаний, подобно амортизатору в подвеске автомобиля.
Хотя D-составляющая на основе гироскопа немного отстаёт от P-составляющей из-за инерции рамы, во время движения стика она обычно имеет противоположный знак по отношению к P-составляющей.
ctzsnooze написал:
D-составляющую можно рассчитывать либо по скорости изменения сигнала гироскопа, либо по ошибке между rcCommand и сигналом гироскопа. Первый подход впервые использовался в прошивке Lux, в то время как в multiwii и Rewrite D-составляющая исторически была основана на ошибке.
До недавнего времени BetaFlight использовала расчёт D-составляющей на основе ошибки, но начиная с версии 2.3.4 Boris вернулся к первоначальному подходу Lux, при котором D-составляющая рассчитывается только по скорости изменения сигнала гироскопа.
D-составляющая по своей сути противодействует изменениям в сигнале гироскопа и сильнее противодействует быстрым изменениям, чем медленным. Если вы держите квадрокоптер в руках в режиме acro без движения стиков и внезапно, но очень быстро, слегка наклоняете его, то немедленное противодействие этому резкому небольшому изменению обеспечивается почти исключительно D-составляющей.
Оба метода ведут себя одинаково при отсутствии движения стиков, но значительно различаются, когда управляющее воздействие вызывает резкую «ошибку» между текущей и желаемой (целевой) скоростями крена.
Когда D основана на ошибке, при резком изменении rcCommand (положения стиков) возникает сильный «удар D-составляющей» (dterm kick). Этот удар обычно совпадает по фазе с желаемой скоростью и ускоряет реакцию на движение стика, поскольку удар обычно преодолевает обычную реакцию D-составляющей, противодействующую движению.
Однако этот эффект удара вызывает «всплески» на графике D-составляющей — меньшие при использовании Sbus, но большие при PPM. Основной причиной внедрения rcSmoothing (сглаживания сигнала управления) было именно устранение этих всплесков, но при этом сохранение эффекта «удара».
При резком движении стика квадрокоптер будет реагировать немного быстрее, если D-составляющая основана на ошибке, потому что D не будет противодействовать движению, вызванному движением стика. Заметно ли это на практике — неясно, но теоретически он должен быть немного более отзывчивым.
Однако возможен и недостаток: дрожание после резких движений стика (например, в конце крена) может быть менее выражено, когда D-составляющая не основана на ошибке. Кроме того, если «удары» не сглаживаются, они могут вызывать шум в моторах во время движения стика, снижая эффективность, и поскольку сглаживание rcSmoothing для их устранения может вызывать задержки или создавать иные проблемы, Boris, похоже, стремится пересмотреть, какой подход является наилучшим.
Было бы полезно, хотя бы в целях тестирования, иметь возможность выбирать режим расчёта D-составляющей с помощью переключателя, чтобы можно было изменять функциональность в полёте и реально увидеть, есть ли существенная разница. Или изменять его через параметр CLI. В противном случае довольно сложно определить, какой подход лучше — приходится перепрошивать с помощью кастомной версии, и сравнить их становится не так просто.
Но да, при сильных движениях стика новый подход к D-составляющей будет выглядеть более плавным на BlackBox во время ввода, и D-составляющая всегда будет находиться в противофазе с гироскопом, что может немного замедлить реакцию на P-составляющую при движении стика. Возможно, небольшое увеличение P-составляющей компенсирует потерю эффекта «удара D-составляющей». Если это так, то появляется соблазн отказаться от расчёта D-составляющей на основе ошибки.
Дополнительная информация
Влияние D-составляющей на ПИД-регулятор: http://www.youtube.com/watch?v=xMygUvegC80
Общее объяснение D-составляющей: http://en.wikipedia.org/wiki/Derivative
4. Фильтрация, наложение спектров и синхронизация гироскопа — объяснение (Filtering, Aliasing and Gyro Sync explained)
Следующие видео были созданы с учётом особенностей BetaFlight и предоставляют отличный ресурс для глубокого изучения этих сложных тем.
- Основы фильтрации: http://www.youtube.com/watch?v=CpW8_fOJ7_M
- Nuhertz Spectra для анализа данных гироскопа коптера: http://www.youtube.com/watch?v=fZm9N-WFkQk
- Анализ графиков БПФ (FFT) для настройки мультикоптера: http://www.youtube.com/watch?v=nxHK-V7GCYY
- Объяснение наложения спектров и синхронизации гироскопа: http://www.youtube.com/watch?v=-lmoKal_e4s
- Новый биквадратный фильтр в BetaFlight V2.3.x: http://www.youtube.com/watch?v=Q2tSWU1MsVk
5. Таблицы преобразования скоростей/коэффициентов rc rate в градусы в секунду (Rates/ rc rate translations into deg/sec Tables)
rc rate — параметр, определяющий крутизну кривой отклонения стика пульта, влияющий на скорость вращения квадрокоптера.
Rate — параметр, устанавливающий максимальную угловую скорость вращения вокруг осей (крен, тангаж, рыскание).
Boris опубликовал таблицы в:
- Влияние rate при статическом rc rate, равном 100 (rc rate не влияет на рыскание). Положение стика на максимуме: http://www.rcgroups.com/forums/showpost.php?p=34028934&postcount=18514
- Влияние rc rate при статическом значении rate, равном 0. Положение стика на максимуме: http://www.rcgroups.com/forums/showpost.php?p=34028937&postcount=18515
- и для полноты картины. Только влияние yaw rate (коэффициент рыскания): http://www.rcgroups.com/forums/showpost.php?p=34028986&postcount=18516
6. Обновление сигналов на двигатели (Motor update)
Джиттер (Jitter) — случайные или регулярные колебания временных интервалов между последовательными событиями (например, обновлениями сигнала), что может привести к нестабильности.
Пример с циклами и обновлением моторов
-
Цикл управления PID (looptime): 375 микросекунд (мкс)
-
Цикл обновления гироскопа (GYRO): 125 мкс
-
Обновление моторов происходит в начале нового цикла обновления гироскопа (cycletime), а не в начале PID-цикла.
-
График сигнала примерно такой:
Start GYRO/PID loop → +125us GYRO/MOTOR → +125us GYRO → +125us PID/GYRO → +125us GYRO/MOTOR (итого 375us)
Важные моменты:
Иметь частоту обновления моторов выше, чем частоту цикла управления (looptime), — полная ерунда, поскольку значения всё равно будут перезаписываться и это приведёт к джиттеру (непредсказуемым временным колебаниям).
Идеальный способ обновления моторов — писать новые значения только тогда, когда доступны новые вычисления от миксера, при этом промежуток времени между обновлениями моторов никогда не должен быть меньше желаемого периода. Более редкие обновления (удлинённые интервалы) не страшны, главное — чтобы следующее обновление не накладывалось на предыдущее.
Допустим, PID-контроллер / микшер запрашивает полный газ на протоколе OneShot125, где ширина ШИМ-сигнала около 250 микросекунд. Если мы будем обновлять моторы с частотой 2 кГц (интервал 500 мкс), то будет в целом 250 мкс "свободного" интервала, в течение которого неважно, когда именно вы обновите сигнал. Следовательно, допустимый период джиттера чуть меньше 250 мкс.
При скорости обновления в 4 кГц (интервал 250 мкс) джиттер практически не допускается, чтобы обеспечить возможность полного газа.
Не имеет значения, если мотор обновляется слишком поздно, но обновлять его слишком рано — ни в коем случае нельзя.
При низких значениях looptime, таких как сейчас, мы приближаемся к ситуации, когда обновления моторов происходят ближе к концу цикла (cycletime). Поэтому здесь нет понятия «задержка». Неважно, выполняется ли действие в начале или конце цикла. Представьте себе, что вы бежите по кругу: нельзя явно определить, где начало, а где конец. Порядок действий уже не имеет значения.
Именно ближе к концу цикла происходит максимальный джиттер — временные вариации составляют от 0 до 100 микросекунд. Особенно при низких значениях looptime и использовании планировщика задач для максимальной эффективности, конец цикла очень "дрожит" во времени.
Поэтому при переносе обновления моторов в начало цикла вы всегда получаете постоянное время обновления. Временная переменная задержка, которая была при обновлении моторов в конце цикла, становится постоянной задержкой.
Джиттер особенно критичен для протоколов OneShot, где период сигнала около 60 микросекунд — это почти половина длительности самого сигнала.
