水箱水位控制程序

程序仿真的系统结构如下

软件界面如下

第一张图为执行机构的输出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()



        
原文地址:https://www.cnblogs.com/Arago/p/5447492.html