ПИД регулятор - один из самых распространенных автоматических регуляторов. Он настолько универсален, что применяется практически везде, где нужно автоматическое управление. Например температурой: специальные печи, холодильники, инкубаторы, паяльники, сопло и стол 3D принтера, ИК паяльные станции и прочее. Поддержание частоты оборотов мотора, например для станков. Всевозможные балансирующие штуки, гироскутеры, сигвеи, левитирующие магнитные платформы, и конечно же квадрокоптеры и самолёты с автопилотом. Это всё ПИД регулятор.
Почему именно ПИД? Существуют и другие регуляторы, превосходящие ПИД по адаптивности к управляемой системе и стабильности, например линейно квадратичный. Но, чтобы грамотно синтезировать такой регулятор, нужно быть гораздо больше чем "семи пядей" во лбу, а настройка ПИД регулятора дело хоть и неприятное, но фактически очень простое и под силу любому, а сам ПИД регулятор универсален для почти любого процесса.
Система управления #
Прежде чем переходить непосредственно к пиду, очень важно понять и запомнить несколько базовых понятий, из которых состоит автоматическая система. В первую очередь это регулятор, который всем заправляет и находится в центре системы. Регулятор в данном понимании – математический алгоритм или часть программы, которая крутится на микроконтроллере. Регулятор, как алгоритм, работает с обычными числами.
Объект управления – это девайс, которым мы управляем, например печка или мотор. Для этого у нас есть управляющее устройство, например диммируемый тен или драйвер мотора. Управляющее устройство получает от регулятора управляющий сигнал, то есть конкретное число. Это может быть заполнение шим сигнала, от 0 до 255, а может быть угол поворота сервомашинки от 0 до 180, потому что регулятору без разницы чем управлять. В объекте управления у нас стоит датчик, с которого регулятор получает управляемую величину, то есть текущий сигнал с датчика. Это - обратная связь, которая и даёт возможность системе точно поддержать заданное значение. В случае с печкой это температура, а с мотором – частота оборотов. Ну и наконец регулятор получает установку (уставку), то есть число, к которому он должен привести текущее значение с датчика. Установка может задаваться каким угодно образом: крутилкой, ползунком, энкодером, кнопками, да хоть смской или голосовым вводом. Регулятору это неважно, для него это просто цифра.
Задача регулятора состоит в том, чтобы сравнивать текущее значение с установкой и выдавать управляющий сигнал на управляющее устройство. То есть в программе это будет выглядеть условно так: регулятор получил установку, регулятор получил значение с датчика, регулятор выполнил вычисления и выдал нам управляющий сигнал, опять же число. Если это ШИМ – мы его подаём через функцию генерации ШИМ. Есть ещё один момент – регулятор должен делать расчёты и применять управляющий сигнал через равные промежутки времени, то есть с равным периодом или частотой. Эта частота называется частотой дискретизации системы, а период обозначается как dt
, прямо как период интегрирования.
Под капотом у ПИД регулятора #
ПИД регулятор состоит из трёх составляющих: пропорциональной P
, интегрирующей I
и дифференциирующей D
, формируется просто как сумма трёх значений, умноженных каждая на свой коэффициент. Эта сумма после вычислений становится управляющим сигналом, который подаётся на управляющее устройство, обозначим его как out
:
out = P*kP + I*kI + D*kD;
Где kP
, kI
и kD
это и есть те самые коэффициенты, которые нужно настроить для работы ПИДа. Значения тут могут быть самые разные, от 0.001
то десятков и тысяч, это зависит от конкретной системы. Тут есть ещё один момент: любой коэффициент может быть равен нулю, и в таком случае обнуляется вся его компонента. То есть регулятор можно превратить в П, ПИ, ПД, и прочие сочетания. Разные системы требуют разного подхода, именно поэтому ПИД регулятор такой универсальный. В дальнейшем будем пользоваться следующими названиями переменных:
out
- выход с регулятора (управляющий сигнал)setpoint
- установка (заданное значение)input
- вход (значение с датчика)err
- ошибка регулированияdt
- период вычисления и регулирования
P составляющая #
Пропорциональная составляющая предоставляет собой разность текущего значения с датчика и установки:
P = setpoint - input;
Данная разность называется ошибкой регулирования, то есть насколько далеко находится система от заданного значения. Получается чем больше ошибка, тем больше будет управляющий сигнал и тем быстрее система будет приводить управляемую величину к заданному значению. Коэффициент kP
тут влияет роль усиления ошибки и настраивается вручную. Но в то же время, если система пришла к заданной величине, ошибка станет равной нулю, и управляющий сигнал тоже! Другими словами, П регулятор никогда не сможет привести к заданному значению, всегда будет некая ошибка. П составляющая является основной в ПИД регуляторе и так сказать тянет самую большую лямку, регулятор может неплохо работать только лишь на ней одной.
P составляющая исправляет ошибку в текущий момент времени
I составляющая #
Интегральная составляющая просто суммирует в саму себя ту же самую ошибку, разность текущего и заданного значения, умноженную на период дискретизации системы, то есть на время, прошедшее с предыдущего расчёта dt
- фактически берёт интеграл от ошибки по времени:
I = I + (setpoint - input) * dt;
В самом регуляторе это ещё умножается на коэффициент kI
, которым настраивается резкость данной составляющей. В интегральной составляющей буквально копится ошибка, что позволяет регулятору с течением времени полностью её устранить, то есть привести систему ровно к заданному значению с максимальной точностью.
I составляющая исправляет прошлые, накопившиеся ошибки
D составляющая #
Дифференциальная составляющая представляет собой разность текущей и предыдущей ошибки, поделенную на время между измерениями, то есть на ту же dt
, которая общий период регулятора. Иными словами – это производная от ошибки по времени:
err = setpoint - input;
D = (err - prevErr) / dt;
prevErr = err;
Фактически D составляющая реагирует на изменение сигнала с датчика, и чем сильнее происходит это изменение, тем большее значение прибавляется к общей сумме. Иными словами, D позволяет компенсировать резкие изменения в системе и при правильной настройке предотвратить сильное перерегулирование и уменьшить раскачку. Коэффициент Д позволяет настроить вес или резкость данной компенсации, как и остальные коэффициенты регулируют свои составляющие. D составляющая в первую очередь нужна для быстрых систем, то есть для систем с резкими изменениями, такие как квадрокоптер или шпиндель станка под переменной нагрузкой.
D составляющая исправляет возможные будущие ошибки, анализируя скорость изменения входящего сигнала
Настройка регулятора #
Для настройки регулятора нужно варьировать коэффициенты:
- При увеличении
kP
увеличивается скорость выхода на установленное значение, увеличивается управляющий сигнал. Чисто математически система не может прийти ровно к заданному значению, так как при приближении к установке П составляющая пропорционально уменьшается. При дальнейшем увеличенииkP
реальная система теряет устойчивость и начинаются колебания. - При увеличении
kI
растёт скорость компенсации накопившейся ошибки, что позволяет вывести систему точно к заданному значению с течением времени. Если система медленная, аkI
слишком большой - интегральная сумма сильно вырастет и произойдёт перерегулирование, которое может иметь характер незатухающих колебаний с большим периодом. Поэтому интегральную сумму в алгоритме регулятора часто ограничивают, чтобы она не могла увеличиваться и уменьшаться до бесконечности. - При увеличении
kD
растёт стабильность системы, она не даёт системе меняться слишком быстро. В то же времяkD
может стать причиной неадекватного поведения системы и постоянных скачков управляющего сигнала, если значение с датчика шумит. На каждое резкое изменение сигнала с датчика Д составляющая будет реагировать изменением управляющего сигнала, поэтому сигнал с датчика нужно фильтровать.
Вот так выглядит процесс стабилизации при изменении коэффициентов:
Настройка регулятора - дело не очень простое. Начальные коэффициенты для подбора можно получить по следующему алгоритму: сначала выставляем все коэффициенты в 0
. Плавно увеличиваем kP
до появления незатухающих колебаний. Значение kP
, при котором они появились, запишем и обозначим как kP1
. Далее замеряем период колебаний системы в секундах, обозначим как T
. Итоговые коэффициенты получим так:
kP = 0.6 * kP1;
kI = kP / T * 2 * dt;
kD = kP * T / 8 / dt;
Например, незатухающие колебания появились при kP 20, период колебаний составил 3 секунды. Период dt в системе будет 50 мс (0.05 с). Считаем:
kP: 0.6*20 = 12
kI: 12/3*2*0.05 = 0.4
kD: 12*2/8/0.05 = 60
На полученных коэффициентах должны более-менее работать большинство систем, но не все. Также можно воспользоваться автоматическим тюнером коэффициентов, например два разных алгоритма встроены в библиотеку GyverPID.
Реализация #
Соединяя все рассмотренные выше уравнения, получим:
// (вход, установка, п, и, д, период в секундах, мин.выход, макс. выход)
int computePID(float input, float setpoint, float kp, float ki, float kd, float dt, int minOut, int maxOut) {
float err = setpoint - input;
static float integral = 0, prevErr = 0;
integral = constrain(integral + (float)err * dt * ki, minOut, maxOut);
float D = (err - prevErr) / dt;
prevErr = err;
return constrain(err * kp + integral + D * kd, minOut, maxOut);
}
Это готовая функция, которая принимает значение с датчика, установку, три коэффициента и время, а также ограничение выхода с регулятора. Как пользоваться этой функцией: функция должна вызываться с некоторым периодом, причем длительность этого периода нужно будет передать в функцию в секундах. Если попроще, можно использовать задержку. Но делать так не рекомендуется, лучше сделать таймер на миллис и работать с ним. Функция возвращает управляющий сигнал, то есть можно подать его например как ШИМ. Период dt имеет такой смысл: чем инерционнее у нас система, тем реже можно вычислять пид. Например для обогрева комнаты период можно поставить 1 секунду или больше, а для контроля за оборотами двигателя надо будет поставить пару десятков миллисекунд, то есть около сотни раз в секунду.
Библиотеки #
- GyverPID - моя библиотека со встроенным тюнером коэффициентов
- QuickPID - хорошая библиотека с интересными возможностями (оптимизация интегральной суммы, смешанный режим пропорционально ошибке/измерению)
- sTune - тюнер коэффициентов, несколько алгоритмов