传递函数离散化和PID控制的Python实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
本文参考:【Matlab】M文件编写PID调节传递函数 - 知乎 (zhihu.com),和

(3条消息) 传递函数如何转化为差分方程_乄微风绕指柔乄的博客-CSDN博客_传递函数离散化为差分方程感谢这两位大大,声明:本人小白,错误之处多多体谅

寒假车队培训:要求用G(s)=133/(s^2+25s)的传递函数设计一个增量式的pid
查看相关流程可知,首先要将S域的传递函数改写成差分方程,需要按照下述流程,S域传递函数——Z域离散函数——差分方程

我们使用一阶向前差分S=(Z-1)/T,和Y(k-n)=Y(k)*Z^(-n)得到

Z变换后的输出量和控制量之间的关系为

        Y(k)=133*T^2*U(k-2)+(2-25*T)*Y(k-1)+(25*T-1)*Y(k-2)

其中,Y为输出量,U为控制量,也就是说,再pid控制中,传递函数传递的是输出和控制量之间的关系。得到差分方程之后就可以方便多啦。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import matplotlib.pyplot as plt
import numpy as np
#正常显示中文
plt.rcParams['font.sans-serif'] = ['SimHei']
#正常显示负号
plt.rcParams['axes.unicode_minus']=False
#限制幅度
def limit(a,b):
if a>b:
return b
else:
return a
#增量式pid
class PID_incremental():
def __init__(self,wantted,Kp,Ki,Kd,delta_time):
self.Kp=Kp
self.Ki=Ki
self.Kd=Kd
self.wantted_val=wantted
self.time=delta_time
self.sum_err = 0
self.now_err = 0
self.last_err = 0
self.TotalMax = 1100
self.last_val = 0
self.last_last_val = 0
self.now_val = 0
self.last_control = 0
self.last_last_control = 0
self.now_control = 0
def iterator(self):
'''Z变换后的输出量和控制量之间的关系
Y(k)=133*T^2*U(k-2)+(2-25*T)*Y(k-1)+(25*T-1)*Y(k-2)'''
self.now_val = 133*(self.time)**2*self.last_last_control+ (2-25*self.time)*self.last_val+(25*self.time-1)*self.last_last_val
self.last_last_err = self.last_err
self.last_err = self.now_err
self.now_err = self.wantted_val - self.now_val
#控制器输出序列
self.change_control = self.Kp * (self.now_err - self.last_err) + self.Ki * self.now_err + self.Kd * (self.now_err - 2 * self.last_err+ self.last_last_err)
self.now_control += self.change_control*self.time
#限制now_val的最大值
self.now_control = limit(self.now_control,self.TotalMax)
self.last_last_control = self.last_control
self.last_control = self.now_control
self.last_last_val = self.last_val
self.last_val = self.now_val
return self.now_val
pid_incremental_bf=PID_incremental(133,300,0.0,0.0,0.01)
pid_incremental_af=PID_incremental(133,150,0.015,0.01,0.01)
pid_incremental_val_bf=[]
pid_incremental_val_af=[]
for i in range(100):
pid_incremental_val_bf.append(pid_incremental_bf.iterator())
pid_incremental_val_af.append(pid_incremental_af.iterator())
x=np.arange(0,100)
plt.title("增量式PID")
plt.xlabel('step/s')
plt.ylabel('current_value')
plt.plot(x,pid_incremental_val_bf)
plt.plot(x,pid_incremental_val_af)
plt.legend(['Adjust_Before','Adjust_After'])