Каскадный интегратор для ПИД (CIC-PID)

Про байтики и логику ЭБУ
Post Reply
User avatar
andreika
donator
donator
Posts: 461
Joined: Mon Feb 13, 2017 2:35 pm
Location: Kiev

Каскадный интегратор для ПИД (CIC-PID)

Post by andreika »

Немного предыстории.
Мы с Артёмом @darxfame пробовали "на бумаге" некоторые методы автонастройки ПИДа для РХХ, вроде Циглера и подобных. Вбивали полученные коэффициенты в текущую реализацию ПИДа в rusEFI и смотрели по отладочным логам, что происходит. И заметили, что I-компонента очень часто упирается в пределы мин/макс, особенно на начальных этапах настройки ПИДа.
И это сильно искажает результаты работы, и не даёт адекватно воспринимать реакцию системы при подборе параметров. В текущей реализации ПИДа, I-компонента ограничивается мин/макс-значениями самого ПИДа. И они не годятся, особенно для высокоинерционных движков и медленных РХХ, где накопление интегратора весьма приличное.

Самое простое решение, предложенное ещё в комментариях реализации ПИДа, было просто задать отдельные (увеличенные) лимиты для I-компоненты. Но такой подход обладает одним недостатком: он не умеет "забывать" прошлые ошибки, полагаясь на то, что ПИД уже неплохо настроен, и ошибка будет неизбежно уменьшаться. Однако в случае недонастроенного ПИДа или иных причин, когда появляются автоколебания регулятора ("раскачивания"), этого не происходит. Интегратор всё равно упирается в лимиты, пусть даже расширенные. Но, главное, при этом внутри I-компоненты оказываются слишком старые ошибки, которые уже не актуальны для текущего положения регулятора.

Поэтому возникла идея: сделать для интегратора временнОе окно (измеряемое в N секундах, в зависимости от настройки периода ПИД), и тогда накопления прошлых ошибок не будет, и сама I-компонента будет естественным образом ограничена. К сожалению, реализовать "в лоб" moving sum мы не можем себе позволить, т.к. придётся хранить в большом буфере все значения ошибок в течение всего окна интегрирования (а оно может быть десятки секунд). Поэтому был реализован каскадный интегратор - алгоритм наподобие CIC-фильтра (cascaded integrator-comb), который требует на порядок меньше памяти для своего буфера, и при этом позволяет поддерживать moving sum в довольно большом окне.

Собственно, сейчас используется только два каскада (для экономии памяти) и, соответственно, один циклический буфер - этого хватает для окна интегрирования шириной более 10 секунд даже для самого малого периода 10 мс. При этом в памяти мы занимаем 32*4 байта. Также мы используем усреднение значений в буфере для сглаживания перехода между позициями буфера (иначе "резкий" CIC может спровоцировать возбуждение в ПИДе).

Алгоритм вынесен в отдельный класс PidCic, и тем самым в прошивке есть возможность на выбор использовать любую из имеющихся реализаций ПИД - старую и новую. Обратная совместимость полностью сохранена, и для пользователей не возникнет неудобств.

Этот алгоритм уже частично протестирован Артёмом на реальной машине, и тестирование ещё продолжается.

Итак, вот PR:
https://github.com/rusefi/rusefi/pull/519
User avatar
AndreyB
Site Admin
Posts: 14292
Joined: Wed Aug 28, 2013 1:28 am
Location: Jersey City
Github Username: rusefillc
Slack: Andrey B

Re: Каскадный интегратор для ПИД (CIC-PID)

Post by AndreyB »

Очень хороший топик! Лучше его можно сделать только переводом на английский, чтоб вся аудитория могла читать :)
Very limited telepathic abilities - please post logs & tunes where appropriate - http://rusefi.com/s/questions

Always looking for C/C++/Java/PHP developers! Please help us see https://rusefi.com/s/howtocontribute
User avatar
andreika
donator
donator
Posts: 461
Joined: Mon Feb 13, 2017 2:35 pm
Location: Kiev

Re: Каскадный интегратор для ПИД (CIC-PID)

Post by andreika »

russian wrote:
Mon Dec 25, 2017 2:24 am
Очень хороший топик! Лучше его можно сделать только переводом на английский, чтоб вся аудитория могла читать :)
https://github.com/rusefi/rusefi/blob/master/firmware/util/math/pid_cic.md
:roll:
Post Reply