Skip to main content
 首页 » 编程设计

Python PID模拟

2025年05月04日7三少

我想弄清楚如何在 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) 

我想更改控制反馈的部分,以便它更接近地模拟我的系统(Plant),但这就是我遇到的问题。我通过应用一个步骤并记录输出并绘制它来确定系统(工厂)的传递函数。根据曲线、直流增益和时间常数,我得出传递函数为 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。

请您参考如下方法:

  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; 
   } 
} 

希望这会有所帮助。