Немного предыстории.
Мы с Артёмом @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
Каскадный интегратор для ПИД (CIC-PID)
- AndreyB
- Site Admin
- Posts: 14643
- Joined: Wed Aug 28, 2013 1:28 am
- Location: Jersey City
- Github Username: rusefillc
- Slack: Andrey B
Re: Каскадный интегратор для ПИД (CIC-PID)
Очень хороший топик! Лучше его можно сделать только переводом на английский, чтоб вся аудитория могла читать 

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
Always looking for C/C++/Java/PHP developers! Please help us see https://rusefi.com/s/howtocontribute