2

我想弄清楚如何在 python 中模拟控制系统。这是我到目前为止所拥有的:

PID.py - 设置 Kp、Ki、Kd 的函数,以及基于错误生成输出的函数。前任。PID.genout(错误)

PIDPlot.py - 根据步进输入绘制输出。这是代码示例:

for i in range(1, 51):

    # summing node
    err = sp - fb

    # PID block
    outv = pid.GenOut(err)

    # control feedback
    if sp > 0:
        fb += (outv - (1.0/i))

    # start with sp = 0, simulate a step input at t(10)
    if i > 5:
        sp = 10

    # add sp and outv to there lists
    sp_list.append(sp)
    fb_list.append(fb)
    sample_list.append(i * .05)



    time.sleep(.05)

我想更改控制反馈的部分,以便更紧密地模拟我的系统(工厂),但这就是我卡住的地方。我通过应用一个步骤并记录输出并绘制它来确定系统(工厂)的传递函数。根据曲线、直流增益和时间常数,我得出了 0.92/16s +1 的传递函数。当我像这样在 Python 中绘制阶跃响应时:

from numpy import min, max
from scipy import linspace
from scipy.signal import lti, step

# making transfer function
# example from Ogata Modern Control Engineering 
# 4th edition, International Edition page 307

# num and den, can be list or numpy array type
num = [-0.93] 

#denominator of the form s^2 + s +1
den = [16, 1]

tf = lti(num, den)

# get t = time, s = unit-step response
t, s = step(tf)

# recalculate t and s to get smooth plot
t, s = step(tf, T = linspace(min(t), t[-1], 500))

# get i = impulse
#t, i = impulse(tf, T = linspace(min(t), t[-1], 500))

from matplotlib import pyplot as plt

#plt.plot(t, s, t, i)
plt.plot(t, s)
plt.title('Transient-Response Analysis')
plt.xlabel('Time(sec)')
plt.ylabel('Amplitude')
plt.hlines(1, min(t), max(t), colors='r')
plt.hlines(0, min(t), max(t))
plt.xlim(xmax=max(t))
plt.legend(('Unit-Step Response',), loc=0)
plt.grid()
plt.show()

它与我绘制的数据很好地匹配。现在如何使用此传递函数在 PIDPlot 中生成反馈?然后从那里我可以尝试编写代码来根据系统(工厂)自动调整 pid。

4

1 回答 1

-1
  1. 在 PIDPlot 中生成反馈 我在代码中没有看到传递函数,你能告诉我吗?

  2. 如果您想调整 PID 并为您的 DC 系统找到最佳 Kp、Ki、Kd,您需要考虑图表中的这些波动和变化。您需要动态控制 PID 常数,这意味着您需要方法。

这是一个非常有用的博客,讨论在 Python 中调整 PID。我之前写了一个 PID 控制算法,并从这个博客中获得了一些想法,非常有帮助。

http://brettbeauregard.com/blog/2011/04/improving-the-beginner%E2%80%99s-pid-tuning-changes/

/*working variables*/
unsigned long lastTime;
double Input, Output, Setpoint;
double ITerm, lastInput;
double kp, ki, kd;
int SampleTime = 1000; //1 sec
void Compute()
{
   unsigned long now = millis();
   int timeChange = (now - lastTime);
   if(timeChange>=SampleTime)
   {
      /*Compute all the working error variables*/
      double error = Setpoint - Input;
      ITerm += (ki * error);
      double dInput = (Input - lastInput);

      /*Compute PID Output*/
      Output = kp * error + ITerm - kd * dInput;

      /*Remember some variables for next time*/
      lastInput = Input;
      lastTime = now;
   }
}

void SetTunings(double Kp, double Ki, double Kd)
{
  double SampleTimeInSec = ((double)SampleTime)/1000;
   kp = Kp;
   ki = Ki * SampleTimeInSec;
   kd = Kd / SampleTimeInSec;
}

void SetSampleTime(int NewSampleTime)
{
   if (NewSampleTime > 0)
   {
      double ratio  = (double)NewSampleTime
                      / (double)SampleTime;
      ki *= ratio;
      kd /= ratio;
      SampleTime = (unsigned long)NewSampleTime;
   }
}

希望这会有所帮助。

于 2015-05-21T14:39:06.630 回答