156 lines
5.4 KiB
Python
156 lines
5.4 KiB
Python
import tkinter as tk
|
|
from tkinter import ttk
|
|
import math
|
|
|
|
import matplotlib
|
|
matplotlib.use("TkAgg")
|
|
import matplotlib.pyplot as plt
|
|
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
|
|
|
|
import numpy as np
|
|
|
|
class TabElectrical:
|
|
def __init__(self, notebook, tab_simulator, tab_coil):
|
|
"""
|
|
Pestaña para estimar la potencia y corriente necesarias
|
|
para suministrar la energía 'E_mec' en diferentes tiempos,
|
|
con un voltaje fijo V.
|
|
- 'tab_simulator': donde se calcula la energía mecánica requerida.
|
|
- 'tab_coil': por si quieres leer datos de la bobina (en este ejemplo,
|
|
no lo usamos ya, pero lo mantenemos para coherencia).
|
|
"""
|
|
self.notebook = notebook
|
|
self.tab_sim = tab_simulator
|
|
self.tab_coil = tab_coil
|
|
|
|
# Creamos el frame principal de la pestaña
|
|
self.frame = tk.Frame(notebook)
|
|
self.frame.pack(fill="both", expand=True)
|
|
# Nota: si en main.py ya se hace 'notebook.add(self.frame, text="Eléctrico")',
|
|
# no repitas esa línea aquí.
|
|
|
|
# Layout principal (izquierda: controles, derecha: gráfica)
|
|
frame_left = tk.Frame(self.frame)
|
|
frame_left.pack(side="left", fill="y", padx=5, pady=5)
|
|
|
|
frame_right = tk.Frame(self.frame, bd=2, relief="groove")
|
|
frame_right.pack(side="right", fill="both", expand=True, padx=5, pady=5)
|
|
|
|
#
|
|
# Sección Izquierda
|
|
#
|
|
tk.Label(frame_left, text="Simulación Eléctrica (Potencia & Corriente)").pack(anchor="w", pady=3)
|
|
|
|
btn_import = tk.Button(
|
|
frame_left, text="Importar Config",
|
|
command=self.import_config
|
|
)
|
|
btn_import.pack(pady=5, anchor="w")
|
|
|
|
# Variables
|
|
self.var_emech = tk.DoubleVar(value=0.0) # Energía mecánica importada
|
|
self.var_V = tk.DoubleVar(value=12.0) # Voltaje (valor por defecto 12 V)
|
|
self.var_tmax = tk.DoubleVar(value=2.0) # Tiempo máximo de estudio (s)
|
|
|
|
# Muestra la energía mecánica importada
|
|
tk.Label(frame_left, text="E_mec (J):").pack(anchor="w")
|
|
self.lbl_emech = tk.Label(frame_left, text="N/A")
|
|
self.lbl_emech.pack(anchor="w", pady=2)
|
|
|
|
# Frame para pedir V y T_max
|
|
param_frame = tk.Frame(frame_left, bd=1, relief="sunken")
|
|
param_frame.pack(fill="x", pady=10)
|
|
|
|
tk.Label(param_frame, text="Voltaje (V):").grid(row=0, column=0, sticky="w", padx=4, pady=2)
|
|
self.entry_V = tk.Entry(param_frame, width=8, textvariable=self.var_V)
|
|
self.entry_V.grid(row=0, column=1, padx=5, pady=2)
|
|
|
|
tk.Label(param_frame, text="T_max (s):").grid(row=1, column=0, sticky="w", padx=4, pady=2)
|
|
self.entry_Tmax = tk.Entry(param_frame, width=8, textvariable=self.var_tmax)
|
|
self.entry_Tmax.grid(row=1, column=1, padx=5, pady=2)
|
|
|
|
# Botón de simulación
|
|
btn_simular = tk.Button(param_frame, text="Simular", command=self.simular)
|
|
btn_simular.grid(row=2, column=0, columnspan=2, pady=5)
|
|
|
|
#
|
|
# Sección Derecha: gráficas
|
|
#
|
|
self.fig = plt.Figure(figsize=(5, 3), dpi=100)
|
|
|
|
# Subplot 1: Potencia vs tiempo
|
|
self.ax_p = self.fig.add_subplot(211)
|
|
# Subplot 2: Corriente vs tiempo
|
|
self.ax_i = self.fig.add_subplot(212)
|
|
|
|
self.canvas = FigureCanvasTkAgg(self.fig, master=frame_right)
|
|
self.canvas_widget = self.canvas.get_tk_widget()
|
|
self.canvas_widget.pack(fill="both", expand=True)
|
|
|
|
def import_config(self):
|
|
"""
|
|
Importa la energía mecánica desde la pestaña de simulación.
|
|
Ajusta la variable self.var_emech.
|
|
"""
|
|
# Supongamos que TabSimulator tiene un método 'get_energy_required()'
|
|
# que devuelve la energía calculada.
|
|
try:
|
|
E_mech_val = self.tab_sim.get_energy_required()
|
|
except:
|
|
E_mech_val = 0.0
|
|
|
|
self.var_emech.set(E_mech_val)
|
|
self.lbl_emech.config(text=f"{E_mech_val:.3f} J")
|
|
|
|
def simular(self):
|
|
"""
|
|
Barrido de tiempos (0..T_max):
|
|
P(t) = E / t
|
|
I(t) = P(t) / V
|
|
Se grafican P(t) e I(t).
|
|
"""
|
|
E = self.var_emech.get() # Joules
|
|
V = self.var_V.get() # Voltios
|
|
T_max = self.var_tmax.get() # s
|
|
|
|
# Evitar tiempos <= 0
|
|
if T_max <= 0.0:
|
|
T_max = 2.0
|
|
self.var_tmax.set(T_max)
|
|
|
|
# Creamos un vector de tiempos discretos, evitando t=0
|
|
# por ejemplo de 0.01 a T_max en 50 pasos
|
|
t_vals = np.linspace(0.01, T_max, 50)
|
|
p_vals = [] # Potencia en cada t
|
|
i_vals = [] # Corriente en cada t
|
|
|
|
for t in t_vals:
|
|
# P(t) = E / t
|
|
P_t = 0.0
|
|
I_t = 0.0
|
|
if t > 0:
|
|
P_t = E / t
|
|
# I(t) = P(t)/V = E/(V*t)
|
|
if V > 1e-12:
|
|
I_t = P_t / V
|
|
|
|
p_vals.append(P_t)
|
|
i_vals.append(I_t)
|
|
|
|
# Graficamos
|
|
self.ax_p.clear()
|
|
self.ax_p.plot(t_vals, p_vals, label="P(t) = E / t", color="blue")
|
|
self.ax_p.set_xlabel("Tiempo (s)")
|
|
self.ax_p.set_ylabel("Potencia (W)")
|
|
self.ax_p.grid(True)
|
|
self.ax_p.legend()
|
|
|
|
self.ax_i.clear()
|
|
self.ax_i.plot(t_vals, i_vals, label="I(t) = P(t)/V", color="red")
|
|
self.ax_i.set_xlabel("Tiempo (s)")
|
|
self.ax_i.set_ylabel("Corriente (A)")
|
|
self.ax_i.grid(True)
|
|
self.ax_i.legend()
|
|
|
|
self.canvas.draw()
|