Init
This commit is contained in:
commit
f26a806b5d
1
berry_USB.py
Normal file
1
berry_USB.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
"""Aqui esta el main de la rasberri cuando funcione en modo USB"""
|
13
berry_server.py
Normal file
13
berry_server.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
from clase_cliente import Cliente
|
||||||
|
|
||||||
|
# Configuración del cliente y el servidor
|
||||||
|
SERVER_HOST = '127.0.0.1' # Asumimos localhost
|
||||||
|
SERVER_PORT = 65432 # Puerto de comunicación
|
||||||
|
|
||||||
|
# Ejecución del cliente
|
||||||
|
if __name__ == "__main__":
|
||||||
|
berry = Cliente(SERVER_HOST, SERVER_PORT)
|
||||||
|
berry.conectar()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
berry.escuchar_y_responder()
|
72
clase_cliente.py
Normal file
72
clase_cliente.py
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import socket, json
|
||||||
|
from lector import *
|
||||||
|
|
||||||
|
# Clase Cliente para la conexión y generación de ondas
|
||||||
|
class Cliente:
|
||||||
|
def __init__(self, host, port):
|
||||||
|
self.host = host
|
||||||
|
self.port = port
|
||||||
|
self.socket = None
|
||||||
|
|
||||||
|
|
||||||
|
def conectar(self):
|
||||||
|
"""Conecta al servidor de forma persistente"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
self.socket.connect((self.host, self.port))
|
||||||
|
print("Conectado al servidor")
|
||||||
|
|
||||||
|
except ConnectionError as e:
|
||||||
|
print(f"Error al conectar con el servidor: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def escuchar_y_responder(self):
|
||||||
|
"""Escucha solicitudes del servidor y responde con datos generados"""
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
# Escucha de forma continua para recibir la solicitud de medición del servidor
|
||||||
|
print("Esperando solicitud de medición del servidor...")
|
||||||
|
data = self.socket.recv(1024)
|
||||||
|
|
||||||
|
if data:
|
||||||
|
print("Solicitud recibida del servidor:", data.decode('utf-8'))
|
||||||
|
request_vars = json.loads(data.decode('utf-8'))
|
||||||
|
|
||||||
|
if request_vars == 'Apagate':
|
||||||
|
break
|
||||||
|
|
||||||
|
self.mandar_datos(request_vars)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error en la conexión con el servidor: {e}")
|
||||||
|
|
||||||
|
finally:
|
||||||
|
self.socket.close()
|
||||||
|
print("Conexión cerrada con el servidor")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def mandar_datos(self, request_vars):
|
||||||
|
"""Genera los datos de las ondas según las variables recibidas y los envía al servidor"""
|
||||||
|
|
||||||
|
fs = request_vars.get('Velocidad Muestreo', 1e3) # Frecuencia de muestreo en Hz, valor estandar 1e3
|
||||||
|
size = request_vars.get('Numero Muestras', 50) # Número de muestras, valor estandar 50
|
||||||
|
|
||||||
|
paquete = generar_paquete_ejemplo(fs, size)
|
||||||
|
|
||||||
|
# Envía los datos de vuelta al servidor
|
||||||
|
self.mandar_paquete(paquete)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def mandar_paquete(self, data):
|
||||||
|
"""Envía el JSON generado al servidor en la misma conexión"""
|
||||||
|
try:
|
||||||
|
json_data = json.dumps(data) + "\n" # Añadimos el delimitador al final del mensaje
|
||||||
|
self.socket.sendall(json_data.encode('utf-8'))
|
||||||
|
print("Datos enviados al servidor")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error al enviar datos al servidor: {e}")
|
75
clase_ploteador.py
Normal file
75
clase_ploteador.py
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
|
||||||
|
from funciones_analisis import *
|
||||||
|
from scipy.fft import fft, fftfreq
|
||||||
|
|
||||||
|
class Ploteador_VI(FigureCanvas):
|
||||||
|
def __init__(self, t, V, I, Titulo = False, parent=None):
|
||||||
|
fig, self.ax = plt.subplots(figsize=(6,4))
|
||||||
|
super().__init__(fig)
|
||||||
|
self.setParent(parent)
|
||||||
|
self.x = t
|
||||||
|
self.y1 = V
|
||||||
|
self.y2 = I
|
||||||
|
self.linea_V, self.linea_I = plot_VI(self.ax, self.x, self.y1, self.y2, Titulo=Titulo)
|
||||||
|
|
||||||
|
def actualizar_plot(self, t, V, I):
|
||||||
|
self.linea_V.set_xdata(t)
|
||||||
|
self.linea_I.set_xdata(t)
|
||||||
|
|
||||||
|
self.linea_V.set_ydata(V)
|
||||||
|
self.linea_I.set_ydata(I)
|
||||||
|
|
||||||
|
self.ax.relim()
|
||||||
|
self.ax.autoscale()
|
||||||
|
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Ploteador_Termico(FigureCanvas):
|
||||||
|
def __init__(self, t, Temperatura1, Temperatura2, parent=None):
|
||||||
|
fig, self.ax = plt.subplots(figsize=(6,4))
|
||||||
|
super().__init__(fig)
|
||||||
|
self.setParent(parent)
|
||||||
|
self.x = t
|
||||||
|
self.y1 = Temperatura1
|
||||||
|
self.y2 = Temperatura2
|
||||||
|
self.linea_1 = plot_termico(self.ax, self.x, self.y1, tags = "Cobre, ",Titulo='Termico')
|
||||||
|
self.linea_2 = plot_termico(self.ax, self.x, self.y2, tags = "Hierro", reset_plot=False)
|
||||||
|
|
||||||
|
def actualizar_plot(self, t, Temperatura1, Temperatura2):
|
||||||
|
self.linea_1.set_xdata(t)
|
||||||
|
self.linea_2.set_xdata(t)
|
||||||
|
|
||||||
|
self.linea_1.set_ydata(Temperatura1)
|
||||||
|
self.linea_2.set_ydata(Temperatura2)
|
||||||
|
|
||||||
|
self.ax.relim()
|
||||||
|
self.ax.autoscale()
|
||||||
|
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Ploteador_fft(FigureCanvas):
|
||||||
|
def __init__(self, t, onda, fs, param, parent=None):
|
||||||
|
fig, self.ax = plt.subplots(figsize=(6,4))
|
||||||
|
super().__init__(fig)
|
||||||
|
self.setParent(parent)
|
||||||
|
|
||||||
|
self.linea = plot_fft(self.ax, t, onda, fs, Titulo = f"FFT de {param}")
|
||||||
|
|
||||||
|
def actualizar_plot(self, t, onda, fs, param):
|
||||||
|
x = fftfreq(len(t), 1/fs)[:len(t)//2]
|
||||||
|
y = 1/len(x) * np.abs(fft(onda)[0:len(t)//2])
|
||||||
|
|
||||||
|
self.linea.set_ydata(y)
|
||||||
|
self.linea.set_xdata(x)
|
||||||
|
|
||||||
|
self.ax.set_title(f"FFT de {param}")
|
||||||
|
|
||||||
|
self.ax.relim()
|
||||||
|
self.ax.autoscale()
|
||||||
|
|
||||||
|
self.draw()
|
102
clase_server.py
Normal file
102
clase_server.py
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
import socket, json
|
||||||
|
|
||||||
|
|
||||||
|
# Configuración del servidor
|
||||||
|
HOST = '127.0.0.1'
|
||||||
|
PORT = 65432
|
||||||
|
|
||||||
|
class Server:
|
||||||
|
def __init__(self):
|
||||||
|
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
self.server_socket.bind((HOST, PORT))
|
||||||
|
self.server_socket.listen(1)
|
||||||
|
print("Esperando conexión del cliente...")
|
||||||
|
|
||||||
|
self.conn, addr = self.server_socket.accept()
|
||||||
|
print(f"Cliente conectado desde {addr}")
|
||||||
|
|
||||||
|
def apagar_cliente(self): # Funcion que manda orden de apagar cliente, util para desarrollo y debug
|
||||||
|
vars_request = "Apagate"
|
||||||
|
|
||||||
|
flag = True
|
||||||
|
|
||||||
|
while flag:
|
||||||
|
|
||||||
|
try:
|
||||||
|
json_data = json.dumps(vars_request) + "\n" # Añadimos el delimitador al final
|
||||||
|
self.conn.sendall(json_data.encode('utf-8'))
|
||||||
|
print("Orden de Apagado Enviada")
|
||||||
|
|
||||||
|
flag = False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error al enviar orden de apagado:", {e})
|
||||||
|
break
|
||||||
|
|
||||||
|
# Función para enviar solicitudes de medición al cliente de forma continua
|
||||||
|
def pedir_datos(self, fs, size=50): #necesita la frecuencia de medida si o si, size tiene un valor base que se puede cambiar
|
||||||
|
"""Envia solicitudes de inicio al cliente cada f_request segundos"""
|
||||||
|
|
||||||
|
flag = True
|
||||||
|
|
||||||
|
while flag:
|
||||||
|
|
||||||
|
vars_request = {
|
||||||
|
"Velocidad Muestreo": fs,
|
||||||
|
"Numero Muestras": size
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
json_data = json.dumps(vars_request) + "\n" # Añadimos el delimitador al final
|
||||||
|
self.conn.sendall(json_data.encode('utf-8'))
|
||||||
|
|
||||||
|
datos = self.escuchar_datos()
|
||||||
|
|
||||||
|
flag = False
|
||||||
|
|
||||||
|
return datos
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error al enviar solicitud de medición al cliente: {e}")
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
# Funcion que espera para escuchar datos
|
||||||
|
def escuchar_datos(self):
|
||||||
|
buffer_size = 4096 # Tamaño del búfer de recepción
|
||||||
|
data_buffer = "" # Almacena datos recibidos incompletos
|
||||||
|
|
||||||
|
flag = True
|
||||||
|
|
||||||
|
while flag: # solo acaba el bucle cuando un paquete ha sido recibido
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Recibe el siguiente fragmento de datos
|
||||||
|
packet = self.conn.recv(buffer_size).decode('utf-8')
|
||||||
|
if not packet:
|
||||||
|
break # Desconexión del cliente
|
||||||
|
|
||||||
|
# Añade el fragmento al buffer de datos
|
||||||
|
data_buffer += packet
|
||||||
|
|
||||||
|
# Procesa cada mensaje JSON completo en el buffer
|
||||||
|
while "\n" in data_buffer: # Verifica si hay un delimitador en el buffer
|
||||||
|
json_message, data_buffer = data_buffer.split("\n", 1) # Separa el mensaje completo
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Decodifica el mensaje JSON completo
|
||||||
|
received_data = json.loads(json_message)
|
||||||
|
flag = False
|
||||||
|
|
||||||
|
return received_data
|
||||||
|
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
print(f"Error al decodificar datos JSON: {e}")
|
||||||
|
|
||||||
|
except (ConnectionResetError, ConnectionAbortedError) as e:
|
||||||
|
print("La conexión con el cliente se cerró abruptamente:", e)
|
||||||
|
break
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error inesperado al recibir datos del cliente: {e}")
|
||||||
|
break
|
1
clase_usb.py
Normal file
1
clase_usb.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
"""Este script se encarga de la comunicacion entre berry y ordenador por USB"""
|
9
comprobar_modo.sh
Normal file
9
comprobar_modo.sh
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if ls /dev/ttyACM* 1>/dev/null 2>&1; then
|
||||||
|
echo "USB detectado"
|
||||||
|
python3 /ruta/a/berry_usb.py
|
||||||
|
else
|
||||||
|
echo "USB no detectado, mandando al server"
|
||||||
|
python3 /ruta/a/berry_server.py
|
||||||
|
fi
|
184
funciones_analisis.py
Normal file
184
funciones_analisis.py
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
import numpy as np
|
||||||
|
import pandas as pd
|
||||||
|
import os, shutil
|
||||||
|
from scipy.fft import fft, fftfreq
|
||||||
|
|
||||||
|
|
||||||
|
def crear_cache():
|
||||||
|
try:
|
||||||
|
os.makedirs('temp/T1')
|
||||||
|
os.makedirs('temp/T2')
|
||||||
|
os.makedirs('temp/Tiempo')
|
||||||
|
|
||||||
|
|
||||||
|
except FileExistsError:
|
||||||
|
shutil.rmtree('temp')
|
||||||
|
os.makedirs('temp/T1')
|
||||||
|
os.makedirs('temp/T2')
|
||||||
|
os.makedirs('temp/Tiempo')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def plot_VI(ax, t, V, I, analisis = False, Titulo = False): #parametro reset plot sirve para dar la opcion a superponer graficas
|
||||||
|
|
||||||
|
linea_V, = ax.plot(t, V, label="Tension") # Graficar la Tension
|
||||||
|
linea_I, = ax.plot(t, I, label="Corriente") # Graficar la Corriente
|
||||||
|
ax.set_ylabel('Amplitud')
|
||||||
|
ax.set_xlabel('Tiempo [ms]')
|
||||||
|
ax.grid(True)
|
||||||
|
|
||||||
|
if Titulo: ax.set_title(Titulo) #si hay un titulo que lo ponga
|
||||||
|
|
||||||
|
ax.legend(loc='upper right')
|
||||||
|
|
||||||
|
if analisis:
|
||||||
|
V_rms, I_rms, FP, tipo_FP = analizar_ondas(V,I)
|
||||||
|
data = [f"Tension RMS: {V_rms}[V]", f"Corriente RMS: {I_rms}[A]", f"FP: {FP} {tipo_FP}"]
|
||||||
|
|
||||||
|
for i, text in enumerate(data):
|
||||||
|
ax.text(1.05, 0.8 - i*0.1, text, fontsize=12, ha='left', va='center', transform=ax.transAxes)
|
||||||
|
|
||||||
|
return linea_V, linea_I
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def plot_termico(ax, t, T, reset_plot = True, tags = False, Titulo = False):
|
||||||
|
|
||||||
|
if reset_plot: ax.clear() # que limpie la grafica
|
||||||
|
if Titulo: ax.set_title(Titulo) #que ponga un titulo si lo hay
|
||||||
|
|
||||||
|
linea, = ax.plot(t, T, label = tags) # Graficar temperatura
|
||||||
|
ax.set_ylabel('Temperatura [ºC]')
|
||||||
|
ax.set_xlabel('Tiempo [s]')
|
||||||
|
ax.grid(True)
|
||||||
|
|
||||||
|
if tags: ax.legend(loc='upper right')
|
||||||
|
|
||||||
|
return linea
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def plot_fft(ax, t, onda, fs, threshold_picos = False, reset_plot = False, Titulo = False, tags = False):
|
||||||
|
|
||||||
|
if reset_plot: ax.clear() # que limpie la grafica
|
||||||
|
if Titulo: ax.set_title(Titulo) #que ponga un titulo si lo hay
|
||||||
|
|
||||||
|
x = fftfreq(len(t), 1/fs)[:len(t)//2]
|
||||||
|
y = 1/len(x) * np.abs(fft(onda)[0:len(t)//2])
|
||||||
|
|
||||||
|
linea, = ax.plot(x,y)
|
||||||
|
ax.set_ylabel('Amplitud')
|
||||||
|
ax.set_xlabel('Frecuencias')
|
||||||
|
|
||||||
|
if threshold_picos:
|
||||||
|
peaks = [(freq, amp) for freq, amp in zip(x, y) if amp > threshold_picos]
|
||||||
|
|
||||||
|
for freq, amp in peaks:
|
||||||
|
ax.annotate(f"{freq:.2f} Hz\n Amplitud: {amp:.2f}",
|
||||||
|
xy =(freq, amp),
|
||||||
|
xytext=(freq, amp +.05),
|
||||||
|
fontsize=10,
|
||||||
|
ha="left",
|
||||||
|
va = 'center')
|
||||||
|
|
||||||
|
ax.set_xlim(left=min(x), right=max(x) + 10)
|
||||||
|
ax.set_ylim(bottom=0, top=max(y) + 0.2)
|
||||||
|
|
||||||
|
if tags: ax.legend(loc='upper right')
|
||||||
|
|
||||||
|
return linea
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def analizar_ondas(V, I):
|
||||||
|
|
||||||
|
V_rms = round(np.sqrt(np.mean(np.array(V)**2)))
|
||||||
|
I_rms = round(np.sqrt(np.mean(np.array(I)**2)))
|
||||||
|
|
||||||
|
V = fft(V)
|
||||||
|
I = fft(I)
|
||||||
|
|
||||||
|
idx = np.argmax(np.abs(V))
|
||||||
|
|
||||||
|
fase_1 = np.angle(V[idx])
|
||||||
|
fase_2 = np.angle(I[idx])
|
||||||
|
|
||||||
|
desfase = fase_2 - fase_1
|
||||||
|
|
||||||
|
tipo_desfase = 'Inductivo'
|
||||||
|
|
||||||
|
if desfase > 0:
|
||||||
|
tipo_desfase = 'Capacitivo'
|
||||||
|
|
||||||
|
factor_potencia = round(np.cos(abs(desfase)),2)
|
||||||
|
|
||||||
|
return V_rms, I_rms, factor_potencia, tipo_desfase
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def guardar_todo(datos_temp, datos_electricos):
|
||||||
|
|
||||||
|
print('Guardando Archivos')
|
||||||
|
|
||||||
|
guardar_temperatura_npy(datos_temp['Tiempo'], datos_temp['T1'], datos_temp['T2'])
|
||||||
|
guardar_temperatura()
|
||||||
|
guardar_VI(datos_electricos['V1'], datos_electricos['I1'], datos_electricos['V2'], datos_electricos['I2'])
|
||||||
|
|
||||||
|
shutil.rmtree('temp') #borro chache
|
||||||
|
|
||||||
|
print('Archivos Guardados')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def guardar_temperatura_npy(Tiempo, T1, T2):
|
||||||
|
|
||||||
|
n = len(os.listdir('temp/Tiempo'))
|
||||||
|
|
||||||
|
np.save(f"temp/Tiempo/{n}.npy", Tiempo)
|
||||||
|
np.save(f"temp/T1/{n}.npy", T1)
|
||||||
|
np.save(f"temp/T2/{n}.npy", T2)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def guardar_temperatura(): # Mira los datos del directorio temp y guarda los datos de temperatura en un csv
|
||||||
|
|
||||||
|
try: os.makedirs('Resultados/Termicos')
|
||||||
|
except:pass
|
||||||
|
|
||||||
|
elementos = os.listdir('temp')
|
||||||
|
data = []
|
||||||
|
|
||||||
|
for i in elementos:
|
||||||
|
temp = [0]
|
||||||
|
|
||||||
|
for j in os.listdir(f"temp/{i}"):
|
||||||
|
temp = np.concatenate((temp, np.load(f"temp/{i}/{j}")))
|
||||||
|
|
||||||
|
data.append(temp[-(len(temp)-1):])
|
||||||
|
|
||||||
|
|
||||||
|
data = np.array(data)
|
||||||
|
df = pd.DataFrame(np.transpose(data), columns= elementos)
|
||||||
|
n = len(os.listdir('Resultados/Termicos')) + 1
|
||||||
|
|
||||||
|
df.to_csv(f"Resultados/Termicos/Datos_Termicos_{n}.csv", index=False)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def guardar_VI(V1, I1, V2, I2): # guarda los utimos datos electricos en un csv
|
||||||
|
|
||||||
|
try:os.makedirs('Resultados/Electricos')
|
||||||
|
except:pass
|
||||||
|
|
||||||
|
data = np.array([V1, I1, V2, I2])
|
||||||
|
|
||||||
|
columnas = ['Tension Primario [V]', 'Corriente Primario [A]', 'Tension Secundario [V]', 'Corriente Secundario [A]']
|
||||||
|
df = pd.DataFrame(np.transpose(data), columns = columnas)
|
||||||
|
|
||||||
|
n = len(os.listdir('Resultados/Termicos')) + 1
|
||||||
|
|
||||||
|
df.to_csv(f'Resultados/Electricos/Datos_Electricos_{n}.csv')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
26
lector.py
Normal file
26
lector.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import numpy as np
|
||||||
|
import random
|
||||||
|
|
||||||
|
def generar_paquete_ejemplo(fs, size):
|
||||||
|
|
||||||
|
t = np.arange(0, size/fs, 1/fs)
|
||||||
|
|
||||||
|
# Generación de las ondas
|
||||||
|
V1 = 200 * np.sin(2 * np.pi * 50 * t ) + 100 * np.sin(2 * np.pi * 100 * t) + 50 * np.sin(2 * np.pi * 150 * t) + 10*np.random.normal(0,1,size= size)
|
||||||
|
I1 = 30* np.sin(2 * np.pi * 50 * t + np.radians(60)) + 10*np.random.normal(0,1,size= size) # Desfase de 90º
|
||||||
|
V2 = 200 * np.sin(2 * np.pi * 50 * t + np.radians(random.randint(0,90))) + 10*np.random.normal(0,1,size= size) # Desfase de 30º con V1
|
||||||
|
I2 = 30* np.sin(2 * np.pi * 50 * t + np.radians(random.randint(0,90))) + 10*np.random.normal(0,1,size= size)# Desfase de 30º con I1 y 90º de V1
|
||||||
|
T1 = 3*t*random.randint(0,3)
|
||||||
|
T2 = 2*t
|
||||||
|
|
||||||
|
# Empaquetado en Diccionario
|
||||||
|
data = {
|
||||||
|
"V1": np.array(V1.tolist()),
|
||||||
|
"V2": np.array(V2.tolist()),
|
||||||
|
"I1": np.array(I1.tolist()),
|
||||||
|
"I2": np.array(I2.tolist()),
|
||||||
|
"T1": np.array(T1.tolist()),
|
||||||
|
"T2": np.array(T2.tolist())
|
||||||
|
}
|
||||||
|
|
||||||
|
return data
|
334
main_ordenador.py
Normal file
334
main_ordenador.py
Normal file
@ -0,0 +1,334 @@
|
|||||||
|
import sys
|
||||||
|
from lector import *
|
||||||
|
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QHBoxLayout, QVBoxLayout, QGridLayout
|
||||||
|
from PyQt5.QtWidgets import QLabel, QLineEdit, QPushButton
|
||||||
|
from PyQt5.QtCore import QTimer, Qt
|
||||||
|
from PyQt5.QtGui import QFont
|
||||||
|
from clase_ploteador import *
|
||||||
|
|
||||||
|
class MainWindow(QMainWindow):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.setWindowTitle("Analizador")
|
||||||
|
self.setGeometry(0, 0, 1000, 800)
|
||||||
|
self.center_window()
|
||||||
|
|
||||||
|
central_widget = QWidget()
|
||||||
|
self.setCentralWidget(central_widget)
|
||||||
|
font = QFont('Arial',14)
|
||||||
|
|
||||||
|
central_widget.setFont(font)
|
||||||
|
|
||||||
|
layout = QHBoxLayout()
|
||||||
|
layout_parametros = QVBoxLayout()
|
||||||
|
layout_graficas = QGridLayout()
|
||||||
|
|
||||||
|
self.fs = 1000
|
||||||
|
self.buff = 100
|
||||||
|
self.act = 500
|
||||||
|
self.mult_V1 = 1
|
||||||
|
self.mult_I1 = 1
|
||||||
|
self.mult_V2 = 1
|
||||||
|
self.mult_I2 = 1
|
||||||
|
self.selec_fft = 'V1'
|
||||||
|
|
||||||
|
layout_parametros = self.modulo_botones(layout_parametros)
|
||||||
|
layout_graficas = self.modulo_graficas(layout_graficas)
|
||||||
|
|
||||||
|
layout.addLayout(layout_graficas)
|
||||||
|
layout.addLayout(layout_parametros)
|
||||||
|
|
||||||
|
layout.setStretchFactor(layout_graficas, 6)
|
||||||
|
layout.setStretchFactor(layout_parametros, 1)
|
||||||
|
|
||||||
|
central_widget.setLayout(layout)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def center_window(self):
|
||||||
|
screen = QApplication.primaryScreen()
|
||||||
|
|
||||||
|
frame_geom = self.frameGeometry()
|
||||||
|
|
||||||
|
screen_center = screen.availableGeometry().center()
|
||||||
|
|
||||||
|
frame_geom.moveCenter(screen_center)
|
||||||
|
self.move(frame_geom.topLeft())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def modulo_botones(self, layout):
|
||||||
|
self.label_fs = QLabel("Fecuencia Medida: 1 kHz")
|
||||||
|
self.label_buff= QLabel("Tamaño de Paquete Datos: 100")
|
||||||
|
self.label_act= QLabel("Frecuencia Actualizacion Graficos: 2 fps")
|
||||||
|
self.label_V1= QLabel("Multiplicador Tension 1º: 1")
|
||||||
|
self.label_I1= QLabel("Multiplicador Corriente 1º: 1")
|
||||||
|
self.label_V2= QLabel("Multiplicador Tension 2º: 1")
|
||||||
|
self.label_I2= QLabel("Multiplicador Corriente 2º: 1")
|
||||||
|
|
||||||
|
self.input_fs = QLineEdit()
|
||||||
|
self.input_fs.setPlaceholderText('Frecuencia de medida')
|
||||||
|
|
||||||
|
self.input_buff = QLineEdit()
|
||||||
|
self.input_buff.setPlaceholderText('Tamaño del Paquete')
|
||||||
|
|
||||||
|
self.input_act = QLineEdit()
|
||||||
|
self.input_act.setPlaceholderText('Frecuencia de Actualizacion')
|
||||||
|
|
||||||
|
self.input_V1 = QLineEdit()
|
||||||
|
self.input_V1.setPlaceholderText('Multiplicador Tension 1º')
|
||||||
|
|
||||||
|
self.input_I1 = QLineEdit()
|
||||||
|
self.input_I1.setPlaceholderText('Multiplicador Corriente 1º')
|
||||||
|
|
||||||
|
self.input_V2 = QLineEdit()
|
||||||
|
self.input_V2.setPlaceholderText('Multiplicador Tension 2º')
|
||||||
|
|
||||||
|
self.input_I2 = QLineEdit()
|
||||||
|
self.input_I2.setPlaceholderText('Multiplicador Corriente 2º')
|
||||||
|
|
||||||
|
self.update_button = QPushButton('Actualizar Medidas')
|
||||||
|
self.update_button.clicked.connect(self.actualizar_metodo_medida)
|
||||||
|
|
||||||
|
self.update_button = QPushButton('Actualizar Medidas')
|
||||||
|
self.update_button.clicked.connect(self.actualizar_metodo_medida)
|
||||||
|
|
||||||
|
layout.addWidget(self.label_fs)
|
||||||
|
layout.addWidget(self.input_fs)
|
||||||
|
layout.addWidget(self.label_buff)
|
||||||
|
layout.addWidget(self.input_buff)
|
||||||
|
layout.addWidget(self.label_act)
|
||||||
|
layout.addWidget(self.input_act)
|
||||||
|
layout.addWidget(self.label_V1)
|
||||||
|
layout.addWidget(self.input_V1)
|
||||||
|
layout.addWidget(self.label_I1)
|
||||||
|
layout.addWidget(self.input_I1)
|
||||||
|
layout.addWidget(self.label_V2)
|
||||||
|
layout.addWidget(self.input_V2)
|
||||||
|
layout.addWidget(self.label_I2)
|
||||||
|
layout.addWidget(self.input_I2)
|
||||||
|
layout.addWidget(self.update_button)
|
||||||
|
|
||||||
|
layout.setAlignment(Qt.AlignRight)
|
||||||
|
|
||||||
|
return layout
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def actualizar_metodo_medida(self):
|
||||||
|
|
||||||
|
if self.input_fs.text():
|
||||||
|
temp = self.input_fs.text()
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.fs = float(temp) * 1000 #Guardo el Valor
|
||||||
|
self.label_fs.setText(f"Fecuencia Medida: {temp} kHz")
|
||||||
|
|
||||||
|
except: self.label_fs.setText(f"Fecuencia Medida: ¡No valido!")
|
||||||
|
|
||||||
|
if self.input_buff.text():
|
||||||
|
temp = self.input_buff.text()
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.buff = int(temp) # guardo el valor
|
||||||
|
self.label_buff.setText(f"Tamaño de Paquete Datos: {temp}")
|
||||||
|
|
||||||
|
except: self.label_buff.setText(f"Tamaño de Paquete Datos: ¡No valido!")
|
||||||
|
|
||||||
|
if self.input_act.text():
|
||||||
|
temp = self.input_act.text()
|
||||||
|
self.act = 1000/float(temp)
|
||||||
|
|
||||||
|
try:
|
||||||
|
if self.act >= self.buff/self.fs:
|
||||||
|
self.act = temp # guardo el valor
|
||||||
|
self.label_act.setText(f"Frecuencia Actualizacion Graficos: {temp} fps")
|
||||||
|
|
||||||
|
else: self.label_act.setText(f"Frecuencia Actualizacion Graficos: ¡No valido!")
|
||||||
|
|
||||||
|
except: self.label_act.setText(f"Frecuencia Actualizacion Graficos: ¡No valido!")
|
||||||
|
|
||||||
|
if self.input_V1.text():
|
||||||
|
temp = self.input_V1.text()
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.mult_V1 = float(temp) # guardo el valor
|
||||||
|
self.label_V1.setText(f"Multiplicador Tension 1º: {temp}")
|
||||||
|
|
||||||
|
except: self.label_V1.setText("Multiplicador Tension 1º: ¡No valido!")
|
||||||
|
|
||||||
|
if self.input_I1.text():
|
||||||
|
temp = self.input_I1.text()
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.mult_I1 = float(temp) # guardo el valor
|
||||||
|
self.label_I1.setText(f"Multiplicador Corriente 1º: {temp}")
|
||||||
|
|
||||||
|
except: self.label_I1.setText("Multiplicador Corriente 1º: ¡No valido!")
|
||||||
|
|
||||||
|
if self.input_V2.text():
|
||||||
|
temp = self.input_V2.text()
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.mult_V2 = float(temp) # guardo el valor
|
||||||
|
self.label_V2.setText(f"Multiplicador Tension 2º: {temp}")
|
||||||
|
|
||||||
|
except: self.label_V2.setText("Multiplicador Tension 2º: ¡No valido!")
|
||||||
|
|
||||||
|
if self.input_I2.text():
|
||||||
|
temp = self.input_I2.text()
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.mult_I2 = float(temp) # guardo el valor
|
||||||
|
self.label_I2.setText(f"Multiplicador Corriente 2º: {temp}")
|
||||||
|
|
||||||
|
except: self.label_I2.setText("Multiplicador Corriente 2º: ¡No valido!")
|
||||||
|
|
||||||
|
self.input_fs.clear()
|
||||||
|
self.input_buff.clear()
|
||||||
|
self.input_act.clear()
|
||||||
|
self.input_V1.clear()
|
||||||
|
self.input_I1.clear()
|
||||||
|
self.input_V2.clear()
|
||||||
|
self.input_I2.clear()
|
||||||
|
|
||||||
|
def modulo_seleccionador_fft(self, layout):
|
||||||
|
self.boton_fft_V1 = QPushButton("Tension 1")
|
||||||
|
self.boton_fft_I1 = QPushButton("Corriente 1")
|
||||||
|
self.boton_fft_V2 = QPushButton("Tension 2")
|
||||||
|
self.boton_fft_I2 = QPushButton("Corriente 2")
|
||||||
|
|
||||||
|
self.boton_fft_V1.clicked.connect(lambda:self.seleccion_fft('V1'))
|
||||||
|
self.boton_fft_I1.clicked.connect(lambda:self.seleccion_fft('I1'))
|
||||||
|
self.boton_fft_V2.clicked.connect(lambda:self.seleccion_fft('V2'))
|
||||||
|
self.boton_fft_I2.clicked.connect(lambda:self.seleccion_fft('I2'))
|
||||||
|
|
||||||
|
layout.addWidget(self.boton_fft_V1)
|
||||||
|
layout.addWidget(self.boton_fft_I1)
|
||||||
|
layout.addWidget(self.boton_fft_V2)
|
||||||
|
layout.addWidget(self.boton_fft_I2)
|
||||||
|
|
||||||
|
return layout
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def seleccion_fft(self, seleccion):
|
||||||
|
self.selec_fft = seleccion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def modulo_graficas(self, layout):
|
||||||
|
datos = generar_paquete_ejemplo(self.fs, self.buff)
|
||||||
|
|
||||||
|
tiempo = np.arange(0, self.buff/self.fs, 1/self.fs)
|
||||||
|
|
||||||
|
# Crear Layout Primero
|
||||||
|
layout_primario_main = QVBoxLayout()
|
||||||
|
layout_analisis_1 = QHBoxLayout()
|
||||||
|
|
||||||
|
V, I, FP, tipo = analizar_ondas(datos['V1'], datos['I1'])
|
||||||
|
|
||||||
|
self.label_V1rms = QLabel(f'V_rms = {V}V')
|
||||||
|
self.label_I1rms = QLabel(f'I_rms = {I}A')
|
||||||
|
self.label_FP1 = QLabel(f'PF = {FP} {tipo}')
|
||||||
|
|
||||||
|
layout_analisis_1.addWidget(self.label_V1rms)
|
||||||
|
layout_analisis_1.addWidget(self.label_I1rms)
|
||||||
|
layout_analisis_1.addWidget(self.label_FP1)
|
||||||
|
|
||||||
|
self.primario = Ploteador_VI(t=tiempo, V = datos['V1'], I = datos['I1'], Titulo = 'VI Primario')
|
||||||
|
|
||||||
|
layout_primario_main.addWidget(self.primario)
|
||||||
|
layout_primario_main.addLayout(layout_analisis_1)
|
||||||
|
|
||||||
|
layout_primario_main.setStretchFactor(self.primario, 8)
|
||||||
|
layout_primario_main.setStretchFactor(layout_analisis_1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
# Crear Layout Secundario
|
||||||
|
layout_secundario_main = QVBoxLayout()
|
||||||
|
layout_analisis_2 = QHBoxLayout()
|
||||||
|
|
||||||
|
V, I, FP, tipo = analizar_ondas(datos['V2'], datos['I2'])
|
||||||
|
|
||||||
|
self.label_V2rms = QLabel(f'V_rms = {V}V')
|
||||||
|
self.label_I2rms = QLabel(f'I_rms = {I}A')
|
||||||
|
self.label_FP2 = QLabel(f'PF = {FP} {tipo}')
|
||||||
|
|
||||||
|
layout_analisis_2.addWidget(self.label_V2rms)
|
||||||
|
layout_analisis_2.addWidget(self.label_I2rms)
|
||||||
|
layout_analisis_2.addWidget(self.label_FP2)
|
||||||
|
|
||||||
|
self.secundario = Ploteador_VI(t=tiempo, V = datos['V2'], I = datos['I2'], Titulo= 'VI Secundario')
|
||||||
|
|
||||||
|
layout_secundario_main.addWidget(self.secundario)
|
||||||
|
layout_secundario_main.addLayout(layout_analisis_2)
|
||||||
|
|
||||||
|
layout_secundario_main.setStretchFactor(self.secundario, 8)
|
||||||
|
layout_secundario_main.setStretchFactor(layout_analisis_2, 1)
|
||||||
|
|
||||||
|
# Crear Layout del Termico
|
||||||
|
self.termico = Ploteador_Termico(t=tiempo, Temperatura1=datos['T1'], Temperatura2=datos['T2'])
|
||||||
|
|
||||||
|
# crear layout de la fft
|
||||||
|
layout_fft_main = QVBoxLayout()
|
||||||
|
layout_fft_selector = QHBoxLayout()
|
||||||
|
|
||||||
|
layout_fft_selector = self.modulo_seleccionador_fft(layout_fft_selector)
|
||||||
|
|
||||||
|
self.fourier = Ploteador_fft(t=tiempo, onda = datos[self.selec_fft], fs = self.fs, param= self.selec_fft)
|
||||||
|
|
||||||
|
layout_fft_main.addWidget(self.fourier)
|
||||||
|
layout_fft_main.addLayout(layout_fft_selector)
|
||||||
|
|
||||||
|
# Agregar los widgets de gráficos al layout de la cuadrícula
|
||||||
|
layout.addLayout(layout_primario_main, 0, 0)
|
||||||
|
layout.addLayout(layout_secundario_main, 0, 1)
|
||||||
|
layout.addWidget(self.termico, 1, 0)
|
||||||
|
layout.addLayout(layout_fft_main, 1, 1)
|
||||||
|
|
||||||
|
layout.setRowStretch(0,1)
|
||||||
|
layout.setRowStretch(1,1)
|
||||||
|
|
||||||
|
# Configurar el temporizador para actualizar las gráficas en tiempo real
|
||||||
|
self.timer = QTimer(self)
|
||||||
|
self.timer.timeout.connect(self.update_graphs)
|
||||||
|
self.timer.start(self.act) # Actualiza plots
|
||||||
|
|
||||||
|
return layout
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def update_graphs(self):
|
||||||
|
# Generar nuevos datos en tiempo real (puedes reemplazar con datos reales)
|
||||||
|
datos = generar_paquete_ejemplo(self.fs, self.buff)
|
||||||
|
tiempo = np.arange(0, self.buff/self.fs, 1/self.fs)
|
||||||
|
|
||||||
|
# Actualizar cada gráfico
|
||||||
|
self.primario.actualizar_plot(tiempo, self.mult_V1 * datos['V1'], self.mult_I1 * datos['I1'])
|
||||||
|
self.secundario.actualizar_plot(tiempo, self.mult_V2 * datos['V2'], self.mult_I2 * datos['I2'])
|
||||||
|
self.termico.actualizar_plot(tiempo, datos['T1'], datos['T2'])
|
||||||
|
self.fourier.actualizar_plot(tiempo, datos[self.selec_fft], self.fs, self.selec_fft)
|
||||||
|
|
||||||
|
# Actualizar Los analisis
|
||||||
|
V, I, FP, tipo = analizar_ondas(datos['V1'], datos['I1'])
|
||||||
|
self.label_V1rms.setText(f"Vrms = {V} V")
|
||||||
|
self.label_I1rms.setText(f"Irms = {I} A")
|
||||||
|
self.label_FP1.setText(f"FP = {FP} {tipo}")
|
||||||
|
|
||||||
|
V, I, FP, tipo = analizar_ondas(datos['V2'], datos['I2'])
|
||||||
|
self.label_V2rms.setText(f"Vrms = {V} V")
|
||||||
|
self.label_I2rms.setText(f"Irms = {I} A")
|
||||||
|
self.label_FP2.setText(f"FP = {FP} {tipo}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
|
||||||
|
window = MainWindow()
|
||||||
|
window.show()
|
||||||
|
|
||||||
|
sys.exit(app.exec_())
|
29
main_server.py
Normal file
29
main_server.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from funciones_analisis import *
|
||||||
|
from clase_server import Server
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Ejecución del servidor
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
frecuencia_sampling = 1e3 # velocidad muestreo
|
||||||
|
tamaño_paquete = 100 #
|
||||||
|
|
||||||
|
t = np.arange(0,tamaño_paquete/frecuencia_sampling, 1/frecuencia_sampling)
|
||||||
|
|
||||||
|
servidor = Server() # activo el servidor
|
||||||
|
|
||||||
|
datos = servidor.pedir_datos(fs= frecuencia_sampling, size= tamaño_paquete)
|
||||||
|
|
||||||
|
fig, ax = plt.subplots(1,1)
|
||||||
|
|
||||||
|
plot_fft(ax, t, datos['V1'], fs=frecuencia_sampling, threshold_picos=0.1)
|
||||||
|
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
servidor.apagar_cliente() # para debug esto hay que quitar
|
||||||
|
|
5
pyvenv.cfg
Normal file
5
pyvenv.cfg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
home = C:\Users\osuescuneli\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0
|
||||||
|
include-system-site-packages = false
|
||||||
|
version = 3.11.9
|
||||||
|
executable = C:\Users\osuescuneli\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\python.exe
|
||||||
|
command = C:\Users\osuescuneli\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\python.exe -m venv C:\Users\osuescuneli\Desktop\Analizador_Trafos
|
BIN
requirements.txt
Normal file
BIN
requirements.txt
Normal file
Binary file not shown.
44
test.py
Normal file
44
test.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QPushButton, QLabel
|
||||||
|
|
||||||
|
class SelectorOpciones(QWidget):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
# Configurar la ventana
|
||||||
|
self.setWindowTitle("Seleccionador de Opciones")
|
||||||
|
self.setGeometry(100, 100, 300, 200)
|
||||||
|
|
||||||
|
# Layout principal
|
||||||
|
layout = QHBoxLayout()
|
||||||
|
|
||||||
|
# Crear botones para las opciones
|
||||||
|
self.resultado = QLabel("Selecciona una opción")
|
||||||
|
self.boton1 = QPushButton("Opción 1")
|
||||||
|
self.boton2 = QPushButton("Opción 2")
|
||||||
|
self.boton3 = QPushButton("Opción 3")
|
||||||
|
self.boton4 = QPushButton("Opción 4")
|
||||||
|
|
||||||
|
# Conectar los botones a una función
|
||||||
|
self.boton1.clicked.connect(lambda: self.mostrar_seleccion("Opción 1"))
|
||||||
|
self.boton2.clicked.connect(lambda: self.mostrar_seleccion("Opción 2"))
|
||||||
|
self.boton3.clicked.connect(lambda: self.mostrar_seleccion("Opción 3"))
|
||||||
|
self.boton4.clicked.connect(lambda: self.mostrar_seleccion("Opción 4"))
|
||||||
|
|
||||||
|
# Agregar botones al layout
|
||||||
|
layout.addWidget(self.boton1)
|
||||||
|
layout.addWidget(self.boton2)
|
||||||
|
layout.addWidget(self.boton3)
|
||||||
|
layout.addWidget(self.boton4)
|
||||||
|
layout.addWidget(self.resultado)
|
||||||
|
|
||||||
|
# Establecer layout
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
def mostrar_seleccion(self, texto):
|
||||||
|
self.resultado.setText(f"Seleccionaste: {texto}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app = QApplication([])
|
||||||
|
ventana = SelectorOpciones()
|
||||||
|
ventana.show()
|
||||||
|
app.exec_()
|
Loading…
Reference in New Issue
Block a user