Files
apsbps-tools/hmi/hmi.py
Martino Ferrari 607e1b4dd1 Initial commit
2026-02-24 13:15:57 +01:00

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()