python实现二阶状态轨迹的显示(含UI界面)

###matlab转python实现系列(三)

二阶状态轨迹的显示

程序结构
R,L,C皆为数字
R,L,C不为数字
重新输入
初始化界面
按键获取界面信息R,L,C
计算结果
弹窗警告
结果作图显示
自定义函数
#定义函数is_number

#判断一个字符串是不是数字。

def is_number(s):
#定义函数callback

ui界面上的"显示轨迹"按键的响应事件。

清除原fig上的内容,并调用is_number来判断界面上的信息是否有效,从而给出响应。

无效:错误提醒

有效:调用fun_show()函数,实现具体功能。

def callback():
#定义函数fun_show

显示二阶状态轨迹的函数实现。

根据不同情况的状态方程得出不同的结果,并在plot界面中显示。

def fun_show():
#定义函数ui_init

ui界面初始化,返回参数ui,以及输入框entry列表。

def ui_init():
#定义函数fig_init

plot界面初始化,返回视图fig,以及画布img。用以实现matplotlib与tkinter库的互通。

def fig_init(ui):
主要进程
a.

打开界面,运行ui_init ()函数,并存储ui界面,entry框列表信息。

b.

在a所得的ui界面上再作出plot界面,并存储plot界面,img画布信息。

c.

做出所有界面,并根据界面上的按键来响应用户输入信息。

此时主要运作的函数为callback和fun_show 。

最后根据输入信息来判断不同情况,进而解出状态方程,做出二阶状态轨迹图像的显示。

附整体代码
import tkinter as tk
import tkinter.font as tkFont
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import scipy.signal as signal
import scipy.integrate as si
import numpy as np
import math
#定义函数is_number 判断一个字符串是不是数字。
def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        pass
 
    try:
        import unicodedata
        unicodedata.numeric(s)
        return True
    except (TypeError, ValueError):
        pass
 
    return False
#定义函数callback 显示轨迹按键的界面响应。
def callback():
    plt.clf()
    if is_number(info[0].get()) and is_number(info[1].get()) and is_number(info[2].get()):
        fun_show()
    else:   
        tk.messagebox.showerror("错误","数据不符合要求,请重新输入")
