Initial commit
This commit is contained in:
123
hmi/hmi.py
Normal file
123
hmi/hmi.py
Normal file
@@ -0,0 +1,123 @@
|
||||
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()
|
||||
Reference in New Issue
Block a user