Подобрать параметры PID

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

Здравствуйте. На просторах интернета нашёл (не сам написал) функцию PID регулирования.

// (вход, установка, п, и, д, период в секундах, мин.выход, макс. выход)
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);
}

Функция вызывается раз в 2 секунды

digitalWrite(tenpin, computePID(steinhart, brewtemp, PP, II, DD, 2, 0, 1));
// (вход, установка, п, и, д, период в секундах, мин.выход, макс. выход)

и подаёт сигнал на твердотельное реле, которое коммутирует ТЭН в бойлере. На всякий случай скажу, что ТЭН на 1500 Вт, объём воды в бойлере - 300 мл, теплопотери назвать не могу, стоит задача поддерживать температуру 94С. На 100% мощности (исключительно пропорциональное регулирование) система выходит на заданную температуру за 200-240 секунд, но за счёт инертности поддерживать P-регулированием такую систему невозможно - колебания будут очень большими.

Подбираю параметры P,I,D уже не первый день. По моему опыту коэффициент P в таких системах должен находиться на уровне 0.1 - 1, я его установил на 0.4, а вот с I и D мучаюсь долго.

При установке I и D 1 и 4 соответственно, идут колебания от 91.8 до 100 с затуханиями, однако, и с всплесками до 97С

Значения 1 - 20, как и 5 - 20 и 3 - 10 дают колебания от 93 до 98.
Пробовал повышать коэффициенты до значений P20 / I25 - через 10 минут начинается уход выше заданных значений.
Кто может дать совет по настройке? Строить модель, учитывающую все параметры, я не могу, тем более,я всех параметров и не знаю.
Как сделать автонастройку тоже не знаю.
BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Просто спросить хочу: Почему PID? Не проще ли использовать два/три термодатчика и греть/не греть используя их показания?

nik182
Offline
Зарегистрирован: 04.05.2015

В условиях 300 мг на 1500 ватт и системой вкл откл очень важно становится как это вкл откл осуществляется. Если это 50 Гц через реле или тиристор то ПИД можно настраивать до маланиной свадьбы и не настроить. Слишком большая ошибка может случиться, если команда на отключение придёт в начале полупериода сети. 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

nik182 пишет:

В условиях 300 мг на 1500 ватт и системой вкл откл очень важно ...

300 миллилитров это порядка 300 грамм однако

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

BOOM пишет:

Просто спросить хочу: Почему PID? Не проще ли использовать два/три термодатчика и греть/не греть используя их показания?

Потому что этот метод уже зарекомендовал себя на бойлерах с ТЭНом. В другом месте (бойлер 1500 мл) отлично справляется.

nik182
Offline
Зарегистрирован: 04.05.2015

ua6em пишет:

nik182 пишет:

В условиях 300 мг на 1500 ватт и системой вкл откл очень важно ...

300 миллилитров это порядка 300 грамм однако

ну да, согласен, лишнюю м на радостях воткнул, но 1.5кВт на 300 грамм именно и имел в виду. Поток тепла от тэна может греть такой объём быстрее, чем реагирует измеритель температуры - тоже дополнительная ошибка. 

DIVGENY
Offline
Зарегистрирован: 23.08.2016

мой пид регулятор в мозгу выдал такую формулу

  мощность тена 1 : обьем 1 = мощность тена 2 : обьем 2

  мощность тена 2 = 0.5 кВт, пошел я заварю себе кофейку... у меня там простой термостат...

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

Опытным путём прихожу к следующему (вдруг кто будет искать, это относится к коду в первом сообщении, в других PID-регуляторах P-коэффициент может быть обратнопропорциональным):

1. Ставим всё в ноль.

2. Коэффициент P нужно поставить такой, чтоб он не раскачивал систему сильно. Ставлю 2 - температура прёт без остановки до целевого показателя, следовательно, наблюдается жуткий перебег, ставлю 0.4 - температура растёт почти до целевого значения, но приближаясь к нему, ТЭН всё чаще отключается, ставлю 0.05 - растёт ооочень медленно. Опытным путём прихожу к значению 0.3 +/- 0.1

3. D - это демпфер. Пока мне сложно объяснить его воздействие, но интуитивно понимаю, что он сглаживает колебания.

nik182
Offline
Зарегистрирован: 04.05.2015

D производная. Она реагирует на резкие скачки, которых в нагревных системах можно получить только плеснув холодной воды в горячий бойлер. 

inspiritus
Offline
Зарегистрирован: 17.12.2012

Твердотелка какая? С z ?

