diff --git a/integration/integrate.py b/integration/integrate.py index 3edb8670f00862beefcdcc795d1e46ec127c8aa1..046179c4a633766adb555b5de93fe3eece841318 100644 --- a/integration/integrate.py +++ b/integration/integrate.py @@ -1,14 +1,25 @@ import tkinter as tk from tkinter import ttk +from matplotlib.pyplot import Figure import serial - +from math import atan2, asin, cos, sin +from matplotlib.figure import Figure +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg +import numpy as np +import time class Interface: def __init__(self): print("start") + self.treeview = None + self.x_data = [] + self.y1_data = [] + self.y2_data = [] + def create_popup(self): + global frame1, frame2, frame3, frame4,width,height,popup popup = tk.Tk() popup.title("Project") @@ -28,28 +39,29 @@ class Interface: popup.rowconfigure(1, weight=1) # First row, two sections - frame1 = ttk.Frame(popup, borderwidth=1, relief="solid") + frame1 = ttk.Frame(popup, borderwidth=1, relief="solid",width=width/3,height=height/2) frame1.grid(row=0, column=0, padx=10, pady=10, sticky="nsew") - label1 = ttk.Label(frame1, text="If IMU is connected to the laptop please click the Connect button") + label1 = ttk.Label(frame1, text="If IMU is connected to the laptop please click the Connect button",wraplength=width/4) label1.place(relx=0.5, rely=0.9, anchor='center') label2 = ttk.Label(frame1,text="Port: None ") - label2.place(relx=0.2, rely=0.8, anchor='center') + label2.place(relx=0.35, rely=0.8, anchor='e') - frame2 = ttk.Frame(popup, borderwidth=1, relief="solid") + frame2 = ttk.Frame(popup, borderwidth=1, relief="solid",width=width*2/3,height=height/2) frame2.grid(row=0, column=1, padx=10, pady=10, sticky="nsew") label2 = ttk.Label(frame2, text="Section 2") label2.place(relx=0.5, rely=0.5, anchor='center') # Second row, two sections - frame3 = ttk.Frame(popup, borderwidth=1, relief="solid") + frame3 = ttk.Frame(popup, borderwidth=1, relief="solid",width=width/3,height=height/2) frame3.grid(row=1, column=0, padx=10, pady=10, sticky="nsew") - label3 = ttk.Label(frame3, text="If EMG is connected to the laptop please click the Connect button") + label3 = ttk.Label(frame3, text="If EMG is connected to the laptop please click the Connect button",wraplength=width/4) label3.place(relx=0.5, rely=0.9, anchor='center') label4 = ttk.Label(frame3, text="Port: None ") - label4.place(relx=0.2, rely=0.8, anchor='center') + label4.place(relx=0.35, rely=0.8, anchor='e') - frame4 = ttk.Frame(popup, borderwidth=1, relief="solid") + frame4 = ttk.Frame(popup, borderwidth=1, relief="solid",width=width*2/3,height=height/2) frame4.grid(row=1, column=1, padx=10, pady=10, sticky="nsew") + frame4.grid_propagate(False) label4 = ttk.Label(frame4, text="Section 4") label4.place(relx=0.5, rely=0.5, anchor='center') @@ -66,25 +78,161 @@ class Interface: try: arduino = serial.Serial('COM4', 115200, timeout=1) column_limit = 9 - # 执行后续步骤 + label2 = ttk.Label(frame1, text="Port: COM4 ") + label2.place(relx=0.2, rely=0.8, anchor='center') print("Connected to IMU") - # 例如,读取一些数据 - # data = arduino.readline() - # print(data) except serial.SerialException: print("IMU is not connected") + return + + try: + while True: + while arduino.inWaiting() == 0: + pass + + try: + data_packet = arduino.readline().decode('utf-8').strip() + data = data_packet.split(',') + + if len(data) == column_limit: + emg = float(data[0]) # emg sensor data + q0 = float(data[1]) # qw + q1 = float(data[2]) # qx + q2 = float(data[3]) # qy + q3 = float(data[4]) # qz + + roll = atan2(2 * (q0 * q1 + q2 * q3), 1 - 2 * (q1 * q1 + q2 * q2)) + pitch = -asin(2 * (q0 * q2 - q3 * q1)) + yaw = -atan2(2 * (q0 * q3 + q1 * q2), 1 - 2 * (q2 * q2 + q3 * q3)) + + print(f"EMG: {emg}, Roll: {roll}, Pitch: {pitch}, Yaw: {yaw}") + else: + print("Data packet does not match column limit") + + except ValueError: + print("Error in data conversion") + except UnicodeDecodeError: + print("Error in decoding data") + + except KeyboardInterrupt: + arduino.close() + print("Disconnected from IMU") + + def EMG_Connect(self): try: - arduino = serial.Serial('COM4', 115200, timeout=1) - column_limit = 9 - # 执行后续步骤 + self.arduino = serial.Serial('COM5', 115200, timeout=1) + label2 = ttk.Label(frame3, text="Port: COM5 ") + label2.place(relx=0.35, rely=0.8, anchor='e') + label_EMG_title = ttk.Label(frame3, text="Auto Calibralian",font=("Helvetica", 16)) + label_EMG_title.place(relx=0.5, rely=0.1, anchor='center') + label_EMG_Gesture = ttk.Label(frame3, text="Gesture :", font=("Helvetica", 13)) + label_EMG_Gesture.place(relx=0.2, rely=0.5, anchor='center') + self._initialise_real_time_classification_graph() + self.read_and_display_emg_data() print("Connected to EMG") - # 例如,读取一些数据 - # data = arduino.readline() - # print(data) except serial.SerialException: print("EMG is not connected") + return + + def read_and_display_emg_data(self): + while True: + emg_values = self.read_emg_data() + if emg_values is not None: + print(f"EMG Value 1: {emg_values[0]}, EMG Value 2: {emg_values[1]}") + if len(emg_values) >= 2: + # 更新表格 + self.update_table(emg_values) + + # 更新数据存储 + self.x_data.append(len(self.x_data) + 1) + self.y1_data.append(emg_values[0]) + self.y2_data.append(emg_values[1]) + + # 保持数据长度 + if len(self.x_data) > 100: + self.x_data = self.x_data[-100:] + self.y1_data = self.y1_data[-100:] + self.y2_data = self.y2_data[-100:] + + # 更新图表 + self.update_graph() + # 在这里添加数据分析代码 + # 例如,计算平均值,滤波等 + else: + print("Failed to read EMG data") + time.sleep(0.1) # 控制读取频率 + + + + # 定时读取数据 (1000ms = 1秒) + #popup.after(1000, self.read_and_display_emg_data, self.arduino) + + def update_graph(self): + # 更新线的数据 + self.line1.set_data(self.x_data, self.y1_data) + self.line2.set_data(self.x_data, self.y2_data) + + # 设置 X 轴范围 + self.ax.set_xlim(min(self.x_data), max(self.x_data)) + + # 自适应 Y 轴范围 + self.ax.relim() + self.ax.autoscale_view() + + # 更新图表 + self.canvas.draw() + + def update_table(self, emg_data): + if self.treeview: + self.treeview.delete(*self.treeview.get_children()) # 清除现有数据 + self.treeview.insert("", "end", values=("Gesture 1", f"{emg_data[0]:.2f}")) + self.treeview.insert("", "end", values=("Gesture 2", f"{emg_data[1]:.2f}")) + + + + + + def _initialise_real_time_classification_graph(self): + # Create a figure and axis + fig = Figure(figsize=((width / 200), (height / 200))) # Adjusting figsize based on frame size + self.ax = fig.add_subplot(111) + + self.ax.set_title("Electromyography Envelope", fontsize=14, pad=0) + + + self.ax.set_xlim(0, 5) + self.ax.set_ylim(0, 5) + + self.ax.set_xlabel("Sample(20 samples per second)",fontsize=8,labelpad=-2) + self.ax.set_ylabel("Magnitude",labelpad=0) + + self.ax.set_xticks(np.arange(0, 41, 8)) + self.ax.set_yticks(np.arange(0, 1001, 200)) + + for x_tick in self.ax.get_xticks(): + self.ax.axvline(x_tick, color='gray', linestyle='--', linewidth=0.5) + for y_tick in self.ax.get_yticks(): + self.ax.axhline(y_tick, color='gray', linestyle='--', linewidth=0.5) + + + + + # Plot two lines + self.line1, = self.ax.plot([], [], color='red', label='Outer Wrist Muscle (Extensor Carpi Ulnaris)') + self.line2, = self.ax.plot([], [], color='blue', label='Inner Wrist Muscle (Flexor Carpi Radialis)') + self.ax.legend(fontsize=9, loc='upper right') + + + + + # Embed the plot in the tkinter frame + self.canvas = FigureCanvasTkAgg(fig, master=frame4) + self.canvas.draw() + self.canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True) + +