124 lines
4.0 KiB
Python
124 lines
4.0 KiB
Python
import threading
|
|
import time
|
|
import tkinter as tk
|
|
from tkinter import messagebox, ttk
|
|
|
|
import serial
|
|
import serial.tools.list_ports
|
|
|
|
|
|
class WaveformGenHMI:
|
|
def __init__(self, root):
|
|
self.root = root
|
|
self.root.title("ESP32-P4 Waveform Generator")
|
|
self.root.geometry("400x300")
|
|
|
|
self.ser = None
|
|
|
|
# UI Elements
|
|
ttk.Label(root, text="Serial Port:").grid(
|
|
row=0, column=0, padx=5, pady=5, sticky="w"
|
|
)
|
|
self.port_var = tk.StringVar()
|
|
self.port_combo = ttk.Combobox(root, textvariable=self.port_var)
|
|
self.port_combo.grid(row=0, column=1, padx=5, pady=5)
|
|
self.refresh_ports()
|
|
|
|
ttk.Button(root, text="Connect", command=self.toggle_connect).grid(
|
|
row=0, column=2, padx=5, pady=5
|
|
)
|
|
|
|
ttk.Label(root, text="GPIO Pin:").grid(
|
|
row=1, column=0, padx=5, pady=5, sticky="w"
|
|
)
|
|
self.pin_entry = ttk.Entry(root)
|
|
self.pin_entry.insert(0, "21")
|
|
self.pin_entry.grid(row=1, column=1, padx=5, pady=5)
|
|
|
|
ttk.Label(root, text="Frequency (Hz):").grid(
|
|
row=2, column=0, padx=5, pady=5, sticky="w"
|
|
)
|
|
self.freq_slider = tk.Scale(
|
|
root, from_=0, to=5000, orient=tk.HORIZONTAL, length=200
|
|
)
|
|
self.freq_slider.grid(row=2, column=1, columnspan=2, padx=5, pady=5)
|
|
|
|
self.freq_entry = ttk.Entry(root, width=10)
|
|
self.freq_entry.insert(0, "1000")
|
|
self.freq_entry.grid(row=3, column=1, padx=5, pady=5, sticky="w")
|
|
ttk.Button(root, text="Apply", command=self.send_config).grid(
|
|
row=3, column=2, padx=5, pady=5
|
|
)
|
|
|
|
self.status_label = ttk.Label(root, text="Disconnected", foreground="red")
|
|
self.status_label.grid(row=4, column=0, columnspan=3, pady=10)
|
|
|
|
# Sync slider and entry
|
|
self.freq_slider.bind("<Motion>", lambda e: self.sync_entry_to_slider())
|
|
self.freq_entry.bind("<Return>", lambda e: self.sync_slider_to_entry())
|
|
|
|
def refresh_ports(self):
|
|
ports = [p.device for p in serial.tools.list_ports.comports()]
|
|
self.port_combo["values"] = ports
|
|
if ports:
|
|
self.port_combo.current(0)
|
|
|
|
def sync_entry_to_slider(self):
|
|
self.freq_entry.delete(0, tk.END)
|
|
self.freq_entry.insert(0, str(self.freq_slider.get()))
|
|
|
|
def sync_slider_to_entry(self):
|
|
try:
|
|
val = int(self.freq_entry.get())
|
|
if 0 <= val <= 5000:
|
|
self.freq_slider.set(val)
|
|
except ValueError:
|
|
pass
|
|
|
|
def toggle_connect(self):
|
|
if self.ser and self.ser.is_open:
|
|
self.ser.close()
|
|
self.status_label.config(text="Disconnected", foreground="red")
|
|
else:
|
|
try:
|
|
self.ser = serial.Serial(self.port_var.get(), 115200, timeout=1)
|
|
self.status_label.config(
|
|
text=f"Connected to {self.port_var.get()}", foreground="green"
|
|
)
|
|
except Exception as e:
|
|
messagebox.showerror("Error", f"Failed to connect: {e}")
|
|
|
|
def send_config(self):
|
|
if not self.ser or not self.ser.is_open:
|
|
messagebox.showwarning("Warning", "Not connected to serial port")
|
|
return
|
|
|
|
try:
|
|
pin = int(self.pin_entry.get())
|
|
freq = int(self.freq_entry.get())
|
|
|
|
if not (0 <= pin <= 54):
|
|
raise ValueError("Pin must be 0-54")
|
|
if not (0 <= freq <= 5000):
|
|
raise ValueError("Frequency must be 0-5000")
|
|
|
|
cmd = f"SET {pin} {freq}"
|
|
|
|
self.ser.write(cmd.encode())
|
|
|
|
# Optional: read response
|
|
line = self.ser.readline().decode().strip()
|
|
if line:
|
|
print(f"ESP32: {line}")
|
|
|
|
except ValueError as e:
|
|
messagebox.showerror("Error", str(e))
|
|
except Exception as e:
|
|
messagebox.showerror("Error", f"Serial communication error: {e}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
root = tk.Tk()
|
|
app = WaveformGenHMI(root)
|
|
root.mainloop()
|