вообще то при такой малоинерционности лучше иметь хотяббы пару тэнов (например 1+0.5) ​и при приближении к уставке выключать мощный и доводить температуру числоимпульным способом менее мощным тэном.

я когдато делал такую бяку на 4х тэнах для какого то хим.реактора- 3 вкл/выкл один регулирующий не фазоимпульсным а числоимпульсным способом
 

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

inspiritus пишет:

Твердотелка какая? С z ?

 

Везде пишут, что с zero-cross, но я сам не разбирал, поэтому верю на слово. Я уже подобрал коэффициенты, с которыми есть выход на заданную температуру, но минут 5-10 она колеблется в пределах 1-2 градусов от целевой, потом устаканивается. Всё работает, но только спустя 10 минут. Хотелось бы колебания раньше укротить. И "слабый" ТЭН тут не нужен - мощный можно включать раз в 10 секунд на 1 секунду для поддержания температуры.

Повторюсь, я уже делал подобное, но там объём в 6 раз больше.

DIVGENY
Offline
Зарегистрирован: 23.08.2016

andreykrasnodar пишет:

Повторюсь, я уже делал подобное, но там объём в 6 раз больше.

так там инерция была, поэтому и получилось, а тут из ваших же параметров нагрев может происходить до 4 сек, если  цикл опроса через каждые две. Просится кроме пропуска интервалов с помощью детектора нуля пропускать периоды для уменьшения мощности тэна при выходе на заданную температуру. Просто ради эксперимента  нагрейте воду до предела и отключите тэн. Пусть постепенно остывает. Затем на 80гр включите  ровно на 1, 2 секунды и посмотрите разбег по температуре.

 

b707
Offline
Зарегистрирован: 26.05.2017

andreykrasnodar пишет:

Опытным путём прихожу к следующему

Адррей, про принципы ручного подбора коэф почитайте тут:

http://arduino.ru/forum/pesochnitsa-razdel-dlya-novichkov/etyudy-dlya-pesochnitsy-teoriya-upravleniya-i-regulyatory#comment-512055

например, то что у вас при Kp = 2 наблюдается "жуткий перебег" - это абслютно нормально, так и должно быть. Это не обязательно означает, что Kp надо уменьшать - этот перебег устраняется подбором других коэффициентов

b707
Offline
Зарегистрирован: 26.05.2017

пример подбора:

как видите. сначала по Kp есть перебег, но потом его убирают подбором Kd

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

Спасибо. Собственно, так и делаю. Но коэффициент I вообще не трогаю - и без него колебания около уровня установки, а когда менял - был перебег.

Буду повышать P и сглаживать с помощью D. Ещё раз спасибо.

nik182
Offline
Зарегистрирован: 04.05.2015

Странно. Только с помощью I можно точно держать уставку. Надо только без фанатизма этот коэффициент увеличивать. Дело в том что у P и D есть зона не чувствительности около уставки. При Ваших кр 0.3 это 3 градуса. При малых отклонениях нужно время, чтобы набрать ошибку. Именно это делает интегральная составляющая. 

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

nik182 пишет:

Странно. Только с помощью I можно точно держать уставку. Надо только без фанатизма этот коэффициент увеличивать. Дело в том что у P и D есть зона не чувствительности около уставки. При Ваших кр 0.3 это 3 градуса. При малых отклонениях нужно время, чтобы набрать ошибку. Именно это делает интегральная составляющая. 

Возможно, I должна быть очень маленькой. Например, 0.05.

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

Нашёл вот такой способ:

1. Выставляем все коэффициенты (Kp, Ki, Kd) в 0.

2. Начинаем постепенно увеличивать значение Kp и следим за реакцией системы. Нам нужно добиться, чтобы в системе начались устойчивые колебания (вызванные перерегулированием). Увеличиваем Kp, пока колебания системы не стабилизируются (перестанут затухать). У меня это значение около 1.

3. Запоминаем текущее значение (Ku = 1) и замеряем период колебаний системы, у меня оно около 120 с. (Tu = 120).



Теперь используем полученные значения Ku и Tu для расчета всех параметров ПИД регулятора по формулам:



Kp = 0.6 * Ku = 0.6

Ki = 2 * Kp / Tu = 0.01

Kd = Kp * Tu / 8 = 9

Методом подбора приходил к подобным результатам (0 и 0.01 почти одно и то же), но D в 2 раза выше.

nik182
Offline
Зарегистрирован: 04.05.2015

Если про I - 0 и 0.01 , то это кардинально разные вещи. При нуле интегральный компонент не работает. При любом отличном от нуля значении происходит интегрирование. В отличии от P D, I суммируется на каждом шаге. За 10 шагов можно считать что Кi из 0.01 превратился в 0.1 и чем больше шагов ПИД провернулось, тем больше. Именно это свойство I канала ПИД удерживает точку уставки. 

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

