| @ -1,157 +1,168 @@ | |||
| # -*- coding: utf-8 -*- | |||
| """ | |||
| Created on Wed Feb 15 10:44:49 2023 | |||
| @author: david | |||
| """ | |||
| from threading import Thread | |||
| import collections #Colección de datos para graficarlos | |||
| import matplotlib.pyplot as plt #Gráficación de datos | |||
| import matplotlib.animation as animation #Animar la gráfica | |||
| import time | |||
| import serial | |||
| #import numpy as np | |||
| from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg #Crear una figura para insertar en tkinter | |||
| import tkinter as tk #Para la interfaz | |||
| #from matplotlib.lines import Line2D | |||
| def leer_datos(): | |||
| time.sleep(1.0) | |||
| arduino.reset_input_buffer() | |||
| print("leyendo") | |||
| while(isRun): | |||
| global isReceiving | |||
| global dato1 | |||
| print("RECIBIENDO...") | |||
| dato1 = float(arduino.readline().decode("utf-8").strip()) | |||
| print(dato1) | |||
| var.set("TEMPERATURA: " + str(dato1) + " °C") | |||
| isReceiving = True | |||
| def iniciarGrafica(self, muestras,lines): | |||
| global dato1 | |||
| data.append(dato1) | |||
| lines.set_data(range(muestras), data) | |||
| global isRun | |||
| isReceiving = False | |||
| isRun = True | |||
| dato1 = 0.0 | |||
| serialPort = 'COM3' | |||
| baudRate = 9600 | |||
| def conectar_serial(): | |||
| global arduino | |||
| try: | |||
| arduino = serial.Serial(serialPort, baudRate) | |||
| arduino.timeout = 0.5 | |||
| time.sleep(0.5) | |||
| print("CONECTADO") | |||
| btnStart.config(state = "normal") | |||
| btnConectar.config(state = "disabled") | |||
| except: | |||
| print("Error de conexión") | |||
| def iniciar_hilo(): | |||
| global thread | |||
| thread = Thread(target=leer_datos) | |||
| thread.start() | |||
| btnStart.config(state = "disabled") | |||
| btnPause.config(state = "normal") | |||
| def guardarGrafica(): | |||
| plt.savefig('miFigura.png') | |||
| def control1(): | |||
| window2 = tk.Toplevel() | |||
| window2.resizable(width = 0, height = 0) | |||
| window2.title('Control Manual') | |||
| window2.geometry('500x300') | |||
| def control2(): | |||
| window3 = tk.Toplevel() | |||
| window3.resizable(width = 0, height = 0) | |||
| window3.title('Control ON/OFF') | |||
| window3.geometry('500x300') | |||
| def pausar(): | |||
| anim.event_source.stop() | |||
| btnResume.config(state = "normal") | |||
| btnPause.config(state = "disabled") | |||
| def reanudar(): | |||
| anim.event_source.start() | |||
| btnResume.config(state = "disabled") | |||
| btnPause.config(state = "normal") | |||
| def desconectar_serial(): | |||
| global isRun | |||
| anim.event_source.stop() | |||
| isRun = False | |||
| arduino.close() | |||
| btnPause.config(state = "disabled") | |||
| btnResume.config(state = "disabled") | |||
| muestras = 100 | |||
| data = collections.deque([0] * muestras, maxlen = muestras) | |||
| tiempoMuestreo = 100 | |||
| fig = plt.figure(facecolor = '0.94') | |||
| ax = plt.axes(xlim=(0,100), ylim=(-40, 150)) | |||
| plt.title("Sensor 1 - Arduino") | |||
| ax.set_xlabel("Muestras") | |||
| ax.set_ylabel("Voltaje") | |||
| lines = ax.plot([], [])[0] | |||
| root= tk.Tk() | |||
| root.title("Sistema de calentamiento") | |||
| var = tk.StringVar() | |||
| frame = tk.Frame(root, bd=2) | |||
| frame.grid(column=0, row=3, columnspan=2, sticky="nsew") | |||
| frame1 = tk.Frame(root) | |||
| frame1.grid(column=0, row=1, columnspan=2, sticky="EW") | |||
| frame2 = tk.Frame(root) | |||
| frame2.grid(column=0, row=2, columnspan=2, sticky="EW") | |||
| frame0 = tk.Frame(root) | |||
| frame0.grid(column=0, row=0, columnspan=2, sticky="EW") | |||
| root.columnconfigure(0, weight=1) | |||
| root.columnconfigure(1, weight=1) | |||
| #self.master.rowconfigure(0, weigh=1) | |||
| #self.master.rowconfigure(1, weigh=1) | |||
| #self.master.rowconfigure(2, weigh=1) | |||
| root.rowconfigure(3, weigh=5) | |||
| canvas = FigureCanvasTkAgg(fig, master=frame) | |||
| canvas.get_tk_widget().pack(padx=0, pady=0, expand=True, fill='both') | |||
| btnManual = tk.Button(frame2, text = "Manual", command = control1) | |||
| btnManual.grid(row=0, column=0, pady=2, padx=10) | |||
| btnOnOff = tk.Button(frame2, text = "ON/OFF", command = control2) | |||
| btnOnOff.grid(row=0, column=1, pady=2, padx=10) | |||
| btnConectar = tk.Button(frame1, text = "Connect", command = conectar_serial, bg="#00F1FC") | |||
| btnConectar.grid(row=0, column=0, pady=2, padx=10) | |||
| btnStart = tk.Button(frame1, text = "Start", command = iniciar_hilo, bg="#008C17", state="disabled") | |||
| btnStart.grid(row=0, column=1, pady=2, padx=10) | |||
| btnPause = tk.Button(frame1, text = "Pause", command = pausar, bg="#E2E200", state="disabled") | |||
| btnPause.grid(row=0, column=2, pady=2, padx=10) | |||
| btnResume = tk.Button(frame1, text = "Resume", command = reanudar, bg="#00F428", state="disabled") | |||
| btnResume.grid(row=0, column=3, pady=2, padx=10) | |||
| btnDesconectar = tk.Button(frame2, text='Disconnect', command = desconectar_serial, bg="#FE5E5E") | |||
| btnDesconectar.grid(row=0, column=3, pady=2, padx=10) | |||
| labelData = tk.Label(frame2, textvariable=var) | |||
| labelData.grid(row=0, column=4, pady=2, padx=500) | |||
| barraMenu = tk.Menu(frame0) | |||
| barra1 = tk.Menu(barraMenu) | |||
| barra1.add_command(label="Guardar gráfica", command=guardarGrafica) | |||
| barraMenu.add_cascade(label="Archivo", menu=barra1) | |||
| root.config(menu=barraMenu) | |||
| anim = animation.FuncAnimation(fig, iniciarGrafica, fargs=(muestras, lines), interval = tiempoMuestreo) | |||
| root.geometry('1000x600') | |||
| root.mainloop() | |||
| # -*- coding: utf-8 -*- | |||
| """ | |||
| Created on Wed Feb 15 10:44:49 2023 | |||
| @author: david | |||
| """ | |||
| from threading import Thread #Funciones para hilos | |||
| import collections #Colección de datos para graficarlos | |||
| import matplotlib.pyplot as plt #Gráficación de datos | |||
| import matplotlib.animation as animation #Animar la gráfica | |||
| import time #Delays | |||
| import serial #comunicación con el monitor serial de Arduino | |||
| from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg #Crear una figura para insertar en tkinter | |||
| import tkinter as tk #Para la interfaz | |||
| #Variables a utilizar | |||
| global isRun #Valor booleano de programa corriendo | |||
| isReceiving = False #Valor booleano de recibiendo datos | |||
| isRun = True | |||
| dato1 = 0.0 #Variable del dato a leer desde Arduino | |||
| serialPort = 'COM3' #Puerto al que está conectado el Arduino | |||
| baudRate = 9600 #Baudios configurados en Arduino | |||
| #Función de lectura de datos en Arduino | |||
| def leer_datos(): | |||
| time.sleep(1.0) | |||
| arduino.reset_input_buffer() #limpia el buffer de datos | |||
| print("leyendo") | |||
| while(isRun): | |||
| global isReceiving #valor booleano de recibiendo datos | |||
| global dato1 #dato a recibir desde Arduino | |||
| print("RECIBIENDO...") | |||
| dato1 = float(arduino.readline().decode("utf-8").strip()) #Lectura del dato y conversión a float | |||
| print(dato1) | |||
| var.set("TEMPERATURA: " + str(dato1) + " °C") #impresión del dato numérico en la interfaz | |||
| isReceiving = True #Confirmación de que se ha recibido el dato | |||
| #Función para iniciar la gráfica | |||
| def iniciarGrafica(self, muestras,lines): | |||
| global dato1 | |||
| data.append(dato1) #Agrega el dato a la colección | |||
| lines.set_data(range(muestras), data) #Se grafica en la línea la colección de datos | |||
| #Establecer conexión con Arduino | |||
| def conectar_serial(): | |||
| global arduino #Variable que va aguardar la conexión | |||
| try: | |||
| arduino = serial.Serial(serialPort, baudRate) #Asignación del objeto a la variable | |||
| arduino.timeout = 0.5 #Tiempo a esperar para que haya datos disponibles en el puerto serie | |||
| time.sleep(0.5) #Tiempo muerto para permitir la conexión | |||
| print("CONECTADO") | |||
| btnStart.config(state = "normal") | |||
| btnConectar.config(state = "disabled") | |||
| except: | |||
| print("Error de conexión") | |||
| #Hilo para la lectura de datos constante | |||
| def iniciar_hilo(): | |||
| global thread #Variable donde guardar el hilo | |||
| thread = Thread(target=leer_datos) #Creación del hilo con la función para leer los datos | |||
| thread.start() #Inicio de la lectura | |||
| btnStart.config(state = "disabled") | |||
| btnPause.config(state = "normal") | |||
| #Pestaña para guardar la gráfica | |||
| def guardarGrafica(): | |||
| plt.savefig('miFigura.png') | |||
| #Ventana de control Manual (ON/OFF controlado por el usuario) | |||
| def control1(): | |||
| window2 = tk.Toplevel() | |||
| window2.resizable(width = 0, height = 0) | |||
| window2.title('Control Manual') | |||
| window2.geometry('500x300') | |||
| #Ventana para control según una temperatura dada (Automático) | |||
| def control2(): | |||
| window3 = tk.Toplevel() | |||
| window3.resizable(width = 0, height = 0) | |||
| window3.title('Control ON/OFF') | |||
| window3.geometry('500x300') | |||
| #Función para pausar la gráfica | |||
| def pausar(): | |||
| anim.event_source.stop() | |||
| btnResume.config(state = "normal") | |||
| btnPause.config(state = "disabled") | |||
| #Función para continuar graficando | |||
| def reanudar(): | |||
| anim.event_source.start() | |||
| btnResume.config(state = "disabled") | |||
| btnPause.config(state = "normal") | |||
| #Función para finaliar la conexión con Arduino | |||
| def desconectar_serial(): | |||
| global isRun | |||
| anim.event_source.stop() | |||
| isRun = False | |||
| arduino.close() | |||
| btnPause.config(state = "disabled") | |||
| btnResume.config(state = "disabled") | |||
| #Variables a graficar | |||
| muestras = 100 #Número de datos a visualizar | |||
| data = collections.deque([0] * muestras, maxlen = muestras) #Rango de datos | |||
| tiempoMuestreo = 100 | |||
| fig = plt.figure(facecolor = '0.94') #creación de la gráfica (figura) | |||
| ax = plt.axes(xlim=(0,100), ylim=(-40, 150)) #Rango de ejes | |||
| plt.title("Sensor 1 - Arduino") | |||
| ax.set_xlabel("Muestras") | |||
| ax.set_ylabel("Voltaje") | |||
| lines = ax.plot([], [])[0] #Creación de la línea a graficar | |||
| root= tk.Tk() | |||
| root.title("Sistema de calentamiento") | |||
| var = tk.StringVar() | |||
| frame = tk.Frame(root, bd=2) | |||
| frame.grid(column=0, row=3, columnspan=2, sticky="nsew") | |||
| frame1 = tk.Frame(root) | |||
| frame1.grid(column=0, row=1, columnspan=2, sticky="EW") | |||
| frame2 = tk.Frame(root) | |||
| frame2.grid(column=0, row=2, columnspan=2, sticky="EW") | |||
| frame0 = tk.Frame(root) | |||
| frame0.grid(column=0, row=0, columnspan=2, sticky="EW") | |||
| root.columnconfigure(0, weight=1) | |||
| root.columnconfigure(1, weight=1) | |||
| #self.master.rowconfigure(0, weigh=1) | |||
| #self.master.rowconfigure(1, weigh=1) | |||
| #self.master.rowconfigure(2, weigh=1) | |||
| root.rowconfigure(3, weigh=5) | |||
| canvas = FigureCanvasTkAgg(fig, master=frame) | |||
| canvas.get_tk_widget().pack(padx=0, pady=0, expand=True, fill='both') | |||
| btnManual = tk.Button(frame2, text = "Manual", command = control1) | |||
| btnManual.grid(row=0, column=0, pady=2, padx=10) | |||
| btnOnOff = tk.Button(frame2, text = "ON/OFF", command = control2) | |||
| btnOnOff.grid(row=0, column=1, pady=2, padx=10) | |||
| btnConectar = tk.Button(frame1, text = "Connect", command = conectar_serial, bg="#00F1FC") | |||
| btnConectar.grid(row=0, column=0, pady=2, padx=10) | |||
| btnStart = tk.Button(frame1, text = "Start", command = iniciar_hilo, bg="#008C17", state="disabled") | |||
| btnStart.grid(row=0, column=1, pady=2, padx=10) | |||
| btnPause = tk.Button(frame1, text = "Pause", command = pausar, bg="#E2E200", state="disabled") | |||
| btnPause.grid(row=0, column=2, pady=2, padx=10) | |||
| btnResume = tk.Button(frame1, text = "Resume", command = reanudar, bg="#00F428", state="disabled") | |||
| btnResume.grid(row=0, column=3, pady=2, padx=10) | |||
| btnDesconectar = tk.Button(frame2, text='Disconnect', command = desconectar_serial, bg="#FE5E5E") | |||
| btnDesconectar.grid(row=0, column=3, pady=2, padx=10) | |||
| labelData = tk.Label(frame2, textvariable=var) | |||
| labelData.grid(row=0, column=4, pady=2, padx=500) | |||
| barraMenu = tk.Menu(frame0) | |||
| barra1 = tk.Menu(barraMenu) | |||
| barra1.add_command(label="Guardar gráfica", command=guardarGrafica) | |||
| barraMenu.add_cascade(label="Archivo", menu=barra1) | |||
| root.config(menu=barraMenu) | |||
| #Animación de la gráfica (figura, función que grafica la línea, argumentos para graficar, rango de la figura) | |||
| anim = animation.FuncAnimation(fig, iniciarGrafica, fargs=(muestras, lines), interval = tiempoMuestreo) | |||
| root.geometry('1000x600') | |||
| root.mainloop() | |||