首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >python简单电路仿真有误?

python简单电路仿真有误?

提问于 2024-04-18 09:49:10
回答 0关注 0查看 17

我建立一个简单的由电池、开关和负载的电路,目的是通过开关实时操控来量测电路中电压、电流的变化。现在的代码如下:

代码语言:text
复制
# 模块引用
import tkinter as tk
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.animation import FuncAnimation

电路仿真

代码语言:text
复制
class CircuitSimulator:
    def __init__(self, t_values, initial_switch_state=True):
        self.t_values = t_values
        self.VoltageOverTime = np.full_like(t_values, V_battery)  # 初始时所有时间点电压均为电池电压
        self.CurrentOverTime = np.full_like(t_values, V_battery / R_load)  # 初始化电流数组
        self.switch_states = np.ones_like(t_values, dtype=bool) * initial_switch_state  # 记录每个时间点开关的状态
        self.previous_switch_state = initial_switch_state  # 记录上一个开关状态
        self.previous_switch_time_index = -1 # 初始化为-1,表示尚未进行过切换

    def calculate_circuit_response(self, current_time_index):
        # 检查当前时间点是否有开关切换发生
        if current_time_index > self.previous_switch_time_index:
            # 检查当前时间点的开关状态是否与前一时刻不同
            if self.switch_states[current_time_index] != self.switch_states[current_time_index - 1]:
                self.previous_switch_state = self.switch_states[current_time_index]
                next_switch_index = current_time_index + np.argmax(self.switch_states[current_time_index:] != self.switch_states[current_time_index])
                if not self.previous_switch_state:
                    # 开关断开
                    self.VoltageOverTime[current_time_index:next_switch_index] = 0
                    self.CurrentOverTime[current_time_index:next_switch_index] = 0
                else:
                    # 开关闭合
                    self.VoltageOverTime[current_time_index:next_switch_index] = V_battery * np.ones_like(self.VoltageOverTime[current_time_index:next_switch_index])
                    self.CurrentOverTime[current_time_index:next_switch_index] = V_battery / R_load * np.ones_like(self.CurrentOverTime[current_time_index:next_switch_index])
                # 更新上一次开关切换的时间索引
                self.previous_switch_time_index = next_switch_index
                
     def toggle_switch_at_time(self, switch_time_index):
        if 0 <= switch_time_index < len(self.switch_states):
            # 只改变指定时间点及其之后已定义的时间段内的开关状态
            end_of_simulation = min(switch_time_index + 1, len(self.switch_states))  # 防止越界
            self.switch_states[switch_time_index:end_of_simulation] = not self.switch_states[switch_time_index]
        else:

电路GUI

代码语言:text
复制
class CircuitSimulationGUI(tk.Tk):

    def __init__(self):
        super().__init__()

        # 设置窗口标题
        self.title("电路运行状态监控")

        # 创建主容器
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        # 初始化图表
        self.fig, self.axs = plt.subplots(2, 1, figsize=(10, 6))
        self.V_line, = self.axs[0].plot([], [], label='Circuit Voltage (V)')
        self.I_line, = self.axs[1].plot([], [], label='Circuit Current (A)', color='r')
        for ax in self.axs:
            ax.set_xlabel('Time (s)')
            ax.set_ylabel('Value')
            ax.legend()

        # 将matplotlib图表嵌入到Tkinter窗口中
        self.canvas = FigureCanvasTkAgg(self.fig, master=container)
        self.canvas.draw()
        self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)

        # 创建开关按钮
        self.manual_switch_button = tk.Button(master=self, text="Close Circuit", command=self.toggle_manual_switch)
        self.manual_switch_button.pack(pady=10)

        # 初始化动画
        self.simulator = CircuitSimulator(t)
        self.ani = None  # 将动画实例化变量初始化为None

        # 初始化状态变量
        self.current_time_index = 0

        # 启动模拟
        self.start_simulation()

    def toggle_manual_switch(self):
        """
        处理手动开关按钮点击事件,切换当前时刻的开关状态并持续影响后续状态
        """
        # 获取当前时刻的索引
        current_index = int(self.current_time_index)

        # 切换开关状态
        self.simulator.toggle_switch_at_time(current_index)
        self.simulator.calculate_circuit_response(current_index)

        # 更新按钮文本和命令
        if self.manual_switch_button["text"] == "Close Circuit":
            self.manual_switch_button["text"] = "Open Circuit"
        else:
            self.manual_switch_button["text"] = "Close Circuit"

        # 更新整个图表,传递当前时间点的索引
        self.update_plot(current_index)
        self.canvas.draw_idle()


    def start_simulation(self):
        # 使用更现代且兼容的方式检测和控制动画状态
        if self.ani is None:
            self.ani = FuncAnimation(
                fig=self.fig,
                func=self.update_plot, #传递函数而非方法 
                frames=len(t),
                interval=200,
                blit=True
            )
            self.canvas.draw_idle()
        elif getattr(self.ani, '_is_running', False):  # 更改此处
            self.ani.event_source.stop()
            self.ani.event_source.start()
        else:
            self.ani.event_source.start()

    def update_plot(self, frame):
        self.simulator.calculate_circuit_response(frame)
        time = t[frame]
        
        V_circuit = self.simulator.VoltageOverTime[:frame+1]
        I_circuit = self.simulator.CurrentOverTime[:frame+1]

        self.V_line.set_data(t[:len(V_circuit)], V_circuit)
        self.I_line.set_data(t[:len(I_circuit)], I_circuit)
        self.axs[0].set_xlim(0, t_max)
        self.axs[1].set_xlim(0, t_max)
        self.axs[0].set_ylim(0, 20)
        self.axs[1].set_ylim(0, 2)
        print("Plot updated")  # 添加这行代码来确认图表是否被更新
        print("Plot Voltage:", V_circuit[-1], "V")
        return self.V_line, self.I_line
        
# 创建并启动GUI应用
if __name__ == "__main__":
    app = CircuitSimulationGUI()
    app.mainloop()

希望实现的情况如下:

希望生成的图像
希望生成的图像

但是现在点击按钮后,无法生成这样的图像,请问一下应该有什么办法解决?

回答

和开发者交流更多问题细节吧,去 写回答
相关文章

相似问题

相关问答用户
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档