我试图弄清楚如何在python中模拟控制系统。这就是我到目前为止所做的:
PID.py - 用于设置Kp,Ki,Kd和一个基于错误生成输出的函数。恩。 PID.genout(ERR)
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)
我想更改控制反馈的部分,以便更紧密地模拟我的系统(工厂),但这就是我遇到的问题。我通过应用一个步骤并记录输出并绘制它来确定系统(工厂)的传递函数。根据曲线,直流增益和时间常数I为传递函数提出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。
答案 0 :(得分:-1)
在PIDPlot中生成反馈 我没有看到代码中的传递函数,你能告诉我吗?
如果你想调整PID并为你的直流系统找到最好的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;
}
}
希望这会有所帮助。