Как смоделировать и настроить ПИД-регулятор

Я пытался смоделировать 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, чтобы устранить греховную ошибку?

Заранее спасибо

, 👍0

Обсуждение

пожалуйста, оставьте ссылку на библиотеку PID?, @Jose Enrique Calderon


1 ответ


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, я не менял.

Вот рисунок того, что я реализовал в отличие от вашего скетча (по крайней мере, я на это надеюсь ;-))

,