Umstellung auf Customtkinter.
This commit is contained in:
217
main_v3.py
217
main_v3.py
@@ -1,5 +1,8 @@
|
||||
import tkinter as tk
|
||||
from tkinter import ttk, messagebox
|
||||
import customtkinter
|
||||
customtkinter.set_appearance_mode("light")
|
||||
customtkinter.set_default_color_theme("blue")
|
||||
import serial
|
||||
import serial.tools.list_ports
|
||||
import matplotlib.pyplot as plt
|
||||
@@ -10,8 +13,9 @@ import numpy as np
|
||||
|
||||
class ArduinoGUI:
|
||||
def __init__(self, root):
|
||||
self.my_font = customtkinter.CTkFont(family="Calibri", size=15)
|
||||
self.root = root
|
||||
self.root.title("Arduino GUI")
|
||||
self.root.title("PRG 342 GUI")
|
||||
|
||||
self.arduino = None
|
||||
self.ports = list(serial.tools.list_ports.comports())
|
||||
@@ -24,55 +28,87 @@ class ArduinoGUI:
|
||||
self.multi_setpoints_flag = False
|
||||
self.tare_flag = False
|
||||
self.demag_flag = False
|
||||
self.input_source_flag = False
|
||||
self.pid_flag = False # Flag for sending PID parameters
|
||||
|
||||
self.pid_params = {}
|
||||
self.selected_pid = None
|
||||
|
||||
self.create_widgets()
|
||||
|
||||
self.load_configurations()
|
||||
|
||||
# Start the communication thread
|
||||
self.communication_thread = threading.Thread(target=self.communication_loop)
|
||||
self.communication_thread.start()
|
||||
|
||||
|
||||
def create_widgets(self):
|
||||
self.com_label = tk.Label(self.root, text="Select COM Port:")
|
||||
self.com_label.grid(row=0, column=0)
|
||||
|
||||
self.combobox_value = tk.StringVar()
|
||||
self.combobox = ttk.Combobox(self.root, textvariable=self.combobox_value)
|
||||
self.combobox['values'] = [port.device for port in self.ports]
|
||||
self.combobox.grid(row=0, column=1)
|
||||
# Labels and ComboBox for Stellantriebstyp
|
||||
self.stellantriebstyp_label = customtkinter.CTkLabel(self.root, text="Stellantriebstyp:", font=self.my_font)
|
||||
self.stellantriebstyp_label.grid(row=0, column=0, padx=(10, 5), pady=(10, 0), sticky="w")
|
||||
|
||||
self.connect_button = tk.Button(self.root, text="Connect", command=self.connect_arduino)
|
||||
self.connect_button.grid(row=0, column=2)
|
||||
self.config_combobox_value = customtkinter.StringVar()
|
||||
self.config_combobox = customtkinter.CTkComboBox(self.root, variable=self.config_combobox_value, state="readonly", font=self.my_font)
|
||||
self.config_combobox.grid(row=0, column=1, columnspan=1, padx=(0, 10), pady=(10, 0), sticky="ew")
|
||||
#self.config_combobox.bind("<<ComboboxSelected>>", self.on_config_selected)
|
||||
|
||||
self.setpoint_label = tk.Label(self.root, text="Setpoint (Nm):")
|
||||
self.setpoint_label.grid(row=1, column=0)
|
||||
# Setzen Button für Stellantriebstyp
|
||||
self.set_pid_button = customtkinter.CTkButton(self.root, text="Setzen", command=self.set_pid_parameters, font=self.my_font)
|
||||
self.set_pid_button.grid(row=0, column=2, padx=(0, 10), pady=(10, 0), sticky="ew")
|
||||
|
||||
self.setpoint_entry = tk.Entry(self.root)
|
||||
self.setpoint_entry.grid(row=1, column=1)
|
||||
# Labels and ComboBox for COM Port
|
||||
self.com_label = customtkinter.CTkLabel(self.root, text="COM Port:", font=self.my_font)
|
||||
self.com_label.grid(row=1, column=0, padx=(10, 5), pady=(10, 0), sticky="w")
|
||||
|
||||
self.set_setpoint_button = tk.Button(self.root, text="Set", command=self.set_setpoint)
|
||||
self.set_setpoint_button.grid(row=1, column=2)
|
||||
self.combobox_value = customtkinter.StringVar()
|
||||
self.combobox = customtkinter.CTkComboBox(self.root, variable=self.combobox_value, font=self.my_font)
|
||||
self.combobox.configure(values=[port.device for port in self.ports])
|
||||
self.combobox.grid(row=1, column=1, padx=(0, 10), pady=(10, 0), sticky="ew")
|
||||
|
||||
self.multi_setpoints_label = tk.Label(self.root, text="Setpoints (angle;torque):")
|
||||
self.multi_setpoints_label.grid(row=2, column=0)
|
||||
self.connect_button = customtkinter.CTkButton(self.root, text="Verbinden", command=self.connect_arduino, font=self.my_font)
|
||||
self.connect_button.grid(row=1, column=2, padx=(0, 10), pady=(10, 0), sticky="ew")
|
||||
|
||||
self.multi_setpoints_text = tk.Text(self.root, height=5, width=20)
|
||||
self.multi_setpoints_text.grid(row=2, column=1)
|
||||
# Setpoint entry
|
||||
self.setpoint_label = customtkinter.CTkLabel(self.root, text="Sollwerteingabe in Nm:", font=self.my_font)
|
||||
self.setpoint_label.grid(row=2, column=0, padx=(10, 5), pady=(10, 0), sticky="w")
|
||||
|
||||
self.send_multi_setpoints_button = tk.Button(self.root, text="Send Setpoints", command=self.send_multi_setpoints)
|
||||
self.send_multi_setpoints_button.grid(row=2, column=2)
|
||||
self.setpoint_entry = customtkinter.CTkEntry(self.root, font=self.my_font)
|
||||
self.setpoint_entry.grid(row=2, column=1, padx=(0, 10), pady=(10, 0), sticky="ew")
|
||||
|
||||
self.tare_button = tk.Button(self.root, text="Tare Angle", command=self.tare_angle)
|
||||
self.tare_button.grid(row=3, column=2)
|
||||
self.set_setpoint_button = customtkinter.CTkButton(self.root, text="Setzen", command=self.set_setpoint, font=self.my_font)
|
||||
self.set_setpoint_button.grid(row=2, column=2, padx=(0, 10), pady=(10, 0), sticky="ew")
|
||||
|
||||
self.demag_button = tk.Button(self.root, text="Demagnetize", command=self.demagnetize)
|
||||
self.demag_button.grid(row=4, column=2)
|
||||
# Multi Setpoints Textbox and Button
|
||||
self.multi_setpoints_label = customtkinter.CTkLabel(self.root, text="Sollwerteeingabe\n(Winkel;Drehmoment):", font=self.my_font)
|
||||
self.multi_setpoints_label.grid(row=3, column=0, padx=(10, 5), pady=(10, 0), sticky="w")
|
||||
|
||||
self.exit_button = tk.Button(self.root, text="Exit", command=self.on_closing)
|
||||
self.exit_button.grid(row=5, column=2)
|
||||
self.multi_setpoints_text = customtkinter.CTkTextbox(self.root, font=self.my_font)
|
||||
self.multi_setpoints_text.grid(row=3, column=1, padx=(0, 10), pady=(10, 0), sticky="ew")
|
||||
|
||||
self.send_multi_setpoints_button = customtkinter.CTkButton(self.root, text="Sollwerte senden", command=self.send_multi_setpoints, font=self.my_font)
|
||||
self.send_multi_setpoints_button.grid(row=3, column=2, padx=(0, 10), pady=(10, 0), sticky="ew")
|
||||
|
||||
# Analog Control CheckBox
|
||||
self.checkbox_var = customtkinter.IntVar()
|
||||
self.checkbox = customtkinter.CTkCheckBox(self.root, text="Analogsteuerung", variable=self.checkbox_var, command=self.input_source_Switch, font=self.my_font)
|
||||
self.checkbox.grid(row=4, column=0, columnspan=3, padx=(10, 10), pady=(10, 0), sticky="w")
|
||||
|
||||
# Tare and Demagnetize Buttons
|
||||
self.tare_button = customtkinter.CTkButton(self.root, text="Drehwinkel tarieren", command=self.tare_angle, font=self.my_font)
|
||||
self.tare_button.grid(row=5, column=0, padx=(10, 5), pady=(10, 0), sticky="sew")
|
||||
|
||||
self.demag_button = customtkinter.CTkButton(self.root, text="Manuelle Entmagnetisierung", command=self.demagnetize, font=self.my_font)
|
||||
self.demag_button.grid(row=5, column=1, padx=(0, 5), pady=(10, 0), sticky="sew")
|
||||
|
||||
# Exit Button
|
||||
self.exit_button = customtkinter.CTkButton(self.root, text="Beenden", command=self.on_closing, font=self.my_font)
|
||||
self.exit_button.grid(row=5, column=2, padx=(0, 10), pady=(10, 0), sticky="sew")
|
||||
|
||||
# Plot
|
||||
self.figure, self.ax = plt.subplots()
|
||||
self.canvas = FigureCanvasTkAgg(self.figure, self.root)
|
||||
self.canvas.get_tk_widget().grid(row=6, column=0, columnspan=3)
|
||||
self.canvas.get_tk_widget().grid(row=0, column=3, rowspan=6, columnspan=4, padx=(10, 10), pady=(10, 0), sticky="nsew")
|
||||
|
||||
self.ax.set_title("Drehmoment-Drehwinkel-Kennlinie")
|
||||
self.ax.set_xlabel("Winkel (°)")
|
||||
@@ -80,18 +116,82 @@ class ArduinoGUI:
|
||||
self.ax.set_xlim(0, 90)
|
||||
self.ax.set_ylim(0, 50)
|
||||
|
||||
# Current readings labels
|
||||
self.current_angle = 0
|
||||
self.current_torque = 0
|
||||
self.analogInput = 0
|
||||
|
||||
self.angle_label_var = tk.StringVar()
|
||||
self.angle_label_var.set("Current Angle: 0")
|
||||
self.angle_label = tk.Label(self.root, textvariable=self.angle_label_var)
|
||||
self.angle_label.grid(row=7, column=0)
|
||||
self.angle_label_var = customtkinter.StringVar()
|
||||
self.angle_label_var.set("Drehwinkel: 0")
|
||||
self.angle_label = customtkinter.CTkLabel(self.root, textvariable=self.angle_label_var, font=self.my_font)
|
||||
self.angle_label.grid(row=6, column=3, padx=(10, 5), pady=(10, 0), sticky="sw")
|
||||
|
||||
self.torque_label_var = tk.StringVar()
|
||||
self.torque_label_var.set("Current Torque: 0")
|
||||
self.torque_label = tk.Label(self.root, textvariable=self.torque_label_var)
|
||||
self.torque_label.grid(row=7, column=1)
|
||||
self.torque_label_var = customtkinter.StringVar()
|
||||
self.torque_label_var.set("Istwert: 0")
|
||||
self.torque_label = customtkinter.CTkLabel(self.root, textvariable=self.torque_label_var, font=self.my_font)
|
||||
self.torque_label.grid(row=6, column=4, padx=(10, 5), pady=(10, 0), sticky="sw")
|
||||
|
||||
self.analogread_label_var = customtkinter.StringVar()
|
||||
self.analogread_label_var.set("Analogeingang: 0")
|
||||
self.analogread_label = customtkinter.CTkLabel(self.root, textvariable=self.analogread_label_var, font=self.my_font)
|
||||
self.analogread_label.grid(row=6, column=5, padx=(10, 5), pady=(10, 0), sticky="sw")
|
||||
|
||||
self.currentSetpoint_label_var = customtkinter.StringVar()
|
||||
self.currentSetpoint_label_var.set("Aktueller Sollwert: 0")
|
||||
self.currentSetpoint_label = customtkinter.CTkLabel(self.root, textvariable=self.currentSetpoint_label_var, font=self.my_font)
|
||||
self.currentSetpoint_label.grid(row=6, column=6, padx=(10, 5), pady=(10, 0), sticky="sw")
|
||||
|
||||
self.root.grid_columnconfigure(0, weight=0)
|
||||
self.root.grid_columnconfigure(1, weight=0)
|
||||
self.root.grid_columnconfigure(2, weight=0)
|
||||
self.root.grid_columnconfigure(3, weight=1)
|
||||
self.root.grid_columnconfigure(4, weight=1)
|
||||
self.root.grid_columnconfigure(5, weight=1)
|
||||
self.root.grid_columnconfigure(6, weight=1)
|
||||
self.root.grid_rowconfigure(0, weight=0)
|
||||
self.root.grid_rowconfigure(1, weight=0)
|
||||
self.root.grid_rowconfigure(2, weight=0)
|
||||
self.root.grid_rowconfigure(3, weight=0)
|
||||
self.root.grid_rowconfigure(4, weight=0)
|
||||
self.root.grid_rowconfigure(5, weight=1)
|
||||
self.root.grid_rowconfigure(6, weight=0)
|
||||
|
||||
def set_pid_parameters(self):
|
||||
if self.arduino:
|
||||
self.selected_pid = self.config_combobox.get()
|
||||
if self.selected_pid in self.pid_params:
|
||||
self.pid_flag = True
|
||||
else:
|
||||
messagebox.showerror("Error", "Selected PID configuration not found.")
|
||||
else:
|
||||
messagebox.showwarning("Warning", "Arduino not connected")
|
||||
|
||||
def load_configurations(self):
|
||||
try:
|
||||
with open("conf.txt", "r") as file:
|
||||
config_name = None
|
||||
for line in file:
|
||||
line = line.strip()
|
||||
if line.startswith("#") or not line:
|
||||
continue
|
||||
if "{" in line:
|
||||
config_name = line.split("{")[0].strip()
|
||||
self.pid_params[config_name] = {"Kp": 0.0, "Ki": 0.0, "Kd": 0.0}
|
||||
elif "}" in line:
|
||||
config_name = None
|
||||
else:
|
||||
if config_name:
|
||||
key, value = line.split(":")
|
||||
key = key.strip()
|
||||
value = round(float(value.strip()), 3)
|
||||
self.pid_params[config_name][key] = value
|
||||
|
||||
self.config_combobox.configure(values=list(self.pid_params.keys()))
|
||||
if self.pid_params:
|
||||
self.config_combobox.set(list(self.pid_params.keys())[0])
|
||||
self.selected_pid = list(self.pid_params.keys())[0]
|
||||
except Exception as e:
|
||||
messagebox.showerror("Error", f"Error loading configurations: {e}")
|
||||
|
||||
def connect_arduino(self):
|
||||
com_port = self.combobox_value.get()
|
||||
@@ -193,6 +293,12 @@ class ArduinoGUI:
|
||||
else:
|
||||
messagebox.showwarning("Warning", "Arduino not connected")
|
||||
|
||||
def input_source_Switch(self):
|
||||
if self.arduino:
|
||||
self.input_source_flag = True
|
||||
else:
|
||||
messagebox.showwarning("Warning", "Arduino not connected")
|
||||
|
||||
def communication_loop(self):
|
||||
while self.running:
|
||||
if self.arduino:
|
||||
@@ -213,6 +319,13 @@ class ArduinoGUI:
|
||||
self.arduino.write(b'e\n')
|
||||
self.demag_flag = False
|
||||
time.sleep(0.1)
|
||||
if self.input_source_flag:
|
||||
self.arduino.write(b'S\n')
|
||||
self.input_source_flag = False
|
||||
time.sleep(0.1)
|
||||
if self.pid_flag:
|
||||
self.send_pid_parameters()
|
||||
self.pid_flag = False
|
||||
|
||||
self.arduino.write(b'a\n')
|
||||
timeout_ctr = time.time()
|
||||
@@ -223,10 +336,13 @@ class ArduinoGUI:
|
||||
data = self.arduino.readline().decode(errors='ignore').strip().split(";")
|
||||
self.current_angle = float(data[0]) / 1000
|
||||
self.current_torque = float(data[1]) / 1000
|
||||
print(data[2])
|
||||
self.analogInput = float(data[2]) / 1000
|
||||
self.currentSetpoint = float(data[3]) / 1000
|
||||
|
||||
self.angle_label_var.set(f"Current Angle: {self.current_angle}")
|
||||
self.torque_label_var.set(f"Current Torque: {self.current_torque}")
|
||||
self.angle_label_var.set(f"Drehwinkel: {self.current_angle:.1f} °")
|
||||
self.torque_label_var.set(f"Istwert: {self.current_torque:.1f} Nm")
|
||||
self.analogread_label_var.set(f"Analogeingang: {self.analogInput:.1f} V")
|
||||
self.currentSetpoint_label_var.set(f"Aktueller Sollwert: {self.currentSetpoint:.1f} Nm")
|
||||
|
||||
if self.current_point is not None:
|
||||
self.current_point.remove()
|
||||
@@ -234,9 +350,24 @@ class ArduinoGUI:
|
||||
self.canvas.draw()
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
|
||||
time.sleep(0.1)
|
||||
|
||||
def send_pid_parameters(self):
|
||||
if self.selected_pid in self.pid_params:
|
||||
pid_values = self.pid_params[self.selected_pid]
|
||||
kp = f"{pid_values['Kp']:.3f}"
|
||||
ki = f"{pid_values['Ki']:.3f}"
|
||||
kd = f"{pid_values['Kd']:.3f}"
|
||||
self.arduino.write(f"p{kp}\n".encode())
|
||||
time.sleep(0.1)
|
||||
self.arduino.write(f"i{ki}\n".encode())
|
||||
time.sleep(0.1)
|
||||
self.arduino.write(f"d{kd}\n".encode())
|
||||
messagebox.showinfo("Info", f"PID parameters sent: Kp={kp}, Ki={ki}, Kd={kd}")
|
||||
else:
|
||||
messagebox.showerror("Error", "Selected PID configuration not found.")
|
||||
|
||||
def on_closing(self):
|
||||
self.running = False
|
||||
if self.arduino:
|
||||
@@ -245,7 +376,7 @@ class ArduinoGUI:
|
||||
self.root.destroy()
|
||||
|
||||
if __name__ == "__main__":
|
||||
root = tk.Tk()
|
||||
root = customtkinter.CTk()
|
||||
app = ArduinoGUI(root)
|
||||
root.protocol("WM_DELETE_WINDOW", app.on_closing)
|
||||
root.mainloop()
|
||||
root.mainloop()
|
||||
|
||||
Reference in New Issue
Block a user