Как смоделировать и настроить ПИД-регулятор
Я пытался смоделировать PID, используя библиотеку PID Бретта Борегарда, чтобы лучше понять его . Вот мой код.
#include <PID_v1.h>
const unsigned int numReadings = 500;
double analogVals[numReadings];
unsigned int i = 0;
int angle = 0;
//Определяем переменные, к которым мы будем подключаться
double Setpoint, Input, Output;
//Указываем ссылки и первоначальные параметры настройки
PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);
void setup()
{
//включаем ПИД
myPID.SetMode(AUTOMATIC);
Serial.begin(115200);
Setpoint = 300;
myPID.SetOutputLimits(-2,2);
myPID.SetSampleTime(100);
Input = random(292, 302) ;
}
void loop()
{
if (i % 2 == 0) {
Input += random(-2,3);
}
angle += 1 % 360;
Input += sin(angle*355/(113*180));
myPID.Compute();
Input += Output;
analogVals[i] = Input;
i++;
if (i>= numReadings)
{
for (int j = 0; j < i; j++) {
Serial.println(analogVals[j]);
}
i = 0; //возврат к началу массива, чтобы вы не пытались сохранить показания за пределами массива
}
}
Даже если я ограничу вывод PID очень маленьким значением, я получу огромные бессмысленные результаты этого кода. Он колеблется от -1000 до 1000. Я прочитал это https ://robotics.stackexchange.com/questions/167/what-are-good-strategies-for-tuning-pid-loops и попытался настроить свои параметры, но на самом деле это всего лишь выстрелы в темноте, я даже не могу заглушить эти огромные колебания. Как мне настроить PID, чтобы устранить греховную ошибку?
Заранее спасибо
@Andrew Hardy, 👍0
Обсуждение1 ответ
У меня нет вашего PID_v1.h, но я провел простой эксперимент, пытаясь управлять вашим примером с помощью простого P-контроллера вместо библиотеки PID. Я внес следующие изменения в ваш код:
...
double K_P = 1;
...
//myPID.Compute();
Output = K_P*(Setpoint - Input);
Input += Output;
Это работает для очень небольших количеств K_P
, но как только K_P
становится выше 2.0, он очень быстро становится нестабильным. Я думаю, это то, что вы наблюдаете. Причина для меня в том, что вы реализовали идеальный путь управления. В реальных задачах управления всегда будет некоторое поведение передачи
Поэтому я добавил в ваш код простой элемент PT1 (элемент задержки первого порядка), теперь ваша система намного стабильнее, и вы можете экспериментировать с факторами K, I и D. Здесь это работает с K_P даже выше 400:
// #include <PID_v1.h>
const unsigned int numReadings = 500;
double analogVals[numReadings];
unsigned int i = 0;
int angle = 0;
//Определяем переменные, к которым мы будем подключаться
double Setpoint, Input, Output;
double Input_PT1;
double K_P = 20;
//Указываем ссылки и первоначальные параметры настройки
//PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);
void setup()
{
//включаем ПИД
// myPID.SetMode(AUTOMATIC);
Serial.begin(115200);
Setpoint = 300;
// myPID.SetOutputLimits(-2,2);
//myPID.SetSampleTime(100);
Input = random(292, 302) ;
}
void loop()
{
if (i % 2 == 0) {
Input += random(-2, 3);
}
angle += 1 % 360;
Input += sin(angle * 355 / (113 * 180));
//myPID.Compute();
Output = K_P * (Setpoint - Input_PT1);
Input += Output;
// запускаем PT1
Input_PT1 -= Input_PT1 / 25;
Input_PT1 += Input / 25;
// конец PT1
analogVals[i] = Input_PT1;
i++;
if (i >= numReadings)
{
for (int j = 0; j < i; j++) {
Serial.println(analogVals[j]);
}
i = 0; //возврат к началу массива, чтобы вы не пытались сохранить показания за пределами массива
}
}
Небольшой совет:
- Приведенный выше скетч не инициализирует
Input_PT1
, поэтому до достижения устойчивого значения 300 требуется несколько секунд. Если вы не хотите ждать, просто инициализируйтеInput_PT1
с 300. Но именно здесь можно начать увеличивать сначала коэффициенты I, затем D, чтобы попытаться увеличить скорость для достижения устойчивого значения 300 и почувствовать, какое влияние окажут части I и D. Input_PT1
— неподходящее имя, поскольку это выход элемента PT1, но поскольку вы используете его в качестве входа PID, я не менял.
Вот рисунок того, что я реализовал в отличие от вашего скетча (по крайней мере, я на это надеюсь ;-))
- Управление скоростью вентилятора с помощью библиотеки Arduino PID
- Проблема с датчиком температуры и влажности DHT11
- Получение ошибки ets 8 января 2013,rst cause:4,boot mode(1,6) wdt reset
- ПИД-регулятор для управления скоростью двигателя
- Выводы прерываний Arduino Mega 2560 и отображение портов с помощью поворотного энкодера
- Данные DHT11 из Arduino UNO в Firebase через ESP8266
- Объяснение кода MPU6050
- Измерение скорости двигателя постоянного тока с помощью поворотного энкодера
пожалуйста, оставьте ссылку на библиотеку PID?, @Jose Enrique Calderon