Добился минимальных колебаний (при установленном значении 94 очень медленно колеблется от 93.5 до 95), по сути помогла формула. Но отчего-то бывают редкие всплески до 96+.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

andreykrasnodar пишет:

Добился минимальных колебаний (при установленном значении 94 очень медленно колеблется от 93.5 до 95), по сути помогла формула. Но отчего-то бывают редкие всплески до 96+.

для 300 грамм сильно большая мощность, на подходе к заданной температуре надо снизить раз в пять, если потери невелики, я бы поинтересовался у тех, кто делал инкубаторы, там удержание в пределах десятых градуса

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

ua6em пишет:

andreykrasnodar пишет:

Добился минимальных колебаний (при установленном значении 94 очень медленно колеблется от 93.5 до 95), по сути помогла формула. Но отчего-то бывают редкие всплески до 96+.

для 300 грамм сильно большая мощность, на подходе к заданной температуре надо снизить раз в пять, если потери невелики, я бы поинтересовался у тех, кто делал инкубаторы, там удержание в пределах десятых градуса

На подходе к целевой как раз мои коэффициенты (0.4/0.01/20, уже наизусть выучил) и снижают мощность раз в 5 (субъективно), снижая время включения ТЭНа. Но выйти к таким значениям,чтобы колебания были в пределах пары десятых, увы, не получилось.

nik182
Offline
Зарегистрирован: 04.05.2015

Субъективно это знатный критерий. Скажу не очевидную вещь. Ваш расчёт даёт средние по больнице параметры. Это я про 120 секунд - найденное Вами постоянная времени системы.  В Вашем случае у ПИД должно быть два канала управления, потому что постоянные времени реакции системы существенно различаются для подъёма и спада температуры. И коэффициенты будут разные, но при усреднении давать то, что рассчитали Вы. И подводя итог, если действительно нужно держать температуру, то надо уходить от зерокросс и вводить два канала ПИД. Иначе от выбросов не избавиться.

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

Всё сделал, но температура как вкопанная стоит на 3.5 градуса выше.

nik182
Offline
Зарегистрирован: 04.05.2015

Это очень близко к зоне нечувстсвительности пропорционального канала. Выведите в сериал значение ПИД. Если оно равно нулю при этом. Значит оно. Вообще при настройке ПИД на каждом шаге выводить значение каждого канала и текущую ошибку, что бы видеть, как каналы реагируют на величину ошибки. Очень полезно для внутреннего понимания. Через какое то время, когда наберётся собственный экспириенс , по данным каналов настройка ПИД будет занимать очень короткое время.

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

nik182 пишет:

Это очень близко к зоне нечувстсвительности пропорционального канала. Выведите в сериал значение ПИД. Если оно равно нулю при этом. Значит оно. Вообще при настройке ПИД на каждом шаге выводить значение каждого канала и текущую ошибку, что бы видеть, как каналы реагируют на величину ошибки. Очень полезно для внутреннего понимания. Через какое то время, когда наберётся собственный экспириенс , по данным каналов настройка ПИД будет занимать очень короткое время.

Попробую. Не претендую на истину, но мне кажется, что "перелёт" может быть следствием высокого коэффициента Ki.

nik182
Offline
Зарегистрирован: 04.05.2015

Вот и посмотрите, как ведёт себя Кi. Он вообще должен работать в отрицательную сторону к ошибке и при уменьшении ошибки обнуляться. Его сущность такая. Я чаще всего использую ПИ регулятор. Д канал с очень маленьким коэффициентом, чтобы реагировать на очень большие скачки ошибки. 

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

nik182 пишет:

Вот и посмотрите, как ведёт себя Кi. Он вообще должен работать в отрицательную сторону к ошибке и при уменьшении ошибки обнуляться. Его сущность такая. Я чаще всего использую ПИ регулятор. Д канал с очень маленьким коэффициентом, чтобы реагировать на очень большие скачки ошибки. 

Не знаю, как правильнее написать, но вывел в порт значения так

  Serial.println();
  Serial.print("p=");Serial.println(err);
  Serial.print("i=");Serial.println(integral);
  Serial.print("d=");Serial.println(D);
  Serial.println(constrain(err * kp + integral + D * kd, minOut, maxOut)); //это результат
  Serial.println();

 

  // а может, нагляднее было бы так, но я этот способ не использовал
  Serial.println();
  Serial.print("p=");Serial.println(err * kp);
  Serial.print("i=");Serial.println(integral);
  Serial.print("d=");Serial.println(D * kd);
  Serial.println(constrain(err * kp + integral + D * kd, minOut, maxOut));
  Serial.println();

