Update auf v3
This commit is contained in:
0
concept.txt
Normal file
0
concept.txt
Normal file
121
main_v2.py
Normal file
121
main_v2.py
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
import tkinter as tk
|
||||||
|
from tkinter import messagebox
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
|
||||||
|
from matplotlib.figure import Figure
|
||||||
|
import serial
|
||||||
|
|
||||||
|
# Globale Variablen
|
||||||
|
Kp = 0.0
|
||||||
|
Ki = 0.0
|
||||||
|
Kd = 0.0
|
||||||
|
arduino = None
|
||||||
|
root = None
|
||||||
|
torque_mode = None
|
||||||
|
|
||||||
|
def open_serial_connection():
|
||||||
|
global arduino
|
||||||
|
try:
|
||||||
|
arduino = serial.Serial(port="COM4", baudrate=115200, timeout=1)
|
||||||
|
print("Verbindung zu Arduino hergestellt.")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Fehler beim Öffnen der seriellen Verbindung: {e}")
|
||||||
|
|
||||||
|
def close_application():
|
||||||
|
if messagebox.askokcancel("Schließen", "Wollen Sie die Anwendung wirklich schließen?"):
|
||||||
|
if arduino and arduino.is_open:
|
||||||
|
arduino.close()
|
||||||
|
root.destroy()
|
||||||
|
|
||||||
|
def create_diagram(plot, coordinates_text, canvas):
|
||||||
|
plot.clear()
|
||||||
|
plot.set_xlim(0, 90)
|
||||||
|
plot.set_ylim(0, 50) # Beispielgrenzen für Drehmoment
|
||||||
|
plot.set_xlabel('Drehwinkel in Grad')
|
||||||
|
plot.set_ylabel('Drehmoment in Nm')
|
||||||
|
|
||||||
|
coordinates = coordinates_text.get("1.0", tk.END).strip().split("\n")
|
||||||
|
valid_coords = [coord for coord in coordinates if ',' in coord and len(coord.split(',')) == 2]
|
||||||
|
|
||||||
|
if valid_coords:
|
||||||
|
x_coords, y_coords = zip(*(map(float, coord.split(',')) for coord in valid_coords))
|
||||||
|
plot.plot(x_coords, y_coords, marker='o', linestyle='-')
|
||||||
|
else:
|
||||||
|
messagebox.showerror("Eingabefehler", "Bitte geben Sie gültige Koordinaten ein. Beispiel: '10,20'")
|
||||||
|
|
||||||
|
canvas.draw()
|
||||||
|
|
||||||
|
|
||||||
|
def send_command_to_arduino(command):
|
||||||
|
if arduino and arduino.is_open:
|
||||||
|
try:
|
||||||
|
arduino.write(command.encode())
|
||||||
|
response = arduino.readline().decode().strip()
|
||||||
|
print(f"Arduino Antwort: {response}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Fehler beim Senden des Befehls {command}: {e}")
|
||||||
|
|
||||||
|
def on_plot_button_click(torque_input, coordinates_text, plot, canvas):
|
||||||
|
if torque_mode.get():
|
||||||
|
set_torque = float(torque_input.get())
|
||||||
|
command = f's{int(set_torque * 1000000):08x}'
|
||||||
|
send_command_to_arduino(command)
|
||||||
|
else:
|
||||||
|
create_diagram(plot, coordinates_text, canvas)
|
||||||
|
|
||||||
|
def setup_gui():
|
||||||
|
global root, torque_mode
|
||||||
|
root = tk.Tk()
|
||||||
|
root.title("Drehmoment-Regelungssystem")
|
||||||
|
|
||||||
|
main_frame = tk.Frame(root)
|
||||||
|
main_frame.pack(fill=tk.BOTH, expand=True)
|
||||||
|
|
||||||
|
left_frame = tk.Frame(main_frame, borderwidth=2, relief=tk.GROOVE)
|
||||||
|
left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
|
||||||
|
|
||||||
|
right_frame = tk.Frame(main_frame, borderwidth=2, relief=tk.GROOVE)
|
||||||
|
right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
|
||||||
|
|
||||||
|
coordinates_label = tk.Label(left_frame, text="Koordinaten (Drehwinkel, Drehmoment):")
|
||||||
|
coordinates_label.pack()
|
||||||
|
coordinates_text = tk.Text(left_frame, height=5)
|
||||||
|
coordinates_text.pack()
|
||||||
|
|
||||||
|
torque_label = tk.Label(left_frame, text="Soll-Drehmoment in Nm:")
|
||||||
|
torque_label.pack()
|
||||||
|
torque_input = tk.Entry(left_frame)
|
||||||
|
torque_input.pack()
|
||||||
|
|
||||||
|
toggle_button = tk.Button(left_frame, text="Wechsel Drehmomentmodus", command=lambda: toggle_torque_mode(torque_input, coordinates_text))
|
||||||
|
toggle_button.pack()
|
||||||
|
|
||||||
|
plot_button = tk.Button(left_frame, text="Eingaben übernehmen", command=lambda: on_plot_button_click(torque_input, coordinates_text, plot, canvas))
|
||||||
|
plot_button.pack()
|
||||||
|
|
||||||
|
close_button = tk.Button(left_frame, text="Schließen", command=close_application)
|
||||||
|
close_button.pack()
|
||||||
|
|
||||||
|
figure = Figure(figsize=(5, 4), dpi=100)
|
||||||
|
plot = figure.add_subplot(111)
|
||||||
|
canvas = FigureCanvasTkAgg(figure, right_frame)
|
||||||
|
canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
|
||||||
|
|
||||||
|
torque_mode = tk.BooleanVar()
|
||||||
|
torque_mode.set(False)
|
||||||
|
|
||||||
|
def toggle_torque_mode(torque_input, coordinates_text):
|
||||||
|
if torque_mode.get():
|
||||||
|
torque_input.config(state='normal')
|
||||||
|
coordinates_text.config(state='disabled')
|
||||||
|
else:
|
||||||
|
torque_input.config(state='disabled')
|
||||||
|
coordinates_text.config(state='normal')
|
||||||
|
|
||||||
|
def main():
|
||||||
|
setup_gui()
|
||||||
|
open_serial_connection()
|
||||||
|
root.mainloop()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
251
main_v3.py
Normal file
251
main_v3.py
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
import tkinter as tk
|
||||||
|
from tkinter import ttk, messagebox
|
||||||
|
import serial
|
||||||
|
import serial.tools.list_ports
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
class ArduinoGUI:
|
||||||
|
def __init__(self, root):
|
||||||
|
self.root = root
|
||||||
|
self.root.title("Arduino GUI")
|
||||||
|
|
||||||
|
self.arduino = None
|
||||||
|
self.ports = list(serial.tools.list_ports.comports())
|
||||||
|
self.running = True
|
||||||
|
self.current_point = None
|
||||||
|
self.setpoints = []
|
||||||
|
|
||||||
|
# Flags for user actions
|
||||||
|
self.setpoint_flag = False
|
||||||
|
self.multi_setpoints_flag = False
|
||||||
|
self.tare_flag = False
|
||||||
|
self.demag_flag = False
|
||||||
|
|
||||||
|
self.create_widgets()
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
self.connect_button = tk.Button(self.root, text="Connect", command=self.connect_arduino)
|
||||||
|
self.connect_button.grid(row=0, column=2)
|
||||||
|
|
||||||
|
self.setpoint_label = tk.Label(self.root, text="Setpoint (Nm):")
|
||||||
|
self.setpoint_label.grid(row=1, column=0)
|
||||||
|
|
||||||
|
self.setpoint_entry = tk.Entry(self.root)
|
||||||
|
self.setpoint_entry.grid(row=1, column=1)
|
||||||
|
|
||||||
|
self.set_setpoint_button = tk.Button(self.root, text="Set", command=self.set_setpoint)
|
||||||
|
self.set_setpoint_button.grid(row=1, column=2)
|
||||||
|
|
||||||
|
self.multi_setpoints_label = tk.Label(self.root, text="Setpoints (angle;torque):")
|
||||||
|
self.multi_setpoints_label.grid(row=2, column=0)
|
||||||
|
|
||||||
|
self.multi_setpoints_text = tk.Text(self.root, height=5, width=20)
|
||||||
|
self.multi_setpoints_text.grid(row=2, column=1)
|
||||||
|
|
||||||
|
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.tare_button = tk.Button(self.root, text="Tare Angle", command=self.tare_angle)
|
||||||
|
self.tare_button.grid(row=3, column=2)
|
||||||
|
|
||||||
|
self.demag_button = tk.Button(self.root, text="Demagnetize", command=self.demagnetize)
|
||||||
|
self.demag_button.grid(row=4, column=2)
|
||||||
|
|
||||||
|
self.exit_button = tk.Button(self.root, text="Exit", command=self.on_closing)
|
||||||
|
self.exit_button.grid(row=5, column=2)
|
||||||
|
|
||||||
|
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.ax.set_title("Drehmoment-Drehwinkel-Kennlinie")
|
||||||
|
self.ax.set_xlabel("Winkel (°)")
|
||||||
|
self.ax.set_ylabel("Drehmoment (Nm)")
|
||||||
|
self.ax.set_xlim(0, 90)
|
||||||
|
self.ax.set_ylim(0, 50)
|
||||||
|
|
||||||
|
self.current_angle = 0
|
||||||
|
self.current_torque = 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.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)
|
||||||
|
|
||||||
|
def connect_arduino(self):
|
||||||
|
com_port = self.combobox_value.get()
|
||||||
|
if com_port:
|
||||||
|
try:
|
||||||
|
self.arduino = serial.Serial(com_port, 115200, timeout=1)
|
||||||
|
messagebox.showinfo("Info", "Connected to Arduino on " + com_port)
|
||||||
|
except Exception as e:
|
||||||
|
messagebox.showerror("Error", str(e))
|
||||||
|
else:
|
||||||
|
messagebox.showwarning("Warning", "Please select a COM port")
|
||||||
|
|
||||||
|
def set_setpoint(self):
|
||||||
|
if self.arduino:
|
||||||
|
try:
|
||||||
|
self.setpoint = float(self.setpoint_entry.get()) * 1000
|
||||||
|
self.setpoint_flag = True
|
||||||
|
except ValueError:
|
||||||
|
messagebox.showerror("Error", "Invalid setpoint value.")
|
||||||
|
else:
|
||||||
|
messagebox.showwarning("Warning", "Arduino not connected")
|
||||||
|
|
||||||
|
def send_multi_setpoints(self):
|
||||||
|
if self.arduino:
|
||||||
|
setpoints = self.multi_setpoints_text.get("1.0", tk.END).strip().split("\n")
|
||||||
|
coordinates = []
|
||||||
|
for point in setpoints:
|
||||||
|
try:
|
||||||
|
angle, torque = map(float, point.split(";"))
|
||||||
|
coordinates.append((angle, torque))
|
||||||
|
except ValueError:
|
||||||
|
messagebox.showerror("Error", f"Invalid input: {point}")
|
||||||
|
return
|
||||||
|
|
||||||
|
coordinates.sort()
|
||||||
|
self.setpoints = coordinates
|
||||||
|
self.plot_coordinates(coordinates)
|
||||||
|
self.multi_setpoints_flag = True
|
||||||
|
else:
|
||||||
|
messagebox.showwarning("Warning", "Arduino not connected")
|
||||||
|
|
||||||
|
def plot_coordinates(self, coordinates):
|
||||||
|
angles, torques = zip(*coordinates)
|
||||||
|
self.ax.clear()
|
||||||
|
self.ax.plot(angles, torques, 'bo-', label="Setpoints")
|
||||||
|
self.ax.set_title("Drehmoment-Drehwinkel-Kennlinie")
|
||||||
|
self.ax.set_xlabel("Winkel (°)")
|
||||||
|
self.ax.set_ylabel("Drehmoment (Nm)")
|
||||||
|
self.ax.set_xlim(0, 90)
|
||||||
|
self.ax.set_ylim(0, 50)
|
||||||
|
self.ax.legend()
|
||||||
|
self.canvas.draw()
|
||||||
|
|
||||||
|
def interpolate_coordinates(self, coordinates):
|
||||||
|
interpolated_points = []
|
||||||
|
for i in range(len(coordinates) - 1):
|
||||||
|
start_angle, start_torque = coordinates[i]
|
||||||
|
end_angle, end_torque = coordinates[i + 1]
|
||||||
|
num_points = int((end_angle - start_angle) * 2)
|
||||||
|
angles = np.linspace(start_angle, end_angle, num_points + 1)
|
||||||
|
torques = np.linspace(start_torque, end_torque, num_points + 1)
|
||||||
|
interpolated_points.extend(zip(angles, torques))
|
||||||
|
|
||||||
|
full_interpolated_points = [(angle, 0) for angle in np.arange(0, 90.5, 0.5)]
|
||||||
|
for angle, torque in interpolated_points:
|
||||||
|
index = int(angle * 2)
|
||||||
|
full_interpolated_points[index] = (angle, torque)
|
||||||
|
|
||||||
|
return full_interpolated_points
|
||||||
|
|
||||||
|
def send_interpolated_points(self):
|
||||||
|
if self.arduino:
|
||||||
|
setpoints_command = "u"
|
||||||
|
for angle, torque in self.setpoints:
|
||||||
|
torque_mnm = torque * 1000
|
||||||
|
setpoints_command += f"{int(angle * 2)},{torque_mnm:.1f};"
|
||||||
|
setpoints_command = setpoints_command.rstrip(';') + "u\n"
|
||||||
|
self.arduino.write(setpoints_command.encode())
|
||||||
|
|
||||||
|
timeout_ctr = time.time()
|
||||||
|
while(self.arduino.in_waiting == 0 and time.time() - timeout_ctr < 2):
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
print(self.arduino.readline())
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
def tare_angle(self):
|
||||||
|
if self.arduino:
|
||||||
|
self.tare_flag = True
|
||||||
|
else:
|
||||||
|
messagebox.showwarning("Warning", "Arduino not connected")
|
||||||
|
|
||||||
|
def demagnetize(self):
|
||||||
|
if self.arduino:
|
||||||
|
self.demag_flag = True
|
||||||
|
else:
|
||||||
|
messagebox.showwarning("Warning", "Arduino not connected")
|
||||||
|
|
||||||
|
def communication_loop(self):
|
||||||
|
while self.running:
|
||||||
|
if self.arduino:
|
||||||
|
self.arduino.read_all()
|
||||||
|
if self.setpoint_flag:
|
||||||
|
self.arduino.write(f"s{self.setpoint:.0f},0\n".encode())
|
||||||
|
self.setpoint_flag = False
|
||||||
|
time.sleep(0.1)
|
||||||
|
if self.multi_setpoints_flag:
|
||||||
|
self.send_interpolated_points()
|
||||||
|
self.multi_setpoints_flag = False
|
||||||
|
time.sleep(0.1)
|
||||||
|
if self.tare_flag:
|
||||||
|
self.arduino.write(b'w\n')
|
||||||
|
self.tare_flag = False
|
||||||
|
time.sleep(0.1)
|
||||||
|
if self.demag_flag:
|
||||||
|
self.arduino.write(b'e\n')
|
||||||
|
self.demag_flag = False
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
self.arduino.write(b'a\n')
|
||||||
|
timeout_ctr = time.time()
|
||||||
|
while(self.arduino.in_waiting == 0 and time.time() - timeout_ctr < 2):
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
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.angle_label_var.set(f"Current Angle: {self.current_angle}")
|
||||||
|
self.torque_label_var.set(f"Current Torque: {self.current_torque}")
|
||||||
|
|
||||||
|
if self.current_point is not None:
|
||||||
|
self.current_point.remove()
|
||||||
|
self.current_point, = self.ax.plot([self.current_angle], [self.current_torque], 'ro')
|
||||||
|
self.canvas.draw()
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
def on_closing(self):
|
||||||
|
self.running = False
|
||||||
|
if self.arduino:
|
||||||
|
self.arduino.close()
|
||||||
|
self.root.quit()
|
||||||
|
self.root.destroy()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
root = tk.Tk()
|
||||||
|
app = ArduinoGUI(root)
|
||||||
|
root.protocol("WM_DELETE_WINDOW", app.on_closing)
|
||||||
|
root.mainloop()
|
||||||
BIN
src/logo1.png
Normal file
BIN
src/logo1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 162 KiB |
Reference in New Issue
Block a user