程序仿真的系统结构如下
软件界面如下
第一张图为执行机构的输出u的变化曲线(第一个水箱的进水量)
第二张图为第一个水箱(上水箱)的水位变化曲线
第三张图为第二个水箱(下水箱)的水位变化曲线
控制面板如下
设定值默认为10
默认为自动控制,点击手动控制按钮后,控制对象的输入u不会自动变化。
手动控制切换自动控制未作无扰切换处理
输入有限幅0~20,有抗积分饱和处理
python版本3.4.3,matplotlib版本1.5.1,numpy版本1.11.0
import matplotlib.pyplot as plt import numpy as np import time import threading import tkinter method=1 #method为1时自动控制,为其他值时手动控制 sp=10 #设定值 T1=10 #第一个水箱的参数 T2=20 #第二个水箱的参数 k1=1.5 #第一个水箱的参数 k2=1.2 #第二个水箱的参数 deltat=0.05 #仿真的步距 showt=0.5 #显示的步距 #pid控制参数 kp=2 ki=0.05 kd=0 #输出限幅 umax=20 umin=0 #初始化 y1=0 #第一个水箱的初始水位 y2=0 #第二个水箱的初始水位 t=0 #运行的时间 i=0 u=1 #第一个水箱的进水量 #三个显示窗口的设置 p1=plt.subplot(3,1,1) p1.set_title('inflow u') p2=plt.subplot(3,1,2) p2.set_title('water level y1') p3=plt.subplot(3,1,3) p3.set_title('water level y2') plt.plot(0,0) def loop(): global y1,y2,t,i,u,sp Y1=[y1] Y2=[y2] T=[t] U=[u] xi=0 e0=0 while True: i=i+1 t=t+deltat #输出限幅 if u<umin: u=umin if u>umax: u=umax #控制对象仿真 y1=(k1*u-y1)/T1*deltat+y1 y2=(k2*y1-y2)/T2*deltat+y2 T+=[t] Y1+=[y1] #记录下第一个水箱的历史水位 Y2+=[y2] #记录下第二个水箱的历史水位 U+=[u] #记录下历史输入 if showt/deltat<=i : i=0 if method==1: #pid控制算法 e=sp-y2 xp=kp*e xi=xi+ki*e xd=(e-e0)*kd/showt e0=e u=xp+xi+xd #抗积分饱和 if xp+xi>umax: xi=umax-xp if xp+xi<umin: xi=umin-xp p1.plot(T,U) p2.plot(T,Y1) p3.plot(T,Y2) p3.set_xlabel('y2=%.2f' %y2) plt.draw() time.sleep(showt) def gui(): global entrysp,entryu root=tkinter.Tk() framesp=tkinter.Frame(root) frameu=tkinter.Frame(root) frameam=tkinter.Frame(root) labelsp=tkinter.Label(framesp,text='设定值') labelu=tkinter.Label(frameu,text='输入u ') entrysp=tkinter.Entry(framesp) entryu=tkinter.Entry(frameu) buttonsp=tkinter.Button(framesp,text='更改',command=gui_sp) buttonu=tkinter.Button(frameu,text='更改',command=gui_u) buttonm2a=tkinter.Button(frameam,text='自动控制',command=gui_m2a) buttona2m=tkinter.Button(frameam,text='手动控制',command=gui_a2m) framesp.pack() frameu.pack() frameam.pack() labelsp.pack(side='left') entrysp.pack(side='left') buttonsp.pack(side='left') labelu.pack(side='left') entryu.pack(side='left') buttonu.pack(side='left') buttonm2a.pack(side='left') buttona2m.pack(side='left') root.mainloop() def gui_sp(): global sp strsp=entrysp.get() sp=float(strsp) def gui_u(): global u stru=entryu.get() u=float(stru) def gui_m2a(): global method method=1 def gui_a2m(): global method method=0 threading.Thread(target=loop,args=()).start() threading.Thread(target=gui,args=()).start() plt.show()