во время разогрева значения сильно меняются, при достижении целевого, например, так

p=-1.19, i=0.62, d=0.07, результат 1 (тут высок вклад d, т.к. коэффициент kD = 62, что в итоге и даёт единицу на выходе.)
p=-1.20, i=0.61, d=-0.01, результат 0, оно и понятно.
 
При долгом простое (тот момент, когда идёт перебег и значение температуры стоит несколько выше нужной) составляющая P всегда отрицательная и составляет около -1.5 (с коэффициентом Kp = 1.2 это -1.8), I и D ничтожно малы: интегральная составляющая обычно равна нулю, дифференциальная - десятые или сотые как со знаком плюс, так и минус, но с множителем 62 даёт ощутимый результат.

Что это может мне дать, понятия не имею. Хотя... понаблюдал и подумал, что надо P-коэффициент увеличить хотя бы с 1.2 до 2.0. Пробую - и при целевом 90С вижу на экране значения от 90.4 до 92. В правильном ли направлении иду, пока неясно: значение температуры снизилось, но колебания возросли.

nik182
Offline
Зарегистрирован: 04.05.2015

Как минимум интеграл надо вывести из кострайн. Иначе он не будет давать отрицательных значений и соответственно не будет подтягивать к уставке при переборе. Или заменить в кострайн минаут на минус махаут. После этого температура должна встать на место.

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

Правильно ли то, что I-составляющая не может воздействовать в отрицательную сторону?

То есть, ошибка ограничена значениями 0 и 1, а значит, работает только "в плюс".

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

nik182 пишет:
Как минимум интеграл надо вывести из кострайн. Иначе он не будет давать отрицательных значений и соответственно не будет подтягивать к уставке при переборе. Или заменить в кострайн минаут на минус махаут. После этого температура должна встать на место.

О том же самом подумал. Писал не видя ваш ответ. Спасибо, значит, мыслю в нужном направлении.

nik182
Offline
Зарегистрирован: 04.05.2015

Это часто бывает, когда из просторов интернета непонятный код. В этом явная ошибка.

nik182
Offline
Зарегистрирован: 04.05.2015

Дубль. Удалил.

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

nik182 пишет:
Это часто бывает, когда из просторов интернета непонятный код. В этом явная ошибка.

Верно, код скопировал не вникая, и только когда вы написали про вывод в порт, наблюдая за изменением значений, понял что куда. Спасибо за это.

Собственно, i-составляющую надо ограничивать значениями -1...+1, она вкупе с коэффициентом 0.006 за пару сотен проходов может достичь даже крайних значений, что вносит коррективы в итоговый сигнал.

Подбор по формуле неплох, по крайней мере показывает примерные значения, от которых уже можно "плясать".

Тему можно закрывать.

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

Для тех, кто захочет регулировать с помощью PID температуру котла:

  // (вход, установка, kP, kI, kD, период в секундах)
  int computePID(float input, float setpoint, float kp, float ki, float kd, float dt) {
  float err = setpoint - input;
  static float integral = 0, prevErr = 0;
  integral = constrain(integral + (float)err * dt * ki, -1, 1);
  float D = (err - prevErr) / dt;
  prevErr = err;  
  return constrain(err * kp + integral + D * kd, 0, 1);
}





//Функция вызывается раз в секунду
//6й пин, steinhart - текущая температура, boilertemp - температура, к которой стремимся,
// PP,II,DD - коэффициенты, у меня они 2, 0.006, 32.
digitalWrite(6, computePID(steinhart, boilertemp, PP, II, DD, 1));

 

uragan
Offline
Зарегистрирован: 23.02.2015

При такой высокой удельной мощности можно намерять что угодно. Вы уверены что температура по объему не гуляет несколько градусов.

ELECTROS
Offline
Зарегистрирован: 28.05.2021

Частота вызова регулятора играет роль, помоему секунда это много на такой мощности, надо чаще.

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

uragan пишет:

При такой высокой удельной мощности можно намерять что угодно. Вы уверены что температура по объему не гуляет несколько градусов.

Ещё как гуляет! Но, во-первых, вода циркулирует (теплая поднимается вверх, холодная - вниз), а замер происходит всегда в одной точке. И условия не меняются, поэтому и решил использовать PID.

По другому опыту: ведётся замера температуры корпуса бойлера, но там готовое устройство с AliExpress с автоподбором коэффициентов (XMT7100). Всё успешно работает.