#定义函数fun_show 显示二阶状态轨迹的函数实现。
def fun_show(): 
    #得到RLC电路的电阻,电感和电容。
    R=float(info[0].get())
    L=float(info[1].get())
    C=float(info[2].get())
    #阻尼系数
    a=R/(2*L)
    #谐振角频率
    w0=1/math.sqrt(L*C)
    #定义时间和电源电压
    t=np.arange(0,100,0.01)
    ut=np.array([1 for i in t])
    #过阻尼状态
    if a>w0 and a>0:
        B=math.sqrt(a*a-w0*w0)
        i_lt=((1/L)*np.exp(-a*t)*np.sinh(B*t))/(B*ut)
        v_ct=(np.exp(-a*t)*(np.exp(-a*t)/(a+B)-np.exp(-a*t)/(a-B)))/(2*B*L*C)+1
        plt.subplot(4,1,1)
        plt.plot(t,i_lt)
        plt.xlabel("time/s")
        plt.ylabel("Il(t)/A")
        plt.subplot(4,1,2)
        plt.plot(t,v_ct)
        plt.xlabel("time/s")
        plt.ylabel("Vc(t)/V")
        plt.subplot(4,1,3)
        plt.plot(v_ct,i_lt)
        plt.xlabel("Vc(t)/V")
        plt.ylabel("Il(t)/A")
        img.draw()

        font1=tkFont.Font(size=15, weight=tkFont.BOLD)
        title=tk.Label(ui,text="过阻尼状态",fg='Orchid',font=font1)
        title.place(relx=0.62,rely=0.02,width=120,height=45)
    #临界阻尼状态
    if a==w0 and a>0:
        i_lt=(1/L)*t*np.exp(-a*t)
        v_ct=(1/(L*C*a*a))*(1-(a*t+1)*np.exp(-a*t))
        plt.subplot(4,1,1)
        plt.plot(t,i_lt)
        plt.xlabel("time/s")
        plt.ylabel("Il(t)/A")
        plt.subplot(4,1,2)
        plt.plot(t,v_ct)
        plt.xlabel("time/s")
        plt.ylabel("Vc(t)/V")
        plt.subplot(4,1,3)
        plt.plot(v_ct,i_lt)
        plt.xlabel("Vc(t)/V")
        plt.ylabel("Il(t)/A")
        img.draw()

        font1=tkFont.Font(size=13, weight=tkFont.BOLD)
        title=tk.Label(ui,text="临界阻尼状态",fg='Indigo',font=font1)
        title.place(relx=0.62,rely=0.02,width=120,height=45)
    #欠阻尼状态
    if a<w0 and a>0:
        w1=math.sqrt(w0*w0-a*a)
        i_lt=w1*L*np.exp(-a*t)*np.sin(w1*t)
        v_ct=1-np.exp(-a*t)*(np.cos(w1*t)+np.sin(w1*t))#/(a*w1)
        plt.subplot(4,1,1)
        plt.plot(t,i_lt)
        plt.xlabel("time/s")
        plt.ylabel("Il(t)/A")
        plt.subplot(4,1,2)
        plt.plot(t,v_ct)
        plt.xlabel("time/s")
        plt.ylabel("Vc(t)/V")
        plt.subplot(4,1,3)
        plt.plot(v_ct,i_lt)
        plt.xlabel("Vc(t)/V")
        plt.ylabel("Il(t)/A")
        img.draw()

        font1=tkFont.Font(size=15, weight=tkFont.BOLD)
        title=tk.Label(ui,text="欠阻尼状态",fg='Chocolate',font=font1)
        title.place(relx=0.62,rely=0.02,width=120,height=45)
    #无阻尼状态
    if a==0:
        i_lt=L*w0*np.sin(w0*t)
        v_ct=1-np.cos(w0*t)
        plt.subplot(4,1,1)
        plt.plot(t,i_lt)
        plt.xlabel("time/s")
        plt.ylabel("Il(t)/A")
        plt.subplot(4,1,2)
        plt.plot(t,v_ct)
        plt.xlabel("time/s")
        plt.ylabel("Vc(t)/V")
        plt.subplot(4,1,3)
        plt.plot(v_ct,i_lt)
        plt.xlabel("Vc(t)/V")
        plt.ylabel("Il(t)/A")
        img.draw()

        font1=tkFont.Font(size=15, weight=tkFont.BOLD)
        title=tk.Label(ui,text="无阻尼状态",fg='LightCoral',font=font1)
        title.place(relx=0.62,rely=0.02,width=120,height=45)
#定义函数ui_init ui界面初始化,返回参数ui,以及输入框entry列表。
def ui_init():
    ui=tk.Tk()
    ui.resizable(False, False)           #取小最大化的按键

    ui.title("exp3:二阶状态轨迹")
    ui.geometry("900x600+0+0")          #设置界面大小

    ##设置输入界面
    label1=tk.Label(ui,text='请输入电阻/(欧姆Ω)',fg='Purple')
    label1.place(relx=0.12,rely=0.1,width=120,height=30)
    label2=tk.Label(ui,text='请输入电感/(亨利H)',fg='Purple')
    label2.place(relx=0.12,rely=0.3,width=120,height=30)
    label3=tk.Label(ui,text='请输入电容/(法拉F)',fg='Purple')
    label3.place(relx=0.12,rely=0.5,width=120,height=30)

    R1=tk.StringVar()
    R2=tk.StringVar()
    R3=tk.StringVar()

    entry1=tk.Entry(ui,textvariable = R1)
    entry1.place(relx=0.12,rely=0.1,width=120,y=30)
    entry2=tk.Entry(ui,textvariable = R2)
    entry2.place(relx=0.12,rely=0.3,width=120,y=30)
    entry3=tk.Entry(ui,textvariable = R3)
    entry3.place(relx=0.12,rely=0.5,width=120,y=30)
    info=[entry1,entry2,entry3]

    ##设置按键及点击事件
    button1=tk.Button(ui,text='显示轨迹',command=callback)
    button1.place(relx=0.12,rely=0.7,width=120,height=70)
    return ui,info
#定义函数fig_init plot界面初始化,返回视图fig,以及画板img。
def fig_init(ui):
    matplotlib.use('TkAgg')
    fig=plt.figure(num=1)
    img=FigureCanvasTkAgg(fig, master=ui)
    img.draw()
    img.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH)
    toolbar = NavigationToolbar2Tk(img, ui)
    toolbar.update()
    img._tkcanvas.place(relx=0.52,rely=0.1,width=300,height=600)
    return fig,img
#运行界面
ui,info=ui_init()
fig,img=fig_init(ui)
ui.mainloop()
  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值