Добавлю. У меня всё получилось, правда, "железобетонное устаканивание температуры" происходит только через полчаса, до этого температура гуляет на +1/-1С

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

ELECTROS пишет:

Частота вызова регулятора играет роль, помоему секунда это много на такой мощности, надо чаще.

Возможно. 

nik182
Offline
Зарегистрирован: 04.05.2015

ELECTROS пишет:

Частота вызова регулятора играет роль, помоему секунда это много на такой мощности, надо чаще.

ТС определил постоянную времени 120 секунд. 1 секунда это лучше чем 1 %. Вполне достаточно для алгоритма. Надо оперировать не мнением, а расчётами.

ELECTROS
Offline
Зарегистрирован: 28.05.2021

nik182 пишет:

ELECTROS пишет:

Частота вызова регулятора играет роль, помоему секунда это много на такой мощности, надо чаще.

ТС определил постоянную времени 120 секунд. 1 секунда это лучше чем 1 %. Вполне достаточно для алгоритма. Надо оперировать не мнением, а расчётами.


Щас глянул первое сообщение, действительно не обратил внимание, но извольте откуда 120? (видимо имеется ввиду период колебаний при К=1). Короче дальше первого поста осилил прочитать , действительно так и получается, но для такого объёма, странно как то...

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

Внесу свою поправку. Получаемые данные не писал в тему, думал, никто и не обратит внимание, а потом забыл. При K=1 период колебаний был около 7 минут (точное значение не помню, за это время было много данных, в памяти всё не держал), из чего следует вывод, что время опроса может быть хоть 5 хоть 10 секунд, ki должен быть очень мал (0.001 - 0.1), kp в пределах пяти, а вот kD - очень большим (у меня в итоге 30).

Короче, система стабилизировалась, всё работает.

ELECTROS
Offline
Зарегистрирован: 28.05.2021

Выше то по другому написано ж было. Ну а если так, то с таким временем конечно...

uragan
Offline
Зарегистрирован: 23.02.2015

Так если температура  гуляет( как по времени, так и по месту)- какую принимаете за истину?
еще и инерционность датчика температуры имеет место быть.

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

uragan пишет:

Так если температура  гуляет( как по времени, так и по месту)- какую принимаете за истину?
еще и инерционность датчика температуры имеет место быть.

За истину принимаю ту, что показывает датчик. Его положение и инерционность неизменны, а система умеет "предсказывать" температуру в будущем.

uragan
Offline
Зарегистрирован: 23.02.2015

andreykrasnodar пишет:

uragan пишет:

Так если температура  гуляет( как по времени, так и по месту)- какую принимаете за истину?
еще и инерционность датчика температуры имеет место быть.

За истину принимаю ту, что показывает датчик. Его положение и инерционность неизменны, а система умеет "предсказывать" температуру в будущем.

допустим по времени попали, а по месту- тоже постоянно? Может выбросы из-за этого? Тогда никакой пид не поможет.

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

uragan пишет:

andreykrasnodar пишет:

uragan пишет:

Так если температура  гуляет( как по времени, так и по месту)- какую принимаете за истину?
еще и инерционность датчика температуры имеет место быть.

За истину принимаю ту, что показывает датчик. Его положение и инерционность неизменны, а система умеет "предсказывать" температуру в будущем.

допустим по времени попали, а по месту- тоже постоянно? Может выбросы из-за этого? Тогда никакой пид не поможет.

Конструкция бойлера такая, что в трубке, где установлен датчик, постоянно циркулирует вода за счёт конвекции. (Хотя, думаю, в любом бойлере вода точно так же будет циркулировать).

Очень грубо смоделирую ситуацию: если температура упадёт на полградуса, PID включит ТЭН на 3 секунды, вода вокруг ТЭНа на некоторое время поднимется на 2 градуса, а за следующие 10 секунд эта же вода смешается с остывшей и общий объём воды вернётся к целевой температуре. Вот так и происходит поддержание заданной температуры. На практике это работает.

uragan
Offline
Зарегистрирован: 23.02.2015

А как это стыкуется с моментами замера температуры: можете замерить в момент включения ТЭНа,  а можете через 10 секунд. Это просто пример, что не все так просто. А еще и инерционность датчика накладывается. Понятно что работает. Вопрос только к точности поддержания температуры. Насколько адекватно требование такой точности.

andreykrasnodar
Offline
Зарегистрирован: 04.10.2020

uragan пишет:

можете замерить в момент включения ТЭНа,  а можете через 10 секунд. 

Замер происходит раз в секунду.