3rd Update
简洁风
code
#11:06:57Current_POS_is: X:77Y:471Z:0U:-2 C:\Log\V55.txt
import time
import tkinter as tk
from tkinter import messagebox
from PIL import Image, ImageTk
import socket
import threading
from datetime import datetime
import logging
import subprocess # 确保导入 subprocess 库
import os
import pyautogui
from HslCommunication import MelsecMcNet
import json
import random
import math
import matplotlib
matplotlib.use('TkAgg') # 设置matplotlib后端
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import numpy as np
#from sklearn.linear_model import LinearRegression
# 修正后的全局变量声明
Response = 0
Offset_X = 0
Offset_Y = 0
Offset_U = 0
Ares_Sensor=None
#定义文件夹路径
folder_path = r'c:\Log' #C:\v5\Public_Release
# 检查文件夹是否存在,如果不存在则创建
if not os.path.exists(folder_path):
os.makedirs(folder_path)
# 设置日志配置
#logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# 新增格式化器,精确到毫秒
formatter = logging.Formatter(
fmt='%(asctime)s,%(msecs)03d - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# 设置基础日志配置
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s,%(msecs)03d - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# 如果已有其他处理器(如 StreamHandler),也应设置相同格式
class TextHandler(logging.Handler):
def __init__(self, widget):
super().__init__()
self.widget = widget
self.formatter = logging.Formatter(
fmt='%(asctime)s,%(msecs)03d - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
def emit(self, record):
# 检查 widget 是否存在且未被销毁
if self.widget and self.widget.winfo_exists():
msg = self.formatter.format(record)
self.widget.insert(tk.END, msg + '\n')
self.widget.yview_moveto(1)
class MyClass(tk.Frame):
def __init__(self, root, parent):
super().__init__(parent) # 初始化父类
self.root = root
self.parent = parent
class TCPClientApp:
def __init__(self, root, parent=None):
self.root = root
self.vision_client_socket = None
self.robot_client_socket = None
self.connected_to_vision = False
self.connected_to_robot = False
self.vision_ip = "127.0.0.1"
self.vision_port = 8888
self.robot_ip = "192.168.0.1" #192.168.0.1
self.robot_port = 2009 #2004
self.is_engineering_mode = True # 新增模式标志
# 新增 CONFIG_PATH 定义
self.CONFIG_PATH = r'C:\Log\config.json' # 配置文件路径
# 确保 INDUSTRIAL_COLORS 初始化在 setup_ui 调用之前
self.INDUSTRIAL_COLORS = {
'bg_main': '#404040', # 主背景色
'fg_main': '#FFFFFF', # 主前景色
'accent': '#FFA500', # 强调色
}
self.setup_ui()
self.setup_logging()
self.app3_process = None # 用于存储子进程的引用
self.parent = parent or root # 自动降级处理
self.plc = None
self.last_y79_state = False # 新增状态缓存
self.last_X2F_state = True # 新增状态缓存
self.setup_plc()
self.start_plc_monitoring()
self.init_plc_connection() # PLC运行
self.run_button = None
self.image_label = None
self.images = []
self.image_index = 0 # 确保在类初始化时设置默认值
###开启程序后自动启动项目
self.connect_to_vision()
self.connect_to_robot()
###开启程序后自动加载offset
self.load_settings()
# 修改窗口关闭事件处理
self.root.protocol("WM_DELETE_WINDOW", self.on_exit)
# 数据存储 Chart
self.history_data = {
'X': [],
'Y': [],
'U': [],
'timestamps': []
}
# 启动定时更新
self.update_interval = 888 # 3.888秒
self.root.after(self.update_interval, self.update_display)
self.update_history_chart()
self.home_received = False # 新增状态变量
def update_image(self):
# 检查图片列表是否存在且非空
if not hasattr(self, 'images') or not self.images:
logging.warning("No Pictures")
self.root.after(333, self.update_image) # 使用 after 安排下一次更新
return
# 检查 image_label 是否初始化
if not hasattr(self, 'image_label') or self.image_label is None:
logging.error("Picture Ini...")
# 使用保存的 right_frame 重新初始化
if hasattr(self, 'right_frame'):
self.create_right_panel(self.right_frame)
else:
logging.error("无法找到 right_frame,无法重新初始化 image_label")
self.root.after(333, self.update_image) # 避免直接递归调用
return
try:
img = self.images[self.image_index]
self.image_label.config(image=img)
self.image_label.image = img
logging.debug(f"成功更新图片索引 {self.image_index}")
except Exception as e:
logging.error(f"更新图片失败: {str(e)}")
self.root.after(1000, self.update_image) # 避免直接递归调用
return
# 更新索引并触发下一次更新
self.image_index = (self.image_index + 1) % len(self.images)
self.root.after(1000, self.update_image) # 使用 after 安排下一次更新
def toggle_mode(self):
self.is_engineering_mode = not self.is_engineering_mode
if self.is_engineering_mode:
self.mode_button.config(text="切换到运转模式")
self.show_engineering_mode()
else:
self.mode_button.config(text="切换到工程模式")
self.show_operation_mode()
def start_run(self):
# 运行按钮点击事件处理
pass
def _update_gauge(self, gauge, value):
"""单个仪表更新逻辑"""
# 更新数值显示
gauge['label'].config(text=f"{value:.2f}")
# 更新指针角度(-60°到240°范围)
angle = 150 * (value / 100) - 60 # 假设值范围-100到100
canvas = gauge['canvas']
canvas.delete('needle')
x = 60 + 40 * math.cos(math.radians(angle))
y = 40 - 40 * math.sin(math.radians(angle))
canvas.create_line(60, 40, x, y, fill='red', width=2, tags='needle')
def update_history_chart(self):
"""更新历史趋势图"""
if not self.history_data['timestamps']:
return
# 限制显示8个数据点
keep_points = 8
x_data = self.history_data['timestamps'][-keep_points:]
self.line_x.set_data(x_data, self.history_data['X'][-keep_points:])
self.line_y.set_data(x_data, self.history_data['Y'][-keep_points:])
self.line_u.set_data(x_data, self.history_data['U'][-keep_points:])
# 自动调整坐标轴
self.ax.relim()
self.ax.autoscale_view()
# 显示最新值 - 工业风格
if self.history_data['X']:
latest_x = self.history_data['X'][-1]
latest_y = self.history_data['Y'][-1]
latest_u = self.history_data['U'][-1]
# 清除之前的文本
for text in self.ax.texts:
text.remove()
# 添加新的值显示 - 工业风格
self.ax.text(0.02, 0.95,
f"Last: X={latest_x:.3f} Y={latest_y:.3f} U={latest_u:.5f}",
transform=self.ax.transAxes,
fontsize=12, # 工业标准字号
color='#FFA500', # 工业橙色
bbox=dict(facecolor='#404040', alpha=0.69, edgecolor='#333333')) # 工业灰色背景
# 显示在上还是曲线在上
self.chart_canvas.draw()
#
def toggle_mode(self):
self.is_engineering_mode = not self.is_engineering_mode
if self.is_engineering_mode:
self.mode_button.config(text="切换到运转模式")
self.show_engineering_mode()
else:
self.mode_button.config(text="切换到工程模式")
self.show_operation_mode()
def start_run(self):
# 运行按钮点击事件处理
pass
def update_display(self):
"""定时更新显示"""
try:
# 更新仪表盘
self.update_gauges()
# 更新趋势图
self.update_history_chart()
# 确保图表窗口仍然存在
if hasattr(self, 'chart_window') and self.chart_window.winfo_exists():
# 获取当前数据点限制
keep_points = getattr(self, 'point_limit', 8)
# 限制显示的数据点数量
x_data = self.history_data['timestamps'][-keep_points:]
# 更新X轴数据
self.line_x.set_data(x_data, self.history_data['X'][-keep_points:])
# 更新Y轴数据
self.line_y.set_data(x_data, self.history_data['Y'][-keep_points:])
# 更新U轴数据
self.line_u.set_data(x_data, self.history_data['U'][-keep_points:])
# 自动调整坐标轴
ax = self.line_x.axes
ax.relim()
ax.autoscale_view()
# 更新动态标题 - 工业风格
if self.history_data['X']:
latest_x = self.history_data['X'][-1]
latest_y = self.history_data['Y'][-1]
latest_u = self.history_data['U'][-1]
# 清除之前的文本
for text in ax.texts:
text.remove()
# 添加新的值显示 - 工业风格
ax.text(0.02, 0.95,
f"Last: X={latest_x:.3f} Y={latest_y:.3f} U={latest_u:.5f}",
transform=ax.transAxes,
fontsize=12,
color='#FFA500',
bbox=dict(facecolor='#404040', alpha=0.69, edgecolor='#333333'))
# 重新绘制图表
ax.figure.canvas.draw()
finally:
# 确保图表窗口仍然存在时才继续定时器
if hasattr(self, 'chart_window') and self.chart_window.winfo_exists():
self.root.after(1000, self.update_display)
def update_static_chart(self):
"""更新静态图表显示"""
try:
# 获取数据点限制
keep_points = 5 # 固定显示最后5个数据点
# 如果没有历史数据,直接返回
if not self.history_data or not self.history_data['timestamps']:
return
# 限制显示的数据点数量
x_data = self.history_data['timestamps'][-keep_points:]
# 更新X轴数据
self.line_x.set_data(x_data, self.history_data['X'][-keep_points:])
# 更新Y轴数据
self.line_y.set_data(x_data, self.history_data['Y'][-keep_points:])
# 更新U轴数据
self.line_u.set_data(x_data, self.history_data['U'][-keep_points:])
# 自动调整坐标轴
ax = self.line_x.axes
ax.relim()
ax.autoscale_view()
# 更新动态标题 - 工业风格
if self.history_data['X']:
latest_x = self.history_data['X'][-1]
latest_y = self.history_data['Y'][-1]
latest_u = self.history_data['U'][-1]
# 清除之前的文本
for text in ax.texts:
text.remove()
# 添加新的值显示 - 工业风格
ax.text(0.02, 0.95,
f"Last: X={latest_x:.3f} Y={latest_y:.3f} U={latest_u:.5f}",
transform=ax.transAxes,
fontsize=12,
color='#FFA500',
bbox=dict(facecolor='#404040', alpha=0.69, edgecolor='#333333'))
# 重新绘制图表
ax.figure.canvas.draw()
finally:
# 静态数据只需更新一次,不需要定时器
pass
# 确保仪表盘也更新
self.update_gauges()
def _update_gauge(self, gauge, value):
"""单个仪表更新逻辑"""
# 更新数值显示
gauge['label'].config(text=f"{value:.2f}")
# 更新指针角度(-60°到240°范围)
angle = 150 * (value / 100) - 60 # 假设值范围-100到100
canvas = gauge['canvas']
canvas.delete('needle')
x = 60 + 40 * math.cos(math.radians(angle))
y = 40 - 40 * math.sin(math.radians(angle))
canvas.create_line(60, 40, x, y, fill='red', width=2, tags='needle')
def update_history_chart(self):
"""更新历史趋势图"""
if not self.history_data['timestamps']:
return
# 限制显示8个数据点
keep_points = 8
x_data = self.history_data['timestamps'][-keep_points:]
self.line_x.set_data(x_data, self.history_data['X'][-keep_points:])
self.line_y.set_data(x_data, self.history_data['Y'][-keep_points:])
self.line_u.set_data(x_data, self.history_data['U'][-keep_points:])
# 自动调整坐标轴
self.ax.relim()
self.ax.autoscale_view()
# 显示最新值 - 工业风格
if self.history_data['X']:
latest_x = self.history_data['X'][-1]
latest_y = self.history_data['Y'][-1]
latest_u = self.history_data['U'][-1]
# 清除之前的文本
for text in self.ax.texts:
text.remove()
# 添加新的值显示 - 工业风格
self.ax.text(0.02, 0.95,
f"Last: X={latest_x:.3f} Y={latest_y:.3f} U={latest_u:.5f}",
transform=self.ax.transAxes,
fontsize=12, # 工业标准字号
color='#FFA500', # 工业橙色
bbox=dict(facecolor='#404040', alpha=0.69, edgecolor='#333333')) # 工业灰色背景
# 显示在上还是曲线在上
self.chart_canvas.draw()
def setup_ui(self):
# 主窗口背景色
self.root.configure(bg=self.INDUSTRIAL_COLORS['bg_main'])
self.root.title("Design by Tim")
self.root.geometry("1924x968") #Display Pix_1024 768 Windows
# Grid weights for resizing behavior
self.root.grid_columnconfigure(0, weight=1)
self.root.grid_columnconfigure(1, weight=2)
self.root.grid_columnconfigure(2, weight=1)
self.root.grid_rowconfigure(0, weight=1)
self.root.grid_rowconfigure(1, weight=1)
# Left Frame
left_frame = tk.Frame(self.root)
left_frame.grid(row=0, column=0, padx=5, pady=5, sticky="nsew")
self.create_left_panel(left_frame)
# Right Frame
right_frame = tk.Frame(self.root)
right_frame.grid(row=0, column=2, padx=5, pady=5, sticky="nsew")
self.create_right_panel(right_frame)
# Bottom Frame
bottom_frame = tk.Frame(self.root, bg='lightgray')
bottom_frame.grid(row=1, column=0, columnspan=3, padx=5, pady=5, sticky="nsew")
self.create_bottom_panel(bottom_frame)
##
def load_images(self):
path = r'C:\Log\Picture'
# 新增:检查目录是否存在并记录日志
if not os.path.exists(path):
logging.error(f"图片文件夹路径不存在: {path}")
self.root.after(3000, self.load_images) # 3秒后重试(替换递归)
return
if not os.path.isdir(path):
logging.error(f"指定路径不是有效的文件夹: {path}")
self.root.after(3000, self.load_images) # 3秒后重试(替换递归)
return
# 新增:记录目录下所有文件(排查文件名问题)
dir_files = os.listdir(path)
logging.debug(f"目录 {path} 下的文件列表: {dir_files}")
extensions = ['.jpg', '.jpeg', '.png', '.bmp', '.gif']
self.images = [] # 清空旧数据
for ext in extensions:
for file in dir_files: # 使用已获取的文件列表(避免重复调用os.listdir)
if file.lower().endswith(ext):
img_path = os.path.join(path, file)
try:
# 新增:记录具体加载的文件
logging.info(f"Retry 2 Loading: {img_path}")
img = Image.open(img_path)
img.thumbnail((456, 456)) # 缩略图适配显示
self.images.append(ImageTk.PhotoImage(img))
logging.debug(f"Loading : {img_path}")
except Exception as e:
# 新增:记录具体错误(如文件被占用、格式损坏)
logging.error(f"Loading {file}: {str(e)} NG ")
# 新增:记录最终加载结果
if not self.images:
logging.warning(f"未找到有效图片文件(共扫描 {len(dir_files)} 个文件),3秒后重新加载...")
self.root.after(3000, self.load_images) # 用after代替递归,避免栈溢出
else:
logging.info(f"Loading {len(self.images)} Pictures")
##
def create_chart_area(self, parent=None):
"""显示为独立弹窗的工业级数据显示面板"""
# 创建新窗口
chart_window = tk.Toplevel(self.root)
chart_window.title("Chart")
# 设置窗口大小和位置(居中显示)
window_width = 1000
window_height = 600
screen_width = chart_window.winfo_screenwidth()
screen_height = chart_window.winfo_screenheight()
x = (screen_width - window_width) // 2
y = (screen_height - window_height) // 2
chart_window.geometry(f'{window_width}x{window_height}+{x}+{y}')
# 使用与show_animation相同的框架结构
fig = Figure(figsize=(8, 4), dpi=60)
ax = fig.add_subplot(111)
# 初始化三条曲线 - 使用工业颜色
self.line_x, = ax.plot([], [], color='#FF0000', linewidth=2, label='X_Pos') # 红色
self.line_y, = ax.plot([], [], color='#00FF00', linewidth=2, label='Y_Pos') # 绿色
self.line_u, = ax.plot([], [], color='#00B0F0', linewidth=2, label='U_Pos') # 科技蓝
# 配置坐标轴和图例 - 工业风格
ax.set_title("Real", fontsize=14, color='#FFFFFF', pad=20)
ax.set_xlabel("Time", fontsize=12, color='#CCCCCC')
ax.set_ylabel("Value(mm)", fontsize=12, color='#CCCCCC')
ax.grid(True, color='#555555', linestyle='--', alpha=0.7)
ax.legend(loc='upper right', fontsize=10)
# 设置背景色
ax.set_facecolor('#333333')
fig.patch.set_facecolor('#404040')
# 设置刻度颜色
ax.tick_params(axis='x', colors='#CCCCCC')
ax.tick_params(axis='y', colors='#CCCCCC')
# 嵌入到Tkinter
canvas = FigureCanvasTkAgg(fig, master=chart_window)
canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
# 创建仪表盘框架
gauge_frame = tk.Frame(chart_window, bg='#404040')
gauge_frame.pack(side=tk.BOTTOM, fill=tk.X, pady=10)
# X值仪表
self.x_gauge = self.create_gauge(gauge_frame, "X Axis")
# Y值仪表
self.y_gauge = self.create_gauge(gauge_frame, "Y Axis")
# U值仪表
self.u_gauge = self.create_gauge(gauge_frame, "U Axis")
# 创建控制面板
control_frame = tk.Frame(chart_window)
control_frame.pack(side=tk.BOTTOM, fill=tk.X, pady=5)
# 添加重置按钮
reset_button = tk.Button(control_frame, text="Reset Data",
command=self.reset_chart_data, width=10)
reset_button.pack(side=tk.LEFT, padx=5)
# 添加数据点数量设置
point_frame = tk.Frame(control_frame)
point_frame.pack(side=tk.LEFT, padx=5)
tk.Label(point_frame, text="Data Points:").pack(side=tk.LEFT)
self.point_entry = tk.Entry(point_frame, width=5)
self.point_entry.pack(side=tk.LEFT)
self.point_entry.insert(0, "5") # 默认显示5个数据点
apply_point_button = tk.Button(point_frame, text="Apply",
command=lambda: self.apply_point_limit_change(), width=5)
apply_point_button.pack(side=tk.LEFT, padx=2)
# 添加关闭按钮
close_button = tk.Button(control_frame, text="Close",
command=chart_window.destroy, width=10)
close_button.pack(side=tk.RIGHT, padx=5)
# 初始化历史数据存储
self.history_data = {
'X': [],
'Y': [],
'U': [],
'timestamps': []
}
# 读取文件中的最后5条记录
file_path = r'C:\Log\log_His.txt'
trajectory_data = self.read_last_n_records(file_path, 5)
# 如果读取到数据,更新历史数据
if trajectory_data:
# 计算时间戳(假设每条记录间隔固定为1秒)
now = time.time()
timestamps = [now + i for i in range(len(trajectory_data))]
# 更新历史数据
for (x, y, z), t in zip(trajectory_data, timestamps):
self.history_data['X'].append(x)
self.history_data['Y'].append(y)
self.history_data['U'].append(z)
self.history_data['timestamps'].append(t)
# 初始化图表数据
self.setup_history_chart(ax)
# 创建并启动静态更新
self.update_static_chart()
def setup_history_chart(self, parent):
"""初始化历史趋势图"""
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
def reset_chart_data(self):
"""重置图表数据"""
# 清空历史数据
self.history_data['X'] = []
self.history_data['Y'] = []
self.history_data['U'] = []
self.history_data['timestamps'] = []
# 重新读取文件中的最后5条记录
file_path = r'C:\Log\log_His.txt'
trajectory_data = self.read_last_n_records(file_path, 5)
# 如果读取到数据,更新历史数据
if trajectory_data:
# 计算时间戳(假设每条记录间隔固定为1秒)
now = time.time()
timestamps = [now + i for i in range(len(trajectory_data))]
# 更新历史数据
for (x, y, z), t in zip(trajectory_data, timestamps):
self.history_data['X'].append(x)
self.history_data['Y'].append(y)
self.history_data['U'].append(z)
self.history_data['timestamps'].append(t)
# 更新静态图表
self.update_static_chart()
# 日志记录
logging.info("图表数据已重置并重新加载")
def reset_chart_data(self):
"""重置图表数据"""
# 初始化历史数据存储
self.history_data = {
'X': [],
'Y': [],
'U': [],
'timestamps': []
}
# 读取文件中的最后5条记录
file_path = r'C:\Log\log_His.txt'
trajectory_data = self.read_last_n_records(file_path, 5)
# 如果读取到数据,更新历史数据
if trajectory_data:
# 计算时间戳(假设每条记录间隔固定为1秒)
now = time.time()
timestamps = [now + i for i in range(len(trajectory_data))]
# 更新历史数据
for (x, y, z), t in zip(trajectory_data, timestamps):
self.history_data['X'].append(x)
self.history_data['Y'].append(y)
self.history_data['U'].append(z)
self.history_data['timestamps'].append(t)
# 更新静态图表
self.update_static_chart()
# 日志记录
logging.info("图表数据已重置并重新加载")
def update_chart_style(self):
"""更新图表样式设置"""
# 设置坐标轴和图例 - 工业风格
self.ax.set_title("实时趋势", fontsize=14, color='#FFFFFF', pad=20)
self.ax.set_xlabel("Time", fontsize=12, color='#CCCCCC')
self.ax.set_ylabel("Value(mm)", fontsize=12, color='#CCCCCC')
self.ax.grid(True, color='#555555', linestyle='--', alpha=0.7)
self.ax.legend(loc='upper right', fontsize=10)
# 设置背景色
self.ax.set_facecolor('#333333')
self.fig.patch.set_facecolor('#404040')
# 设置刻度颜色
self.ax.tick_params(axis='x', colors='#CCCCCC')
self.ax.tick_params(axis='y', colors='#CCCCCC')
# 重新绘制图表
self.ax.figure.canvas.draw()
# 更新图表样式
self.update_chart_style()
def create_left_panel(self, parent):
# 创建带滚动条的框架
left_container = tk.Frame(parent)
left_container.pack(fill=tk.BOTH, expand=True)
canvas = tk.Canvas(left_container, bg='#FFFFFF')
scrollbar = tk.Scrollbar(left_container, orient="vertical", command=canvas.yview)
scrollable_frame = tk.Frame(canvas, bg='#FFFFFF')
scrollable_frame.bind(
"",
lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
)
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
canvas.configure(yscrollcommand=scrollbar.set)
# 设置左面板背景
left_frame = tk.Frame(scrollable_frame, bg='#FFFFFF')
left_frame.pack(fill=tk.BOTH, expand=True, padx=(5, 0)) # 左移调整并减小宽度
# MAIN标题,整体变小
main_title = tk.Label(left_frame,
text="Main",
font=("Arial", 38, "bold"),
fg="black",
bg="#FAFAD2",
anchor='center') # 标题居中对齐
main_title.pack(side=tk.TOP, pady=(53, 30), fill=tk.X)
# Launch Vision 按钮
launch_button = tk.Button(left_frame, text="Launch Vision", command=self.launch_application,
bg="#F0F552",
fg="black",
width=18, # 修改按钮宽度为原来的一半
font=("Segoe UI", 20))
launch_button.pack(pady=(10, 50), anchor='w', padx=30) # 左对齐并减小间距
# Start 按钮
start_button = tk.Button(left_frame, text="Start", command=self.start_auto_command,
bg="#32CD32",
fg="white",
width=18, # 修改按钮宽度为原来的一半
font=("Segoe UI", 20))
start_button.pack(pady=(0, 30), anchor='w', padx=30) # 左对齐并减小间距
###新增空白区域
# 空白区域
blank_frame = tk.Frame(left_frame, bg='#FFFFFF', height=10) # 高度为10像素
blank_frame.pack(fill=tk.X, pady=256) # 填充整个宽度并增加间距
# 水平按钮行框架(新增)
button_row_frame = tk.Frame(left_frame, bg='#FFFFFF')
button_row_frame.pack(pady=10, anchor='w', padx=5) # 整体间距
# 3D 按钮(修改父容器为 button_row_frame)
animation_button = tk.Button(button_row_frame, text="3D", command=self.show_animation,
bg="#00B0F0",
fg="white",
width=8, # 修改按钮宽度为原来的一半
font=("Segoe UI", 12))
animation_button.pack(side=tk.LEFT, padx=5) # 水平排列
# His Chart 按钮(修改父容器为 button_row_frame)
chart_button = tk.Button(button_row_frame, text="His Chart", command=self.create_chart_area,
bg="#00B0F0",
fg="white",
width=8, # 修改按钮宽度为原来的一半
font=("Segoe UI", 12))
chart_button.pack(side=tk.LEFT, padx=5) # 水平排列
# Log 按钮(修改父容器为 button_row_frame)
new_window_button = tk.Button(button_row_frame, text="Log", command=self.show_new_window,
bg="#00B0F0",
fg="white",
width=8, # 修改按钮宽度为原来的一半
font=("Segoe UI", 12))
new_window_button.pack(side=tk.LEFT, padx=5) # 水平排列
# 连接按钮(Vision和Robot)
self._create_connection_buttons(left_frame, "Vision", self.connect_to_vision, self.disconnect_from_vision)
self._create_connection_buttons(left_frame, "Robot", self.connect_to_robot, self.disconnect_from_robot)
# 备用端口按钮(PLC、Falco、Robot)
PLC_button = tk.Button(left_frame, text="PLC Port (Backup)", command=self.start_PLC_command,
bg="#CDCDCD",
fg="gray",
font=("Segoe UI", 12))
PLC_button.pack(side=tk.BOTTOM, fill=tk.X)
Falco_button = tk.Button(left_frame, text="Falco Port (Backup)", command=self.start_Falco_command,
bg="#CDCDCD",
fg="gray",
font=("Segoe UI", 12))
Falco_button.pack(side=tk.BOTTOM, fill=tk.X)
Robot_button = tk.Button(left_frame, text="Robot Port (Backup)", command=self.start_Robot_command,
bg="#CDCDCD",
fg="gray",
font=("Segoe UI", 12))
Robot_button.pack(side=tk.BOTTOM, fill=tk.X)
canvas.pack(side="left", fill="both", expand=True)
# ---新---区域22
blank_frame = tk.Frame(left_frame, bg='#FFFFFF', height=10) # 高度为10像素
blank_frame.pack(fill=tk.X, pady=120) # 填充整个宽度并增加间距
# ---新---区域33
blank_frame = tk.Frame(left_frame, bg='#FFFFFF', height=10) # 高度为10像素
blank_frame.pack(fill=tk.X, pady=120) # 填充整个宽度并增加间距
# 修改滚动条初始状态为隐藏,并绑定鼠标事件
scrollbar.place(relx=1, rely=0, relheight=1, anchor='ne')
scrollbar.lower() # 初始隐藏
left_container.bind("", lambda _: scrollbar.lift()) # 鼠标进入时显示
left_container.bind("", lambda _: scrollbar.lower()) # 鼠标离开时隐藏
def on_exit(self):
"""处理窗口关闭事件"""
# 弹出确认对话框,确保在主线程中执行
if messagebox.askokcancel("退出", "确定要退出程序吗?", parent=self.root):
logging.info("用户确认退出程序,开始清理资源...")
try:
# 保存配置
self.save_settings()
logging.info("配置已自动保存")
# 断开与 Vision 的连接
if self.connected_to_vision:
self.disconnect_from_vision()
logging.info("已断开与 Vision 的连接")
# 断开与 Robot 的连接
if self.connected_to_robot:
self.disconnect_from_robot()
logging.info("已断开与 Robot 的连接")
# 终止子进程
if hasattr(self, 'app3_process') and self.app3_process:
self.terminate_application3()
logging.info("已终止子进程")
# 清理日志处理器
if hasattr(self, 'new_window_handler'):
logger = logging.getLogger()
logger.removeHandler(self.new_window_handler)
logging.info("已移除日志处理器")
except Exception as e:
logging.error(f"退出时发生错误: {str(e)}")
messagebox.showerror("错误", f"退出时发生错误: {str(e)}")
finally:
# 安全关闭主窗口
self.root.destroy()
logging.info("主窗口已关闭")
else:
logging.info("用户取消退出程序")
def show_new_window(self):
"""显示一个新的弹窗"""
new_window = tk.Toplevel(self.root)
new_window.title("Log")
# 设置窗口大小和位置(居中显示)
window_width = 800
window_height = 600
screen_width = new_window.winfo_screenwidth()
screen_height = new_window.winfo_screenheight()
x = (screen_width - window_width) // 2
y = (screen_height - window_height) // 2
new_window.geometry(f'{window_width}x{window_height}+{x}+{y}')
# 创建 Text 组件用于显示日志
self.new_window_text = tk.Text(new_window, wrap=tk.WORD, bg='black', fg='white', font=("Helvetica", 18))
self.new_window_text.pack(fill=tk.BOTH, expand=True)
close_button = tk.Button(new_window, text="Close", command=lambda: self.close_new_window(new_window), width=10)
close_button.pack(pady=10)
# 获取右侧日志区域的全部内容
log_content = self.log_text.get("1.0", tk.END).strip()
# 将日志内容插入到新窗口的 Text 组件中
if log_content:
self.new_window_text.insert(tk.END, log_content)
self.new_window_text.yview_moveto(1) # 滚动到最新位置
# 添加日志处理器
self.new_window_handler = TextHandler(self.new_window_text)
logger = logging.getLogger()
logger.addHandler(self.new_window_handler)
def close_new_window(self, window):
"""关闭新窗口并移除日志处理器"""
if hasattr(self, 'new_window_handler'):
logger = logging.getLogger()
logger.removeHandler(self.new_window_handler)
window.destroy()
def update_new_window_log(self, record):
"""更新新窗口中的日志内容"""
if hasattr(self, 'new_window_text') and self.new_window_text.winfo_exists():
msg = self.formatter.format(record)
self.new_window_text.insert(tk.END, msg + '\n')
self.new_window_text.yview_moveto(1)
def setup_logging(self):
text_handler = TextHandler(self.log_text)
logger = logging.getLogger()
logger.addHandler(text_handler)
# 添加新的处理程序以支持新窗口日志
if hasattr(self, 'new_window_text'):
new_window_handler = TextHandler(self.new_window_text)
logger.addHandler(new_window_handler)
def _create_connection_buttons(self, parent, label_text, connect_cmd, disconnect_cmd):
# 创建连接按钮框架
button_frame = tk.Frame(parent)
button_frame.pack(pady=5)
connect_button = tk.Button(button_frame, text=f"Con. {label_text}", command=connect_cmd, width=14, height=1)
connect_button.pack(side=tk.LEFT, anchor='center', padx=5)
status_indicator = tk.Frame(button_frame, width=20, height=20, bg='red')
setattr(self, f"{label_text.lower()}_status_indicator", status_indicator) # Store as attribute
status_indicator.pack(side=tk.LEFT, anchor='center', padx=(0, 5))
disconnect_button = tk.Button(button_frame, text=f"Dis. {label_text}", command=disconnect_cmd, width=14, height=1)
disconnect_button.pack(side=tk.LEFT, anchor='center', padx=5)
def create_middle_panel(self, parent):
# 中间主框架
middle_frame = tk.Frame(parent, bg='#FFFFFF') #OLD #CCCCCC
middle_frame.pack(fill=tk.BOTH, expand=True)
# 修改 create_right_panel 方法中的标题和区域标识
def create_right_panel(self, parent):
# 保存 right_frame 作为类属性,避免重复初始化
self.right_frame = tk.Frame(parent, bg='#FFFFFF')
self.right_frame.pack(fill=tk.BOTH, expand=True)
# 清除之前的 image_title(如果存在)
if hasattr(self, 'image_title') and self.image_title:
self.image_title.destroy()
# 图片标题
self.image_title = tk.Label(self.right_frame,
text="Picture",
font=("Arial", 38, "bold"),
fg="black",
bg="#FAFAD2",
anchor='center')
self.image_title.pack(pady=(15, 30), fill=tk.X)
# 创建图片显示区域
self.image_label = tk.Label(self.right_frame, bg='white')
self.image_label.pack(fill=tk.BOTH, expand=True, padx=328, pady=10) #PosTimTimTim
# 加载图片
self.load_images()
# 确保 image_index 初始化
if not hasattr(self, 'image_index'):
logging.warning("image_index 未初始化,正在修复...")
self.image_index = 0
# 开始更新图片
self.root.after(333, self.update_image) # 使用 after 安排首次更新
def update_image(self):
# 检查图片列表是否存在且非空
if not hasattr(self, 'images') or not self.images:
logging.warning("Ini...")
self.root.after(333, self.update_image)
return
# 检查 image_label 是否初始化
if not hasattr(self, 'image_label') or self.image_label is None:
logging.error("Picture Ini...---")
# 使用保存的 right_frame 重新初始化
if hasattr(self, 'right_frame'):
self.create_right_panel(self.right_frame)
else:
logging.error("无法找到 right_frame,无法重新初始化 image_label")
self.root.after(333, self.update_image) # 避免直接递归调用
return
try:
img = self.images[self.image_index]
self.image_label.config(image=img)
self.image_label.image = img
logging.debug(f"成功更新图片索引 {self.image_index}")
except Exception as e:
try:
logging.error(f"更新图片失败: {str(e)}")
except RecursionError:
pass # 避免日志记录引发递归错误
self.root.after(333, self.update_image) # 避免直接递归调用
return
# 更新索引并触发下一次更新
self.image_index = (self.image_index + 1) % len(self.images)
self.root.after(333, self.update_image) # 使用 after 安排下一次更新
def load_default_image111(self):
"""加载默认图片到右侧显示区域"""
image_folder = r'C:\Log\Picture' # 默认图片文件夹路径
if not os.path.exists(image_folder):
logging.warning(f"图片文件夹路径不存在: {image_folder}")
return
images = []
for file in os.listdir(image_folder):
if file.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp', '.gif')):
img_path = os.path.join(image_folder, file)
try:
img = Image.open(img_path)
img.thumbnail((800, 600)) # 自适应缩放
images.append(ImageTk.PhotoImage(img))
except Exception as e:
#logging.error(f"无法加载图片 {img_path}: {str(e)}")
logging.error(f"Loading Picture NG... {img_path}: {str(e)}")
if images:
if self.image_label: # 确保 image_label 存在
self.image_label.config(image=images[0]) # 显示第一张图片
self.image_label.image = images[0]
#logging.info(f"成功加载图片: {len(images)} 张")
logging.info(f"Read: {len(images)} Pictures")
else:
logging.warning("未找到有效图片文件")
def create_bottom_panel(self, parent):
# 修改后的偏移量输入和写入按钮布局
offset_frame = tk.Frame(parent, bg='lightgray')
offset_frame.pack(fill=tk.X, pady=5, padx=5)
# X输入
tk.Label(offset_frame, text="X:", bg='lightgray', font=("Helvetica", 12)).grid(row=0, column=0, padx=2)
self.custom_command_entry5 = tk.Entry(offset_frame, width=8, font=("Helvetica", 12))
self.custom_command_entry5.grid(row=0, column=1, padx=2)
# Y输入
tk.Label(offset_frame, text="Y:", bg='lightgray', font=("Helvetica", 12)).grid(row=0, column=2, padx=2)
self.custom_command_entry6 = tk.Entry(offset_frame, width=8, font=("Helvetica", 12))
self.custom_command_entry6.grid(row=0, column=3, padx=2)
# U输入
tk.Label(offset_frame, text="U:", bg='lightgray', font=("Helvetica", 12)).grid(row=0, column=4, padx=2)
self.custom_command_entry7 = tk.Entry(offset_frame, width=8, font=("Helvetica", 12))
self.custom_command_entry7.grid(row=0, column=5, padx=2)
# 统一的写入按钮 ###Tim
write_button = tk.Button(offset_frame, text="Offset_Write", command=self.write_all_offsets,
bg="#32CD32",
fg="white",
width=12,
font=("Segoe UI", 12))
write_button.grid(row=0, column=6, padx=10)
#Enter 1 command
custom_command_frame = tk.Frame(parent)
custom_command_frame.pack(side=tk.TOP, pady=1, fill=tk.X, expand=True)
custom_command_label = tk.Label(custom_command_frame, text="Enter Vision Command:", font=("Helvetica", 1))
custom_command_label.pack(side=tk.LEFT, padx=5)
self.custom_command_entry1 = tk.Entry(custom_command_frame, font=("Helvetica", 1), fg="purple")
self.custom_command_entry1.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
send_command_button = tk.Button(custom_command_frame, text="Send", command=self.send_custom_command1, font=("Helvetica", 1))
send_command_button.pack(side=tk.LEFT, padx=5)
# 新增日志显示区域
log_frame = tk.Frame(parent, bg='black')
log_frame.pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
# 调整日志区域高度为原来的一半
self.log_text = tk.Text(log_frame, wrap=tk.WORD, bg='black', fg='white', font=("Helvetica", 12), height=10)
self.log_text.pack(fill=tk.BOTH, expand=True)
#Enter 2 command
custom_command_frame2 = tk.Frame(parent)
custom_command_frame2.pack(side=tk.TOP, pady=1, fill=tk.X, expand=True)
custom_command_label = tk.Label(custom_command_frame2, text="Enter Robot Command:", font=("Helvetica", 1))
custom_command_label.pack(side=tk.LEFT, padx=5)
self.custom_command_entry2 = tk.Entry(custom_command_frame2, font=("Helvetica", 1), fg="purple")
self.custom_command_entry2.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
send_command_button2 = tk.Button(custom_command_frame2, text="Send", command=self.send_custom_command2, font=("Helvetica", 1))
send_command_button2.pack(side=tk.LEFT, padx=5)
#Enter 3 command
custom_command_frame3= tk.Frame(parent)
custom_command_frame3.pack(side=tk.TOP, pady=1, fill=tk.X, expand=True)
custom_command_label = tk.Label(custom_command_frame3, text="Enter Send To Vision Command:", font=("Helvetica", 1))
custom_command_label.pack(side=tk.LEFT, padx=5)
self.custom_command_entry3 = tk.Entry(custom_command_frame3, font=("Helvetica", 1), fg="purple")
self.custom_command_entry3.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
send_command_button3 = tk.Button(custom_command_frame3, text="Send", command=self.send_custom_command3, font=("Helvetica", 1))
send_command_button3.pack(side=tk.LEFT, padx=5)
# 移除发送按钮并绑定 Enter 键事件到输入框
self.custom_command_entry3.bind('', lambda event: self.send_custom_command3())
def _validate_number(self, value):
"""数值输入验证"""
if value == "" or value == "-":
return True
try:
float(value)
return True
except ValueError:
return False
def setup_logging(self):
text_handler = TextHandler(self.log_text)
logger = logging.getLogger()
logger.addHandler(text_handler)
def connect_to_vision(self):
try:
self.vision_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.vision_client_socket.settimeout(65536)
self.vision_client_socket.connect((self.vision_ip, self.vision_port))
self.connected_to_vision = True
self.update_status_indicator(self.vision_status_indicator, 'green', "Connected to Vision")
logging.info(f"Connected to Vision at {self.vision_ip}:{self.vision_port}")
threading.Thread(target=self.receive_data, args=(self.vision_client_socket, 'vision'), daemon=True).start()
except Exception as e:
self.connected_to_vision = False
self.update_status_indicator(self.vision_status_indicator, 'red', f"Failed to connect to Vision: {e}")
logging.error(f"Failed to connect to Vision: {e}")
if self.vision_client_socket:
self.vision_client_socket.close()
def disconnect_from_vision(self):
if self.connected_to_vision:
self.vision_client_socket.close()
self.connected_to_vision = False
self.update_status_indicator(self.vision_status_indicator, 'red', "Disconnected from Vision")
logging.info("Disconnected from Vision")
##OutofRang
def Out_Of_Range_from_vision(self):
self.update_status_indicator2(self.vision_status_indicator, 'red', "Out_Of_Range_±10°")
logging.info("Out_Of_Range_from_vision_±10°")
def Out_Of_Range_from_vision2(self):
self.update_status_indicator2(self.vision_status_indicator, 'red', "Out_Of_Range_±90°")
logging.info("Out_Of_Range_from_vision_±90°")
##OutofRang
##Robot at Home
def Home_POS(self):
self.update_status_indicator2(self.vision_status_indicator, 'red', "Not Match,Pls Check and Put it Again,\n Then Connect Vision Again ")
logging.info("Not Match,Pls Check and Put it Again ...")
##Robot at Home
def ERROR_(self):
self.update_status_indicator2(self.robot_status_indicator, 'red', "ERROR,PLS Connect Robot\n\n Then, In Robot Software, Press Start to Run...")
logging.info("ERROR,PLS Connect Robot")
def Motor_Off(self):
self.update_status_indicator2(self.robot_status_indicator, 'red', " Area Semnsor \n\n Area Semnsor \n\nArea Semnsor \n\nThen, In Robot Software, Press Start to Run...")
logging.info("ERROR,Area Semnsor")
def connect_to_robot(self):
try:
self.robot_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.robot_client_socket.settimeout(65536)
self.robot_client_socket.connect((self.robot_ip, self.robot_port))
self.connected_to_robot = True
self.update_status_indicator(self.robot_status_indicator, 'green', "Connected to Robot")
logging.info(f"Connected to Robot at {self.robot_ip}:{self.robot_port}")
threading.Thread(target=self.receive_data, args=(self.robot_client_socket, 'robot'), daemon=True).start()
except Exception as e:
self.connected_to_robot = False
self.update_status_indicator(self.robot_status_indicator, 'red', f"Failed to connect to Robot: {e}")
logging.error(f"Failed to connect to Robot: {e}")
if self.robot_client_socket:
self.robot_client_socket.close()
def disconnect_from_robot(self):
if self.connected_to_robot:
self.robot_client_socket.close()
self.connected_to_robot = False
self.update_status_indicator(self.robot_status_indicator, 'red', "Disconnected from Robot")
logging.info("Disconnected from Robot")
def send_custom_command1(self):
command = self.custom_command_entry1.get()
if command:
logging.info(f"Send_Vision_Command2Start: {command}")
self.send_vision_command(command)
# 更新图片逻辑
self.load_images() # 重新加载图片
self.update_image() # 更新图片显示
def send_custom_command2(self):
command = self.custom_command_entry2.get()
if command:
logging.info(f"send_robot_command: {command}")
self.send_robot_command(command)
#self.custom_command_entry.delete(0, tk.END)
def send_custom_command3(self):
global Response # 使用全局变量
if Response == 'Camera_not_Match_Picture' :
##print("666",Response)
time.sleep(0.005)
else:
#global Response # 使用全局变量
#command = self.custom_command_entry2.get()
command = str(Response) # 获取全局变量 RES 的值作为命令内容
if command:
logging.info(f"Recive_Vision/Robot_Data_is_{command}")
logging.info(f"Then_Auto_send_Vision_Pos2robot")
self.send_robot_command(command)
#self.custom_command_entry.delete(0, tk.END)
##
def send_custom_command6_Offset(self):
command = self.custom_command_entry5.get()
if command:
logging.info(f"send_robot_command_X_Offset: {command}")
self.send_robot_command_Offset(command)
#self.custom_command_entry.delete(0, tk.END)
command = self.custom_command_entry6.get()
if command:
logging.info(f"send_robot_command_Y_Offset: {command}")
self.send_robot_command_Offset(command)
#self.custom_command_entry.delete(0, tk.END)
command = self.custom_command_entry7.get()
if command:
logging.info(f"send_robot_command_Z_Offset: {command}")
self.send_robot_command_Offset(command)
#self.custom_command_entry.delete(0, tk.END)
def send_x_offset(self):
self._send_offset("X", self.custom_command_entry5.get())
def send_y_offset(self):
self._send_offset("Y", self.custom_command_entry6.get())
def send_u_offset(self):
self._send_offset("U", self.custom_command_entry7.get())
def _send_offset(self, axis_type, value):
if not value:
return
try:
# 数值有效性验证
float(value)
except ValueError:
messagebox.showerror("Error", "Pls Inpout Number")
#messagebox.showerror("输入错误", "请输入有效的数字")
return
if self.connected_to_robot:
try:
cmd_template = {
"X": "Tim{}Tim0Tim0TimOKTim666666\r\n",
"Y": "Tim0Tim{}Tim0TimOKTim666666\r\n",
"U": "Tim0Tim0Tim{}TimOKTim666666\r\n"
}
command = cmd_template[axis_type].format(value)
self.robot_client_socket.sendall(command.encode('utf-8'))
logging.info(f"Sent {axis_type}_Offset: {command.strip()}")
except Exception as e:
#logging.error(f"发送{axis_type}偏移失败: {str(e)}")
#self.update_status_indicator2(self.robot_status
logging.error(f"Sent {axis_type}Fail,Message is: {str(e)}")
self.update_status_indicator2(self.robot_status_indicator, 'red', f"Sent Fail: {str(e)}")
else:
messagebox.showwarning("Connect Error", "Can not Connected Robot")
def receive_data(self, client_socket, source):
global Response # 使用全局变量
while client_socket and client_socket.fileno() >= 0:
try:
data = client_socket.recv(1024).decode('utf-8')
Response=data
##print (Response)
if not data:
break
# 加载图片
# self.load_images()
# 启动图片更新定时器
# self.update_image()
current_time = datetime.now().strftime("%H:%M:%S")
##print(current_time)
log_entry = f"[{current_time}] {data}\n"
# Append to log file
with open(r"c:\Log\log_His.txt", "a") as log_file:
log_file.write(log_entry)
# Append to log file
with open(r"c:\Log\log_His_BK.txt", "a") as log_file:
log_file.write(log_entry)
# Update the appropriate text widget
if source == 'vision':
data66=data
#print(data66)
if data66 == 'Out_Of_Range_CW10_CCW10Out_Of_Range_CW90_CCW90' or data66 == 'Out_Of_Range_CW10_CCW10' : #Out_Of_Range_CW10_CCW10
#self.disconnect_from_vision()
#print("111")
self.Out_Of_Range_from_vision()
#print("---111")
if data66 == 'Out_Of_Range_CW90_CCW90':
#self.disconnect_from_vision()
self.Out_Of_Range_from_vision2()
if data66 == 'Camera_not_Match_Picture' :
#self.disconnect_from_vision()
##print("666",data66)
#self.Home_POS()
self.root.after(200, lambda: self.Home_POS())
#print("11111111111")
# 解析数据并记录需格式调整 Chart 17:11:35 Tim-692.003Tim233.098Tim-177.533TimOKTim88888888
x_val = float(data66.split('Tim')[1].split('Tim')[0])
#print("22222222222")
y_val = float(data.split('Tim')[2])
#print("333")
u_val = float(data.split('Tim')[3])
#print("555")
#print(x_val)
#print(x_val,y_val,u_val)
self.history_data['X'].append(x_val)
self.history_data['Y'].append(y_val)
self.history_data['U'].append(u_val)
self.history_data['timestamps'].append(time.time())
## self.vision_data_text.insert(tk.END, f"\n«Vision» -Raw data1- \n\n{current_time} {data}\n")
#Response=data
#print (Response)
time.sleep(0.01)
## self.vision_data_text.yview_moveto(1)
data2=data #data = "-801.226XX218.608YY-13.962YY"
x_value = data2.split('X')[0].strip() #将字符串按 X 分割,取第一个部分,即 -801.226,并去除可能的前后空白字符。
start_y = data2.rfind('-')
y_valueLS = data2[start_y:]
y_value = y_valueLS[:-2]
## self.vision_char_text.insert(tk.END, f"\n«Vision» -Split data2- \n\n{current_time} Received: {x_val} {y_val} {u_val} \n")
#self.vision_char_text.insert(tk.END, f"\n«Vision» -Split data- \n\n{current_time} x:{x_value} y:{y_value} \n")
## self.vision_char_text.yview_moveto(1)
parts = data.split('Tim')
if len(parts) >= 4: # Ensure we have X, Y, U values
x_val = float(parts[1])
y_val = float(parts[2])
u_val = float(parts[3])
self.history_data['X'].append(x_val)
self.history_data['Y'].append(y_val)
self.history_data['U'].append(u_val)
self.history_data['timestamps'].append(time.time())
elif source == 'robot':
data666666 = str(Response).strip() # 去除前后空白
Real_Data=repr(Response)
##print("111 repr Real Data:", repr(Response)) # 显示原始字符串
#data666666=data
#data666666 = str(Response)
#print("111",Response)
#print("222",data666666)
if data666666 == 'Shot' or data666666 == 'Shot2':
#self.disconnect_from_vision()
#print("333",data666666)
#self.Home_POS()
self.root.after(200, lambda: self.Ali_Comand())
if data666666 == 'ERROR_' :
#self.disconnect_from_vision()
#print("333",data666666)
#self.Home_POS()
self.root.after(200, lambda: self.ERROR_())
if data666666 == 'Motor_Off' :
self.root.after(200, lambda: self.Motor_Off())
# 在接收数据时检查Home信号
if 'Home1' in data:
self.home_received = True
self.start_button.config(state=tk.NORMAL)
logging.info("Home position received - Start enabled")
elif 'NotHome' in data:
self.home_received = False
self.start_button.config(state=tk.DISABLED)
logging.info("Not in Home position - Start disabled")
## self.robot_data_text.insert(tk.END, f"\n«Robot_data1»\n{current_time} {data} Real_Data is {Real_Data}\n")
## self.robot_data_text.yview_moveto(1)
## self.robot_char_text.insert(tk.END, f"\n«Robot_data2»\n{current_time} {data} Data is {data666666}\n")
## self.robot_char_text.yview_moveto(1)
# Log the data to the log area
## self.log_text.insert(tk.END, log_entry)
## self.log_text.yview_moveto(1)
# 自动发送接收到的数据作为命令
self.send_custom_command3()
except Exception as e:
logging.error(f"Error receiving data: {e}")
logging.error(f"Data parsing error: {str(e)}")
break
if client_socket == self.vision_client_socket:
self.disconnect_from_vision()
elif client_socket == self.robot_client_socket:
self.disconnect_from_robot()
def send_custom_command(self, command=None):
global RES # 使用全局变量
# 如果没有提供命令,则使用全局变量 RES 的值
if command is None:
command = Response
if command:
logging.info(f"Auto_Custom command entered: {command}")
self.send_robot_command3(command)
self.custom_command_entry3.delete(0, tk.END)
def send_vision_command(self, command): #vision
if self.connect_to_vision and self.vision_client_socket:
try:
self.vision_client_socket.sendall(command.encode('utf-8'))
## logging.info(f"Command vision sent to vision: {command}")
except Exception as e:
logging.error(f"Failed to send command to vision: {e}")
def send_robot_command_Area_Sensor(self, command):
if self.connected_to_robot and self.robot_client_socket:
command345="Motor_Off"
try:
self.robot_client_socket.sendall(command345.encode('utf-8'))
# logging.info(f"Command sent to Robot: {command345.strip()}")
print("55555555555")
except Exception as e:
logging.error(f"Failed to send command to Robot: {e}")
def send_robot_command(self, command):
global Offset_X, Offset_Y, Offset_U
ABCDEFG=0
if self.connected_to_robot and self.robot_client_socket:
try:
# 解析原始命令并应用偏移量
parts = command.split('Tim')
if len(parts) >= 4:
x = float(parts[1]) + (Offset_X if Offset_X else 0)
y = float(parts[2]) + (Offset_Y if Offset_Y else 0)
u = float(parts[3]) + (Offset_U if Offset_U else 0)
command = f"Tim{x}Tim{y}Tim{u}TimOKTim666666\r\n"
# 分开记录日志
logging.info(f"Applied offsets - X: {Offset_X}, Y: {Offset_Y}, U: {Offset_U}")
self.robot_client_socket.sendall(command.encode('utf-8'))
logging.info(f"1、Send_Vision_Pos2robot 2、Robot_X_Y_U_Move_Data 3、 From_robot_command: {command.strip()}")
except Exception as e:
logging.error(f"Failed to send command to Robot: {e}")
##Offset
def send_robot_command_Offset(self, command):
if self.connect_to_vision and self.robot_client_socket:
try: #Tim-495.047Tim86.1133Tim-0.284364TimOKTim88888888 "Tim"(command)TimcommandTimcommandTimOKTim88888888"
send_robot_command_Offset=("Tim"+(command)+"Tim"+(command)+"Tim"+(command)+"Tim"+"OK"+"Tim"+"88888888"+"\r\n")
##print(send_robot_command_Offset)
send_robot_command_Offset66=((command)+"\r\n")
self.robot_client_socket.sendall(send_robot_command_Offset66.encode('utf-8'))
logging.info(f"Command robot sent to Robot66: {command}")
except Exception as e:
logging.error(f"Failed to send command to Robot: {e}")
##Offset
def launch_application(self):
#Demo app_path = r"C:\Users\ShineTek\Desktop\V1\Public_Release\v1.exe"
app_path = r"C:\Log\V5\Public_Release\V5.exe"
#app_path = r"C:\Study\Case\V5\Public_Release\V5.exe"
try:
subprocess.Popen(app_path)
logging.info("Launched application successfully.")
except Exception as e:
messagebox.showerror("Error", f"Failed to launch application: {e}")
logging.error(f"Failed to launch application: {e}")
def launch_application3(self):
app_path = r"C:\Users\ShineTek\AppData\Local\Programs\Python\Python37\Python.exe E:\Tim_Study\Python_Code\Ali_Show_Picture666.py"
#app_path = r"C:\Users\ShineTek\Desktop\大视野\V1_Big_OK_250219_AddCode\Ali_Show_Picture666.exe"
#app_path = r"C:\Users\ShineTek\AppData\Local\Programs\Python\Python37\Python.exe C:\Log\Ali_Show_Picture666.py"
### app_path = r"C:\Users\ShineTek\AppData\Local\Programs\Python\Python37\Python.exe E:\EpsonRC70\Projects\V999_1Cycle_\Show_Picture222.py"
try:
# 启动新进程并保存引用
self.app3_process = subprocess.Popen(app_path)
logging.info("Launched application successfully3.")
except Exception as e:
messagebox.showerror("Error", f"Failed to launch application3: {e}")
logging.error(f"Failed to launch application3: {e}")
def terminate_application3(self):
if self.app3_process and self.app3_process.poll() is None:
# 尝试终止进程
try:
self.app3_process.terminate()
self.app3_process.wait()
logging.info("Terminated application3 successfully.")
except Exception as e:
logging.error(f"Failed to terminate application3: {e}")
self.app3_process = None # 重置进程引用
def update_status_indicator(self, indicator, color, message):
indicator.config(bg=color)
self.root.update_idletasks()
messagebox.showinfo("Status", message)
def update_status_indicator2(self, indicator, color, message):
indicator.config(bg=color)
self.root.update_idletasks()
messagebox.showinfo("Waring", message)
##Tim
def update_status_indicator6(self, indicator, color, message):
indicator.config(bg=color)
self.root.update_idletasks()
messagebox.showinfo("ERROR", message)
self.update_status_indicator(self._status_indicator6, 'green', "Center")
self.update_status_indicator(self._status_indicator6, 'red', f"not Center")
def Auto_send(self):
# 等待3秒,以便用户将焦点切换到目标输入框
time.sleep(3)
# 在指定位置输入XXX
x1, y1 = map(int, input("请输入要输入XXX的位置坐标(以空格分隔,例如:100 200):").split())
pyautogui.click(x1, y1)
pyautogui.typewrite('XXX')
# 在指定位置输入YYY
x2, y2 = map(int, input("请输入要输入YYY的位置坐标(以空格分隔,例如:300 400):").split())
pyautogui.click(x2, y2)
pyautogui.typewrite('YYY')
# 找到send按钮的位置(这里假设已经知道send按钮的位置,假设为x_send, y_send)
x_send, y_send = map(int, input("请输入send按钮的位置坐标(以空格分隔,例如:500 600):").split())
# 点击send按钮
pyautogui.click(x_send, y_send)
time.sleep(0.5)
pyautogui.click(x_send, y_send)
def start_auto_command(self):
if self.connect_to_vision and self.vision_client_socket:
#self.connect_to_vision()
#self.connect_to_robot()
#self.root.after(200, lambda: self.connect_to_vision())
print("1111111111111")
#time.sleep(100)
self.custom_command_entry1.delete(0, tk.END)
self.custom_command_entry1.insert(0, "1st_Camera")
self.send_custom_command1()
# 先终止可能正在运行的进程
self.terminate_application3()
# 再启动新进程
self.root.after(200, lambda: self.launch_application3())
def Recive_PLC_start_command(self): #PC Start yeshi zouzheli
##print(Response)
data_Tim = str(Response).strip() # 去除前后空白
if data_Tim=="1NO_Home_Pos":
#if not data_Tim=="Home_Pos":
time.sleep(0.005)
self.root.after(200, lambda: self.Home_POS())
else:
if self.connect_to_vision and self.vision_client_socket:
#self.connect_to_vision()
#self.connect_to_robot()
#self.root.after(200, lambda: self.connect_to_vision())
#print("2222222222")
#time.sleep(100)
self.custom_command_entry1.delete(0, tk.END)
self.custom_command_entry1.insert(0, "1st_Camera")
self.send_custom_command1()
# 先终止可能正在运行的进程
self.terminate_application3()
# 再启动新进程
##self.root.after(200, lambda: self.launch_application3())
# 更新图片逻辑
self.root.after(5000, lambda: self.load_images())
self.root.after(500, lambda: self.update_image())
self.load_images() # 重新加载图片
self.update_image() # 更新图片显示
#self.root.after(200, lambda: self.Ali_Comand())
def Ali_Comand(self):
self.custom_command_entry1.delete(0, tk.END)
self.custom_command_entry1.insert(0, "2nd_Camera")
self.send_custom_command1()
# 先终止可能正在运行的进程
#self.terminate_application3()
# 再启动新进程
###self.root.after(200, lambda: self.launch_application3())
def continue_auto_command(self):
self.custom_command_entry1.delete(0, tk.END)
self.custom_command_entry1.insert(0, "YYY")
self.send_custom_command1()
self.root.after(200, lambda: self.continue_auto_command_U())
def continue_auto_command_U(self):
self.custom_command_entry1.delete(0, tk.END)
self.custom_command_entry1.insert(0, "UUU")
self.send_custom_command1()
def init_plc_connection(self):
"""增强型工业连接协议"""
try:
self.plc = MelsecMcNet("192.168.0.11", 1028)
conn = self.plc.ConnectServer()
if conn.IsSuccess:
#self.status_bar.config(text="PLC已连接 | 协议版本6.2", fg="green")
logging.info(f"Connected to PLC at IP:192.168.0.11 Port:1028 ")
else:
#self.status_bar.config(text=f"连接失败: {conn.Message}", fg="red")
logging.info(f"PLC Connect NG at [{datetime.now().strftime('%H:%M:%S')}]")
self.plc = None
except Exception as e:
#self.status_bar.config(text=f"初始化异常: {str(e)}", fg="orange")
logging.info(f"PLC Connect NG at [{datetime.now().strftime('%H:%M:%S')}]")
def setup_plc(self):
# PLC连接配置
self.plc = MelsecMcNet("192.168.0.11", 1028)
connect_result = self.plc.ConnectServer()
if not connect_result.IsSuccess:
print("PLC Connect NG:", connect_result.Message)
self.plc = None
def start_plc_monitoring(self):
"""智能重连监控系统"""
if self.plc and self._check_connection():
self._monitor_y79()
else:
self.parent.after(2000, self.start_plc_monitoring)
def _monitor_y79(self):
"""修正地址并增强监测"""
try:
# 使用八进制地址Y117(十进制79)
#read_result = self.plc.ReadBool("Y79")
read_result = self.plc.ReadBool("L801")
read_result3 = self.plc.ReadBool("X2F")
#self._log(f"Y79读取结果: 成功={read_result.IsSuccess} 状态={read_result.Content}")
#logging.info(f"Y79读取结果: 成功={read_result.IsSuccess} 状态={read_result.Content}")
#logging.info(f"成功读取到Y79状态:{read_result.Content}")
#logging.info(f"[{datetime.now().strftime('%H:%M:%S')}],Recive PLC Y79 Status is:{read_result.IsSuccess}")
Time_Tim=datetime.now().strftime('%H:%M:%S')
if read_result.Content is False:
print("Content is False")
#logging.info(f"[{datetime.now().strftime('%H:%M:%S')}],PLC No Command")
if read_result.Content is True:
time.sleep(0.005)
#print("Content is True")
#logging.info(f"[{Time_Tim}] Content is True")
#log_entry = f"[{Time_Tim}] Content is True\n"
#logging.info(f"[{datetime.now().strftime('%H:%M:%S')}],Recive PLC Start Command")
if read_result.IsSuccess:
current_state = read_result.Content
# 精确的上升沿检测
if current_state and not self.last_y79_state:
#self._log("检测到Y79上升沿,触发自动命令")
logging.info(f"Check PLC Start Command,UI Start")
#self.start_auto_command
#self.Recive_PLC_start_command
self.start_auto_command() ###Tim Modify
self.last_y79_state = current_state
if read_result3.Content is False:
time.sleep(0.00001)
# print("Content3 is False,Area Sensor On")
# global Ares_Sensor # 使用全局变量
# Ares_Sensor = 1
# print(Ares_Sensor)
if read_result3.Content is True:
time.sleep(0.005)
#print("222Content3 is False,Area Sensor On")
# if read_result3.IsSuccess:
# print("333Content3 is False,Area Sensor On")
# current_state3 = read_result.Content3
# # 精确的上升沿检测
# if current_state3 and not self.last_X2F_state:
# #self._log("检测到Y79上升沿,触发自动命令")
# logging.info(f"Check PLC Area Sensor Command,UI Start")
# print("444Content3 is False,Area Sensor On")
# self.send_robot_command_Area_Sensor() ########
# self.last_X2F_state = current_state3
else:
#self._log(f"通信失败: {read_result.Message}")
# logging.info(f"Recived PLC Area Sensor ...")
# print("Content PLC OK ,Area Sensor is On")
# SERVER_IP = "192.168.0.150" #192.168.0.1
# SERVER_PORT = 5670
# 创建TCP服务器
# server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# server.bind((SERVER_IP, SERVER_PORT))
# server.listen(1)
# print(f"Server OK,Waiting Robot Connect...")
# 接受EPSON控制器连接
# conn, addr = server.accept()
# print(f"Robot Connected: {addr}")
global Ares_Sensor # 使用全局变量
Ares_Sensor = 0 ##3Area Sensor On 1 off 0
if Ares_Sensor == 1:
#print(Ares_Sensor)
try:
# 创建TCP服务器
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定IP和端口
server.bind((SERVER_IP, SERVER_PORT))
# 开始监听,最大连接数为1
server.listen(1)
print(f"Server OK,Waiting Robot Connect...")
# 接受客户端连接
conn, addr = server.accept()
print(f"Robot Connected: {addr}")
# 使用全局变量
Ares_Sensor = 1
if Ares_Sensor == 1:
print(Ares_Sensor)
# 定义命令列表
commands222 = [
"STOP", # 紧急停止
"PAUSE", # 暂停运行
"RESUME", # 恢复运行
"STATUS", # 请求状态反馈
"RESET" # 复位错误
]
commands3333 = [
"STOP" ,1 # 紧急停止
]
# 要发送的命令列表
#commands = ["STOP", "PAUSE", "RESUME"]
commands = ["PAUSE"]
index = 0
#while True:
for aaaa in range(1):
# 获取当前要发送的命令
cmd = commands[index % len(commands)] + "\n"
try:
# 发送命令
conn.sendall(cmd.encode('utf-8')) # t66=((cmd)+"\r\n")
#conn.sendall((cmd)+"\n".encode())
#conn.sendall((cmd)+"\r\n".encode('utf-8'))
print(f"[{time.strftime('%H:%M:%S')}] Send OK。。。。。。 {cmd}")
except socket.error as e:
print(f"Send error: {e}")
break
index += 1
aaaa+=1
print(aaaa)
# 暂停一段时间
time.sleep(0.0001) # 修复括号未关闭的问题
except socket.error as e:
print(f"Socket error: {e}")
finally:
# 关闭服务器和连接
if 'server' in locals():
server.close()
if 'conn' in locals():
conn.close()
time.sleep(0.0001)
except Exception as e:
#self._log(f"监测异常: {str(e)}")
logging.info(f"Error to PLC,Message is : {str(e)}")
finally:
self.parent.after(333, self._monitor_y79)
def _check_connection(self):
"""工业级连接状态验证"""
try:
return self.plc.ConnectServer().IsSuccess
except:
return False
def start_auto_command(self):
"""修正后的自动控制流程,确保仅运行一次"""
logging.info("Start button triggered, running command sequence...")
time.sleep(0.00006)
# 确保仅执行一次流程
if not hasattr(self, '_is_running') or not self._is_running:
self._is_running = True
try:
self.Recive_PLC_start_command() # 执行主流程
finally:
self._is_running = False
def _safe_write(self, address, value, data_type):
"""通用安全写入模板"""
try:
if data_type == 'float':
result = self.plc.WriteFloat(address, value)
elif data_type == 'int32':
result = self.plc.WriteInt32(address, value)
elif data_type == 'bool':
result = self.plc.Write(address, [value])
if not result.IsSuccess:
print(f"Write {address} NG: {result.Message}")
except Exception as e:
print(f"Write NG,Message is : {str(e)}")
def check_y79_status(self):
try:
if self.plc:
# 读取Y79状态(注意地址格式需要根据实际PLC配置调整)
read_result = self.plc.ReadBool("Y79")
if read_result.IsSuccess and read_result.Content:
self.start_auto_command()
finally:
# 持续监控
self.parent.after(500, self.check_y79_status)
def start_Robot_command(self):
"""2025版自动控制流程""" #StartTim1Tim000Tim111Tim222Tim888Tim
##print("Running Command ...")
time.sleep (0.00006)
app_path = r"C:\Users\ShineTek\AppData\Local\Programs\Python\Python37\Python.exe E:\Tim_Study\Python_Code\V5_20250312_Robot_Client_UI_Control.py"
try:
# 启动新进程并保存引用
self.app3_process = subprocess.Popen(app_path)
logging.info("Launched start_Robot_command application successfully.")
except Exception as e:
messagebox.showerror("Error", f"Failed to launch start_Robot_command application: {e}")
logging.error(f"Failed to launch start_Robot_command application: {e}")
def start_Falco_command(self):
"""2025版自动控制流程"""
##print("Running Command ...")
time.sleep (0.00006)
#self.Recive_PLC_start_command() ###Tim Modify
# 保持原有写入逻辑
#self._safe_write("D390", 7777.888, 'float')
#self._safe_write("D397", 55, 'int32')
#self._safe_write("M260", True, 'bool')
def start_PLC_command(self):
"""2025版自动控制流程"""
##print("Running PLC Command ...")
app_path = r"C:\Users\ShineTek\AppData\Local\Programs\Python\Python37\Python.exe E:\Tim_Study\Python_Code\V6_PLC_BaseOn_Ali_Show_Picture666.py"
try:
# 启动新进程并保存引用
self.app3_process = subprocess.Popen(app_path)
logging.info("Launched start_PLC_command application successfully.")
except Exception as e:
messagebox.showerror("Error", f"Failed to launch start_PLC_command application: {e}")
logging.error(f"Failed to launch start_PLC_command application: {e}")
def save_settings(self):
"""增强型配置保存方法"""
config = {
'version': 1.0,
'offsets': {
'x': self.custom_command_entry5.get(),
'y': self.custom_command_entry6.get(),
'u': self.custom_command_entry7.get()
}
}
try:
# 确保目录存在
os.makedirs(os.path.dirname(self.CONFIG_PATH), exist_ok=True)
with open(self.CONFIG_PATH, 'w') as f:
json.dump(config, f, indent=2)
#logging.info("配置保存成功")
logging.info("Config Save")
except Exception as e:
logging.error(f"Save Config FAil,Message is: {str(e)}")
messagebox.showerror("Error", f"Can not Save Config:\n{str(e)}")
#logging.error(f"保存配置失败: {str(e)}")
#messagebox.showerror("错误", f"无法保存配置:\n{str(e)}")
def load_settings(self):
"""增强型配置加载方法"""
try:
if os.path.exists(self.CONFIG_PATH):
with open(self.CONFIG_PATH, 'r') as f:
config = json.load(f)
# 处理旧版本配置文件
if 'offsets' in config: # 新版本结构
offsets = config['offsets']
else: # 兼容旧版本
offsets = config
# 设置输入框值(带空值保护)
self.custom_command_entry5.delete(0, tk.END)
self.custom_command_entry5.insert(0, offsets.get('x', ''))
self.custom_command_entry6.delete(0, tk.END)
self.custom_command_entry6.insert(0, offsets.get('y', ''))
self.custom_command_entry7.delete(0, tk.END)
self.custom_command_entry7.insert(0, offsets.get('u', ''))
except json.JSONDecodeError:
#logging.warning("配置文件格式错误,已重置")
logging.warning("Config Format Error,Loading Def Config File")
self._create_default_config()
except Exception as e:
#logging.error(f"加载配置失败: {str(e)}")
#messagebox.showwarning("警告", "配置加载失败,已恢复默认值")
logging.error(f"Loading Config Fail,Message is: {str(e)}")
messagebox.showwarning("Waring", "Loading Config Fail,Loading Def Config File")
def _create_default_config(self):
"""创建默认配置文件"""
default_config = {
'version': 1.0,
'offsets': {
'x': "0.0",
'y': "0.0",
'u': "0.0"
}
}
try:
with open(self.CONFIG_PATH, 'w') as f:
json.dump(default_config, f, indent=2)
except Exception as e:
logging.error(f"Great Def Config Fail,Message is: {str(e)}")
def update_gauges(self):
# 从实际数据源获取值
speed = random.randint(0,100)
temp = random.randint(0,100)
#self.speed_gauge.update_value(speed)
#self.temp_gauge.update_value(temp)
self.root.after(1000, self.update_gauges)
def apply_point_limit_change(self):
"""应用数据点数量限制的变更"""
try:
new_limit = int(self.point_entry.get())
if new_limit > 0:
self.point_limit = new_limit
# 立即更新显示
self.update_display()
else:
messagebox.showwarning("输入无效", "数据点数量必须大于0")
except ValueError:
messagebox.showerror("输入错误", "请输入有效的整数")
def write_all_offsets(self):
global Offset_X, Offset_Y, Offset_U
# 获取输入值并验证
try:
Offset_X = float(self.custom_command_entry5.get()) if self.custom_command_entry5.get() else None
Offset_Y = float(self.custom_command_entry6.get()) if self.custom_command_entry6.get() else None
Offset_U = float(self.custom_command_entry7.get()) if self.custom_command_entry7.get() else None
except ValueError:
messagebox.showerror("错误", "请输入有效的数字")
return
# 写入日志
log_msg = f"Offset updated - X: {Offset_X}, Y: {Offset_Y}, U: {Offset_U}"
logging.info(log_msg)
# 更新界面
## self.robot_data_text.yview_moveto(1)
## self.robot_char_text.insert(tk.END, f"{datetime.now().strftime('%H:%M:%S')} {log_msg}\n")
## self.robot_char_text.yview_moveto(1)
def read_last_n_records(self, file_path, n=5):
"""读取文件中最后n条有效数据记录"""
data = []
try:
with open(file_path, 'r') as f:
# 读取所有行
lines = f.readlines()
# 倒序查找有效数据,最多检查最后20行
for line in reversed(lines[-20:]) :
if "Tim" in line:
try:
# 使用正则表达式提取数值
import re
pos_match = re.search(r'Tim([-\d.]+)Tim([-\d.]+)Tim([-\d.]+)Tim', line)
if pos_match:
x, y, z = map(float, pos_match.groups())
data.append((x, y, z))
if len(data) >= n:
break # 达到所需数据量后停止搜索
except Exception as e:
logging.error(f"解析行失败: {str(e)}")
# 返回按时间顺序排列的数据
return data[::-1]
except FileNotFoundError:
logging.error("轨迹文件未找到,请确认路径是否正确")
return []
except Exception as e:
logging.error(f"读取文件时发生错误: {str(e)}")
return []
def read_trajectory_data(self, file_path):
"""使用正则表达式增强版轨迹读取"""
data = []
try:
with open(file_path, 'r') as f:
for line in f:
if "Current_POS_is:" in line:
try:
import re
pos_match = re.search(r'X:([\-0-9.]+)Y:([\-0-9.]+)Z:([\-0-9.]+)U:([\-0-9.]+)', line)
if pos_match:
x, y, z, u = map(float, pos_match.groups())
data.append((x, y, z, u))
except Exception as e:
logging.error(f"解析行失败: {str(e)}")
return data
except FileNotFoundError:
logging.error("轨迹文件未找到,请确认路径是否正确")
return []
def show_animation(self):
"""显示高科技风格的3D轨迹动画"""
file_path = r'C:\Log\v555.txt'
# 验证文件路径
if not os.path.exists(file_path):
messagebox.showerror("文件错误", f"轨迹文件未找到\n路径: {file_path}")
logging.error(f"轨迹文件不存在: {file_path}")
return
trajectory_data = self.read_trajectory_data(file_path)
if not trajectory_data:
logging.warning("没有读取到有效轨迹数据")
return
# 创建新窗口用于显示动画
animation_window = tk.Toplevel(self.root)
animation_window.title("Robot Trajectory Animation")
fig = Figure(figsize=(6, 4), dpi=100)
# 设置中文字体和负号显示
from matplotlib import rcParams
rcParams['font.sans-serif'] = ['SimHei'] # 使用黑体以支持中文
rcParams['axes.unicode_minus'] = False # 正常显示负号
ax = fig.add_subplot(111, projection='3d') # 启用3D绘图
ax.set_title("3D")
ax.set_xlabel("X Position")
ax.set_ylabel("Y Position")
ax.set_zlabel("Z Position") # 添加Z轴标签
ax.grid(True)
ax.set_facecolor('#f0f0f0')
# 修正后的坐标轴背景颜色设置
ax.xaxis.pane.fill = True
ax.xaxis.pane.set_alpha(0.94)
ax.yaxis.pane.fill = True
ax.yaxis.pane.set_alpha(0.90)
ax.zaxis.pane.fill = True
ax.zaxis.pane.set_alpha(0.85)
# 设置坐标轴面板颜色渐变
ax.xaxis.pane.set_facecolor((0.94, 0.94, 0.94))
ax.yaxis.pane.set_facecolor((0.90, 0.90, 0.90))
ax.zaxis.pane.set_facecolor((0.85, 0.85, 0.85))
canvas = FigureCanvasTkAgg(fig, master=animation_window)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
# 使用颜色映射来表示时间进程
from matplotlib import cm
colors = [cm.viridis(i / len(trajectory_data)) for i in range(len(trajectory_data))]
# 创建轨迹线对象
line, = ax.plot([], [], [], lw=2, label='') # 初始化3D线条 实时轨迹
yellow_line, = ax.plot([], [], [], c='gold', lw=2, label='His') # 历史路径标签
# 创建当前点标记
current_point, = ax.plot([], [], [], 'ro', markersize=10, label='Cur') # 当前位置标签
# 创建轨迹尾迹
trail, = ax.plot([], [], [], c='blue', alpha=0.3, lw=2, label='...') # 轨迹尾迹标签
# 添加图例说明
ax.legend(loc='upper left', fontsize=12, bbox_to_anchor=(0.0, 0.9))
def init():
xs = [d[0] for d in trajectory_data]
ys = [d[1] for d in trajectory_data]
zs = [d[2] for d in trajectory_data]
min_range = 20 # 最小显示范围
ax.set_xlim(min(xs) - 5, max(xs) + 5 if max(xs)-min(xs) > min_range else min(xs) + min_range)
ax.set_ylim(min(ys) - 5, max(ys) + 5 if max(ys)-min(ys) > min_range else min(ys) + min_range)
ax.set_zlim(min(zs) - 5, max(zs) + 5 if max(zs)-min(zs) > min_range else min(zs) + min_range)
ax.view_init(elev=20, azim=200) # 默认视角
return line, yellow_line, current_point, trail
def update(frame):
# 提取当前帧前的所有X、Y、Z值
x_values = [d[0] for d in trajectory_data[:frame+1]]
y_values = [d[1] for d in trajectory_data[:frame+1]]
z_values = [d[2] for d in trajectory_data[:frame+1]] # 提取Z值
# 更新轨迹线
line.set_data(x_values, y_values)
line.set_3d_properties(z_values)
line.set_color(colors[frame]) # 设置当前线段的颜色
# 更新黄色轨迹线(现为历史路径)
yellow_x = x_values[:max(0, frame-10)]
yellow_y = y_values[:max(0, frame-10)]
yellow_z = z_values[:max(0, frame-10)]
yellow_line.set_data(yellow_x, yellow_y)
yellow_line.set_3d_properties(yellow_z)
# 更新当前点标记
current_point.set_data([x_values[-1]], [y_values[-1]])
current_point.set_3d_properties([z_values[-1]])
# 更新轨迹尾迹(仅显示最近的20个点)
trail_start = max(0, frame-5)
trail.set_data(x_values[trail_start:], y_values[trail_start:])
trail.set_3d_properties(z_values[trail_start:])
trail.set_alpha(np.linspace(0.2, 0.8, frame - trail_start + 1)[-1])
# 动态更新标题显示当前帧信息
#ax.set_title(f"智能制造演示 | 当前帧: {frame} | X:{x_values[-1]:.2f}, Y:{y_values[-1]:.2f}, Z:{z_values[-1]:.2f} (mm)")
ax.set_title(f"3D")
# 每50帧自动调整视角
if frame % 50 == 0:
ax.view_init(elev=20, azim=35 + frame//10)
return line, yellow_line, current_point, trail
from matplotlib.animation import FuncAnimation
ani = FuncAnimation(fig, update, frames=len(trajectory_data), init_func=init,
blit=True, interval=250, repeat=False) # 运行速度降为原始速度的 1/5 运行速度
ani._start() # 使用TkAgg推荐的启动方式
# 添加动画控制面板
control_frame = tk.Frame(animation_window)
control_frame.pack(side=tk.BOTTOM, fill=tk.X)
# 添加动画控制按钮
btn_frame = tk.Frame(control_frame)
btn_frame.pack(pady=10)
def toggle_animation():
if ani.event_source is None:
return
if ani.event_source.is_running():
ani.event_source.stop()
toggle_btn.config(text="Play")
else:
ani.event_source.start()
toggle_btn.config(text="Pause")
toggle_btn.config(command=toggle_animation)
def reset_animation():
ani.event_source.stop()
init()
toggle_btn.config(text="Play")
reset_btn = tk.Button(btn_frame, text="Reset", command=reset_animation,
bg="#FFA500", fg="white", width=6, font=("Segoe UI", 10))
reset_btn.pack(side=tk.LEFT, padx=5)
close_btn = tk.Button(btn_frame, text="Close", command=animation_window.destroy,
bg="#C0C0C0", fg="black", width=6, font=("Segoe UI", 10))
close_btn.pack(side=tk.RIGHT, padx=5)
#C:\Users\SKD\AppData\Local\Programs\Python\Python311\Scripts\pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ pyautogui
if __name__ == "__main__":
root = tk.Tk()
app = TCPClientApp(root)
root.mainloop()
Robot
------------
Process.prg
------------
Function Alignment_TCP_212
GoTo lblOpenPort
lblOpenPort:
CloseNet #212
Print "Waiting Servers Open ", Time$
SetNet #212, "192.168.0.150", 7777, CRLF, NONE, 0
OpenNet #212 As Client
WaitNet #212
Print "IP:192.168.0.150 Port:7777 Open at ", Time$
MemOff 18 'Clean
''14:28:13 Tim-682.789Tim289.271Tim89.7095TimOKTim888888
'Recive data DOWNTimNoneAUOTim11.999Tim1061.1652Tim1612.829Tim90.005055Tim
Do
'MemOn 18
If MemSw(18) = Off Then
Wait 0.6
Status_212 = ChkNet(212)
Print "Recive data Len/Status is ", Status_212
If Status_212 > 0 And Status_212 < 62 Then
Read #212, Data_212$, Status_212
Print "Recive data1 ", Status_212, "Recive data2 ", Data_212$, "Recive data3 ", Data_212_Read
'ParseStr Data_212$, PData_212$(), "Tim" '锟街革拷锟街凤拷
'Print "Recive data sp is ", PData_212$(0), PData_212$(1), PData_212$(2)
MemOn 18
ElseIf Status_212 > 62 Then
Print "Recive len is so long"
String msg2$, title2$
Integer mFlag2s, answer2
msg2$ = "Recive len is so long" + CRLF
msg2$ = msg2$ + "Press Y or N to Exit..." + CRLF
msg2$ = msg2$ + "Press N or Y to Exit..." + CRLF
title2$ = "Recive Title"
mFlag2s = MB_YESNO + MB_ICONQUESTION
MsgBox msg2$, mFlag2s, title2$, answer2
If answer2 = IDNO Or answer2 = IDYES Then
Quit All
EndIf
Exit Do
ElseIf Status_212 = -3 Then
MemOff 2 'Ethernet Connect Status
Print "Ethernet is Close,Pls Check it...", Time$
GoTo lblOpenPort
EndIf
EndIf
If MemSw(18) = On Then
Wait 0.022
ParseStr Data_212$, PData_212$(), "Tim" '锟街革拷锟街凤拷
'Print "Recive data sp is ", PData_212$(0), PData_212$(1), PData_212$(2), PData_212$(3), PData_212$(4), PData_212$(5)
''Order:1=Ref_A1 2=Ref_A2 3=Ref_A3 4=Ref_A4 5=Start Index:888888
Order = Val(PData_212$(1))
'Index = Val(PData_212$(5))
Pitch = Val(PData_212$(2))
''RIGHTTim2Tim11.999Tim1061.1652Tim1612.829Tim90.005055Tim
''if Pdate 0 1 2 = None, No Action
''Data_212_Start$ = PData_212$(0)=LEFRUPDOWNSAVE
''Data_212_Start$ = PData_212$(1)=Order
''Data_212_Start$ = PData_212$(2)=Pitch
If Order = 0 Then
Print "Home Pos Send", P986
Print #212, "Home Pos Send", P986
Go P986 'Home_Ref
ElseIf Order = 1 Then
Print "Go Ref_A1"
Wait 0.3
P987 = RealPos
Print #212, "Go Ref_A1", P987
Go P985 'A1_Ref
ElseIf Order = 2 Then
Print "Go Ref_A2"
Wait 0.3
P987 = RealPos
Print #212, "Go Ref_A2", P987
Go P984 'A2_Ref
EndIf
Wait 0.88
'
CX_Here = CX(Here)
CY_Here = CY(Here)
CZ_Here = CZ(Here)
CU_Here = CU(Here)
Print "Now pos is :", Here
Data_212_Start$ = PData_212$(0)
If Data_212_Start$ = "UP" Then
Print "Recive UP = ", Data_212_Start$
Go XY(CX(Here) + Pitch, CY(Here), CZ(Here), CU(Here))
Print "Now pos is :", Here
ElseIf Data_212_Start$ = "LEF" Then
Print "Recive Left = ", Data_212_Start$
Go XY(CX(Here), CY(Here) + Pitch, CZ(Here), CU(Here))
Print "Now pos is :", Here
ElseIf Data_212_Start$ = "RIGH" Then
Print "Recive Right = ", Data_212_Start$
Go XY(CX(Here), CY(Here) - Pitch, CZ(Here), CU(Here))
Print "Now pos is :", Here
ElseIf Data_212_Start$ = "DOWN" Then
Print "Recive Down = ", Data_212_Start$
Go XY(CX(Here) - Pitch, CY(Here), CZ(Here), CU(Here))
Print "Now pos is :", Here
ElseIf Data_212_Start$ = "CW" Then
Print "Recive CW = ", Data_212_Start$
Go XY(CX(Here), CY(Here), CZ(Here), CU(Here) - Pitch)
Print "Now pos is :", Here
ElseIf Data_212_Start$ = "CCW" Then
Print "Recive CCW = ", Data_212_Start$
Go XY(CX(Here), CY(Here), CZ(Here), CU(Here) + Pitch)
Print "Now pos is :", Here
ElseIf Data_212_Start$ = "SAVE" Then
Print "Saving Aligment OK Pos ", Here
String msg$, title$
Integer mFlags, answer
msg$ = "Save Pos" + CRLF
msg$ = msg$ + "Are U Sure?"
title$ = "Setting 2 Save"
mFlags = MB_YESNO + MB_ICONQUESTION
MsgBox msg$, mFlags, title$, answer
If answer = IDNO Then
Quit All
ElseIf answer = IDYES Then
PLabel 988, "Aligment"
Here P988
Print "Save Pos ", CRLF, Here
Print #212, "Save Pos ", CRLF, Here
EndIf
EndIf
SavePoints "rbtPoints_212.pts"
Print "Eecive data OK...Start 2 Waiting Order..."
MemOff 18 'Clean
EndIf
Print #212, "---", Time$
Print "---", Time$
MemOff 18 'Clean
Loop
ErrorHandle:
'errnum = Err
Print "ERROR", errnum
Quit All
Fend
Function Welcome
Do
If MemSw(2) = Off Then
Print "Welcome 2 Use"
String msg$, title$
Integer mFlags, answer
msg$ = "Welcome 2 Use" + CRLF
msg$ = msg$ + "Do not Press Or Press Y to Continue..." + CRLF
msg$ = msg$ + "Press N to Exit..." + CRLF
title$ = "Robot Control Tool"
mFlags = MB_YESNO + MB_ICONQUESTION
MsgBox msg$, mFlags, title$, answer
If answer = IDNO Then
Quit All
EndIf
EndIf
'CloseNet #212
Exit Do
Loop
Fend
Function Recive_lendayu62
Do
If Status_212 > 62 Then
Print "Recive len is so long"
String msg$, title$
Integer mFlags, answer
msg$ = "Recive len is so long" + CRLF
msg$ = msg$ + "Press Y to Continue..." + CRLF
msg$ = msg$ + "Press N to Exit..." + CRLF
title$ = "Recive Title"
mFlags = MB_YESNO + MB_ICONQUESTION
MsgBox msg$, mFlags, title$, answer
If answer = IDNO Or answer = IDYES Then
Quit All
EndIf
EndIf
Exit Do
Loop
Fend
Function TCP_209_AreaSensor_As_Client
' 锟截憋拷锟斤拷锟斤拷锟斤拷锟紼S THEN
CloseNet #209
Print "#209 Config Waiting Servers Open ", Time$
' 锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟絆pen ", Time$
SetNet #209, "192.168.0.150", 5670, CRLF, NONE, 0
' 锟皆客伙拷锟斤拷模式锟斤拷锟斤拷锟斤拷锟斤拷, 0
OpenNet #209 As Client
' 锟饺达拷锟斤拷锟斤拷锟斤拷锟接斤拷锟斤拷锟浇, 0
WaitNet #209
Print "#209 Config IP:192.168.0.150 Port:5678 Open at ", Time$
' 锟饺达拷1锟斤拷
Wait 1
Do
' 锟截憋拷锟斤拷锟斤拷锟斤拷锟接斤拷锟斤拷锟浇, 0
CloseNet #209
Print "#209 Waiting Servers Open ", Time$
' 锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟?, TIME$
SetNet #209, "192.168.0.150", 5670, CRLF, NONE, 0
' 锟皆客伙拷锟斤拷模式锟斤拷锟斤拷锟斤拷锟斤拷E, 0
OpenNet #209 As Client
' 锟饺达拷锟斤拷锟斤拷锟斤拷锟接斤拷锟?29Tim90.005055Tim
WaitNet #209
Print "#209 IP:192.168.0.150 Port:5678 Open at ", Time$
' 锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟捷筹拷锟絠me$
Area_Sensor___ = ChkNet(209)
Print "#209 Recived Lens: ", Area_Sensor___
' 锟斤拷锟斤拷锟斤拷锟斤拷萁锟斤拷锟?
If ChkNet(209) > 0 Then
' 锟斤拷取一锟斤拷锟斤拷锟斤拷
''Line Input #209, Area_Sensor_$
Read #209, Area_Sensor_$, Area_Sensor___
Print "data is : ", Area_Sensor_$
' 锟斤拷锟斤拷锟斤拷盏锟斤拷锟斤拷锟斤拷锟?
Select Case UCase$(Trim$(Area_Sensor_$))
Case "PAUSE"
Print "Pause"
Pause ' 锟斤拷停
Case "RESET"
Print "RESUME"
Reset ' 锟斤拷锟斤拷锟斤拷锟阶刺?锟斤拷位锟斤拷锟斤拷
Case "STOP"
Print "Motor_Off"
Motor Off ' 锟截闭碉拷锟?
Case "ESTOPON"
Print "ESTOPON"
'SafeguardOn ' 锟截闭碉拷锟?
'EStopOn
Case "1"
Print "Other command: ", Area_Sensor_$
Motor Off
Send
EndIf
If Area_Sensor___ = -3 Then
Pause ' 锟斤拷停
'Motor Off
String msg6_$, title_6$
Integer mFlags_6, answer_6
msg6_$ = "Waring" + CRLF
msg6_$ = msg6_$ + "Area Sensor !!!" + CRLF
msg6_$ = msg6_$ + "Area Sensor !!!" + CRLF
msg6_$ = msg6_$ + "Area Sensor !!!" + CRLF
msg6_$ = msg6_$ + " " + CRLF
msg6_$ = msg6_$ + "Press N to STOP !!!" + CRLF
msg6_$ = msg6_$ + "Press Y to Continue" + CRLF
title_6$ = "Robot Control Tool"
mFlags_6 = MB_YESNO + MB_ICONQUESTION
MsgBox msg6_$, mFlags_6, title_6$, answer_6
If answer_6 = IDNO Then
Quit All
EndIf
If answer_6 = IDYES Then
Wait 0.0001
EndIf
EndIf
Loop
Fend
Function Big_TCP_212_Runmode
CloseNet #210
SetNet #210, "192.168.0.1", 2009, CRLF, NONE, 0
OpenNet #210 As Server
WaitNet #210
Print "#210 Open at ", Time$
MemOff RecvData 'Clean
Jump P988 LimZ (0) 'NG_Port
'Jump P988
Off 9
Off 8
Wait 0.8
Jump P999 LimZ (0) 'home_Standby
Do
Off 9
Off 8
Wait 0.05 '<1 3 Cycle
If MemSw(RecvData) = Off Then
state211 = ChkNet(210)
Print "Recived Lens: ", state211
Print "For_Index:", For_LS_tim
If state211 > 0 Then
If For_LS_tim = 3 Then
'cLANE
'Input #211, Data211$
Print #210, Clean_Tim$
Clean_Tim$ = ""
Wait 2
Input #210, Data210$
Print Time$, " Recive data: ", Data210$ 'recive data
state211 = ChkNet(210)
'Input #211, Data211$
'Print Time$, " Recive data: ", Data211$ 'recive data
'cLANE ok
Input #210, Data211$
Print Time$, " Recive data_Clean: ", Data211$ 'recive data
ParseStr Data211$, Pdata211$(), "Tim" 'spilt data
MemOn RecvData
Start_String_211$ = Data211$
'Start_Real_211 = Val(Start_String_211$)
Start_Real_211 = Val(Right$(Start_String_211$, 6))
Print "Start index: ", Start_Real_211
ElseIf For_LS_tim = 1 Or For_LS_tim = 2 Then
Input #210, Data211$
Print Time$, " Recive data_Clean: ", Data211$ 'recive data
ParseStr Data211$, Pdata211$(), "Tim" 'spilt data
MemOn RecvData
Start_String_211$ = Data211$
'Start_Real_211 = Val(Start_String_211$)
Start_Real_211 = Val(Right$(Start_String_211$, 6))
Print "Start index: ", Start_Real_211
ElseIf For_LS_tim = 0 Then
Input #210, Data211$
Print Time$, " Recive data: ", Data211$ 'recive data
ParseStr Data211$, Pdata211$(), "Tim" 'spilt data
MemOn RecvData
Start_String_211$ = Data211$
'Start_Real_211 = Val(Start_String_211$)
Start_Real_211 = Val(Right$(Start_String_211$, 6))
Print "Start index: ", Start_Real_211
EndIf
ElseIf state211 = -3 Then
Print Time$, "Ethernet NG ,Pls Connect it."
Print Time$, "Ethernet NG ,Pls Connect it.."
Print Time$, "Ethernet NG ,Pls Connect it..."
''
Do
CloseNet #210
SetNet #210, "192.168.0.1", 2009, CRLF, NONE, 0
OpenNet #210 As Server
WaitNet #210
Print "#210 Open at ", Time$
If state211 <> -3 Then
Quit All
EndIf
Exit Do
Loop
''
EndIf
EndIf
If MemSw(RecvData) = On And For_LS_tim = 0 Or Start_Real_211 = 888888 Or Start_Real_211 = 666666 Then
Home_POS_Index = 0
'Print "x:", Pdata211$(0), "y:", Pdata211$(1), "u:", Pdata211$(2)
X_String_211$ = Pdata211$(0)
X_Real_211 = Val(X_String_211$)
Y_String_211$ = Pdata211$(1)
Y_Real_211 = Val(Y_String_211$)
U_String_211$ = Pdata211$(2)
U_Real_211 = Val(U_String_211$)
If U_Real_211 > 0 Then
U_Real_211_Angle = -U_Real_211
ElseIf U_Real_211 < 0 Then
U_Real_211_Angle = -U_Real_211
EndIf
'' Off_String_211$ = Pdata211$(3)
'' Print "Off_String_211$", (Off_String_211$)
'' If Off_String_211$ = "Motor_off" Then
'' Print #210, "Motor_Off"
'' Print "Off"
'' Motor Off
'' EndIf
'Print U_Real_211_Angle
Print "Spilt data: ", "x_Real:", X_Real_211, "y_Real:", Y_Real_211, "u_Real:", U_Real_211_Angle
Print #210, "x_Real:", X_Real_211, "y_Real:", Y_Real_211, "u_Real:", U_Real_211_Angle
''
' X_Max = 542.666 -386 -372 -355
' X_Min = -990.222 -915 -805
' Y_Max = 836.666 217 206 286 310
' Y_Min = -122.222 -400 -400 -124
If X_Real_211 >= -805 And X_Real_211 <= -355 And Y_Real_211 >= -124 And Y_Real_211 <= 310 Then
P993 = XY(X_Real_211, Y_Real_211, -6.6666, U_Real_211_Angle)
Jump P993 'Vision_Pre
''Go XY(X_Real_211 + 20, Y_Real_211, -1.666, U_Real_211_Angle)
Else
Print "Error 4007, Target position out of range"
String msg$, title$
Integer mFlags, answer
msg$ = "There has An Error" + CRLF
msg$ = msg$ + "Press Y to Close and Call Tim"
title$ = "Error Message From Robot"
mFlags = MB_YESNO + MB_ICONQUESTION
MsgBox msg$, mFlags, title$, answer
If answer = IDNO Then
Quit All
EndIf
CloseNet #210
Exit Do
EndIf
If U_Real_211_Angle >= 0 Then
X_Real_211 = X_Real_211 + 0
Y_Real_211 = Y_Real_211 + 0
U_Real_211_Angle = U_Real_211_Angle + 0
'' ElseIf U_Real_211_Angle >= -16 And U_Real_211_Angle <= 45 Then
'' X_Real_211 = X_Real_211 + 21.237
'' Y_Real_211 = Y_Real_211 + -6.463
'' U_Real_211_Angle = U_Real_211_Angle + -3.065
'' ElseIf U_Real_211_Angle >= -46 And U_Real_211_Angle <= 75 Then
'' X_Real_211 = X_Real_211 + 24.166
'' Y_Real_211 = Y_Real_211 + -10.672
'' U_Real_211_Angle = U_Real_211_Angle + -2.829
'' ElseIf U_Real_211_Angle >= -76 And U_Real_211_Angle <= 105 Then
'' X_Real_211 = X_Real_211 + 25.630
'' Y_Real_211 = Y_Real_211 + -14.882
'' U_Real_211_Angle = U_Real_211_Angle + -2.592
'' ElseIf U_Real_211_Angle >= -106 And U_Real_211_Angle <= 135 Then
'' X_Real_211 = X_Real_211 + 20.834
'' Y_Real_211 = Y_Real_211 + -13.221
'' U_Real_211_Angle = U_Real_211_Angle + -2.728
'' ElseIf U_Real_211_Angle >= -136 And U_Real_211_Angle <= 165 Then
'' X_Real_211 = X_Real_211 + 16.037
'' Y_Real_211 = Y_Real_211 + -11.559
'' U_Real_211_Angle = U_Real_211_Angle + -2.864
'' ElseIf U_Real_211_Angle >= -166 And U_Real_211_Angle <= 195 Then
'' X_Real_211 = X_Real_211 + 11.241
'' Y_Real_211 = Y_Real_211 + -10.063
'' U_Real_211_Angle = U_Real_211_Angle + -2.728
'' ElseIf U_Real_211_Angle >= -196 And U_Real_211_Angle <= 225 Then
'' X_Real_211 = X_Real_211 + 12.060
'' Y_Real_211 = Y_Real_211 + -7.852
'' U_Real_211_Angle = U_Real_211_Angle + -2.852
'' ElseIf U_Real_211_Angle >= -226 And U_Real_211_Angle <= 255 Then
'' X_Real_211 = X_Real_211 + 12.880
'' Y_Real_211 = Y_Real_211 + -5.641
'' U_Real_211_Angle = U_Real_211_Angle + -2.976
'' ElseIf U_Real_211_Angle >= -256 And U_Real_211_Angle <= 285 Then
'' X_Real_211 = X_Real_211 + 13.699
'' Y_Real_211 = Y_Real_211 + 2.791
'' U_Real_211_Angle = U_Real_211_Angle + -2.976
'' ElseIf U_Real_211_Angle >= -286 And U_Real_211_Angle <= 315 Then
'' X_Real_211 = X_Real_211 + 16.212
'' Y_Real_211 = Y_Real_211 + -0.529
'' U_Real_211_Angle = U_Real_211_Angle + -3.102
'' ElseIf U_Real_211_Angle >= -316 And U_Real_211_Angle <= 345 Then
'' X_Real_211 = X_Real_211 + 18.724
'' Y_Real_211 = Y_Real_211 + -3.849
'' U_Real_211_Angle = U_Real_211_Angle + -3.228
'' ElseIf U_Real_211_Angle >= -346 And U_Real_211_Angle <= -15 Then
'' X_Real_211 = X_Real_211 + +20.082
'' Y_Real_211 = Y_Real_211 + 0.812
'' U_Real_211_Angle = U_Real_211_Angle + -3.302
EndIf
'ADD
Go XY(X_Real_211, Y_Real_211, -247.387, U_Real_211_Angle) 'Down -247.387
On 8 'Vacuum
Wait 3.8
''锟斤拷Go XY(X_Real_211, Y_Real_211, -116, U_Real_211_Angle) 'Up
'Jump S_put
'Go Put
'Wait 1.8
''Jump Put2
Jump P983 'Place
Wait 3.8
Off 8
On 9
Wait 0.6
Off 9
'ADD
Jump P999 'home_Standby
Print "home_Pos"
Print #210, "Home_Pos", "Tim", "OK", "Tim"
Home_POS_Index = 1
For_LS_tim = 1 + For_LS_tim
EndIf
If For_LS_tim = 3 Then
For_LS_tim = 1
EndIf
MemOff RecvData
If Home_POS_Index = 1 Then
Wait 0.00001
''Print #210, "Home"
EndIf
Loop
Fend
Function Rbt_PC216
CloseNet #216
OpenNet #216 As Server
WaitNet #216
Print "Open #216 at ", Time$
For_LS = 1
Print For_LS
Do
'Print #216, "Send data from robot "
Wait 3
Print For_LS
state216 = ChkNet(216)
Print "ChkNet= data", state216
If state216 > 0 And For_LS = 2 Then
'If state216 = 23 Or state216 = 25 Then
Wait 0.01
'Print "Send data XXX"
'send_Data$ = "XXXYYUUU"
'Print #216, send_Data$
'Print #216, "ABCC"
'Input #216, Response$
'Print "ChkNet(216) Line Input: "
'Print Response$
Print "Has data"
Read #216, Data$, state216
DataLS$ = Data$
Print #216, Data$
Print "ChkNet(216) Read: "
Print Data$
Print state216
Integer fileNum2, i, j
fileNum2 = FreeFile
AOpen "D:\V80.txt" As #fileNum2
Line Input #fileNum2, Read_file$
Y_Tim_Real = Val(Read_file$)
Print "Y:", Y_Tim_Real
Print "---"
Close #fileNum2
'Input #216, Data$
'Print "Receive data: ", Data$, Time$
'ParseStr Data$, Pdata_x$(), "XX"
'X_Tim_Real = Val(Pdata_x$)
'Print "X:", X_Tim_Real
X_Tim_Real = Val(Left$(Data$, 8))
Print "X:", X_Tim_Real,
ParseStr DataLS$, Pdata_x$(), "YYY"
Y_Tim_Real = Val(Pdata_x$)
Print "Y:", Y_Tim_Real,
U_Tim_Real = Val(Right$(DataLS$, 13))
Print "U:", U_Tim_Real
'Vision_Process
'Wait start_Awitch = True
Print "Process_锟竭讹拷锟斤拷锟斤拷锟教筹拷锟斤拷执锟斤拷锟叫★拷锟斤拷锟斤拷"
'Call Rbt_PC216
Print "Process_Going 2 St_Pick Pos"
'Speed 100, 100, 100
Go P993
'Go P992
'Speed 100, 100, 5
Print "Process_St_Pick Pos"
'Print Here
'Go XY(X_Tim_Real, Y_Tim_Real, -246.628, 5)
Print Here
Wait 0.1
On 8
'Wait Sw(8) = 1
'Wait 1
'Go P990 'OK POS_LS
Go P992 'OK POS
Off 8
'Wait 1
Go P993
'Go pick
'Print "Process_Pick Pos"
'Vision_Process
'Read #216, Data$, numOfChars
'numOfChars = ChkNet(216)
'Print numOfChars
ElseIf state216 = -3 Then
Print "#216 Close ,Pls open #216 "
ElseIf state216 = 0 Then
Print "#216 Net no data ,Pls check it "
' 锟斤拷止锟斤拷锟斤拷65536
ElseIf state216 > 0 And For_LS = 6 Then
For_LS = 10
ElseIf state216 > 0 And For_LS = 12 Then
For_LS = 5
' 锟斤拷止锟斤拷锟斤拷65536
EndIf
state216 = 25
' If Data$ = 3.15 Then
' Select Pdata$(5)
' Case "10000"
' Print #216, "SHAKEHAND 10000"
' Case "31"
' Print #216, "SHAKEHAND 31"
' Go P999
' Send
' EndIf
For_LS = 1 + For_LS
Loop
Fend
Function Vision_Process
Do
'Wait start_Awitch = True
Print "Process_锟竭讹拷锟斤拷锟斤拷锟教筹拷锟斤拷执锟斤拷锟叫★拷锟斤拷锟斤拷"
'Call Rbt_PC216
Print "Process_Going 2 St_Pick Pos"
'Speed 100, 100, 100
Go S_pick
'Speed 100, 100, 5
Print "Process_St_Pick Pos"
Print Here
Go XY(X_Tim_Real, Y_Tim_Real, -216, 5)
Print Here
'Go pick
'Print "Process_Pick Pos"
Loop
Fend
Function File
Do
Print "File"
Wait 2
Integer fileNu, i, j
' fileNum = FreeFile
' WOpen "timTEST.DAT " As #fileNum
' For i = 0 To 100
'Print #fileNum, i
'Next I
'Close #fileNum
'........
fileNu = FreeFile
ROpen "timTEST88.DAT" As #fileNu
For j = 4 To 8
Input #fileNu, j
Print j
Next j
Close #fileNu
Loop
Fend
Function tcpip_211_1Cycle
CloseNet #210
SetNet #210, "192.168.0.1", 2009, CRLF, NONE, 0
OpenNet #210 As Server
WaitNet #210
Print " #210 Open at ", Time$
MemOff RecvData 'Clean
For_LS = 0
Do
Wait 2
If MemSw(RecvData) = Off Then
state211 = ChkNet(210)
Print "state211: ", state211
Print "For_LS_tim", For_LS_tim
If state211 > 0 And For_LS_tim = 0 Then
Input #210, Data211$
Print Time$, " Recive data: ", Data211$ 'recive data
ParseStr Data211$, Pdata211$(), "Tim" 'spilt data
MemOn RecvData
ElseIf state211 = -3 Then
Print "锟斤拷太锟斤拷通讯锟较匡拷锟斤拷锟斤拷锟铰达拷"
EndIf
EndIf
If MemSw(RecvData) = On And For_LS_tim = 0 Then
'Print "x:", Pdata211$(0), "y:", Pdata211$(1), "u:", Pdata211$(2)
X_String_211$ = Pdata211$(0)
X_Real_211 = Val(X_String_211$)
Y_String_211$ = Pdata211$(1)
Y_Real_211 = Val(Y_String_211$)
U_String_211$ = Pdata211$(2)
U_Real_211 = Val(U_String_211$)
Print " Spilt data: ", "x_Real:", X_Real_211, "y_Real:", Y_Real_211, "u_Real:", U_Real_211
Print #210, "x_Real:", X_Real_211, "y_Real:", Y_Real_211, "u_Real:", U_Real_211
Go XY(X_Real_211, Y_Real_211, -216, U_Real_211)
Wait 3
Go P993
' 锟斤拷止锟斤拷锟斤拷65536
' If state211 > 0 And For_LS = 6 Then
' For_LS_tim = 10
' ElseIf state211 > 0 And For_LS = 12 Then
' For_LS_tim = 5
' EndIf
For_LS_tim = 2 + For_LS_tim
Print "For_LS_tim222", For_LS_tim
' 锟斤拷止锟斤拷锟斤拷65536
' Select Pdata211$(0)
' Case "Tim"
' Print "SHAKEHAND 10000"
' Case "31"
' Print "SHAKEHAND 31"
' Send
EndIf
MemOff RecvData
Loop
Fend
Function To_Robot
Print "To_Robot_锟斤拷始锟斤拷锟斤拷Robot 锟斤拷 PC 通讯锟斤拷锟斤拷"
SetNet #205, "192.168.0.1", 2004, CRLF, NONE, 0
OpenNet #205 As Server
Print "To_Robot_锟皆凤拷锟斤拷锟斤拷锟斤拷式锟斤拷205锟剿匡拷"
Print "To_Robot_锟饺达拷锟斤拷锟斤拷"
WaitNet #205
Print "To_Robot_锟斤拷锟接★拷锟斤拷锟斤拷"
Do
Print "To_Robot_Robot 锟斤拷 PC 通讯锟斤拷锟斤拷锟斤拷锟叫★拷锟斤拷锟斤拷"
Wait 1
Print #205, "Robot used: ", h
'Print #205, ""
Print "Robot used: ", h
ATCLR
Wait 1
'Print #205, "Axis Runing Status not 0 is OK : ", "X=", ATRQ(1), "/", "Y=", ATRQ(2), "/", "Z=", ATRQ(3), "/", "U=", ATRQ(4) 'Send Tor data2
Real statustim
statustim = ChkNet(205)
If statustim > 0 Then
Print "#205 锟斤拷锟斤拷锟斤拷"
Print #205, "Robot used: ", h
Print #205, ""
Print "From #205 Recive data "
Print #205, "send data From Robot 192.168.0.1:205"
Wait .5
Input #205, datattt$
ElseIf statustim = -3 Then
Print "锟斤拷太锟斤拷通讯锟较匡拷锟斤拷锟斤拷锟斤拷锟铰打开斤拷锟斤拷头
'Input #205, datatt$
EndIf
Loop
Fend
Function Process
Do
Print "Process_锟竭讹拷锟斤拷锟斤拷锟教筹拷锟斤拷执锟斤拷锟叫★拷锟斤拷锟斤拷"
Print "Process_Standby Pos"
Go P999
Print "Process_Pick_Standby Pos"
Go S_pick
Print "Process_Pick Pos"
Go pick
Off 8
Wait 1
On 8
Print "Vacuum"
Print "Process_Pick_Standby Pos"
Go S_pick
Print "Process_Put_Standby Pos"
Go S_put
Print "Process_Put"
Go Put
Off 8
Wait 1
Print "Process_Put_Standby Pos"
Go S_put
Wait .6
On 9
Off 9
Print "blow"
Loop
Fend
Function Running_time
Do
h = Time(0) '锟斤拷小时锟斤拷锟斤拷通锟斤拷时锟斤拷
Print "Running_time_Robot 锟窖撅拷使锟斤拷: ", h, "小时 ", ",", " 1锟斤拷锟接回憋拷一锟斤拷"
Wait 60
Loop
Fend
Function Current_POS
CloseNet #215
Print "#215 Config Waiting Servers Open ", Time$
SetNet #215, "192.168.0.150", 1122, CRLF, NONE, 0
OpenNet #215 As Client
WaitNet #215
Print "#215 Config IP:192.168.0.150 Port:1122 Open at ", Time$
Wait 1
Do
' CloseNet #215
' Print "#215 Waiting Servers Open ", Time$
' SetNet #215, "192.168.0.150", 1122, CRLF, NONE, 0
' OpenNet #215 As Client
' WaitNet #215
' Print "#215 IP:192.168.0.150 Port:1122 Open at ", Time$
Check_215 = ChkNet(215)
' Print "#215 Recived Lens: ", Check_215
' If ChkNet(215) > 0 Then
'Print Time$, " Current_POS_is: ", "X:", CX_Here, " ,", "Y:", CY_Here, " ,", "Z:", CZ_Here, " ,", "U:", CU_Here
Wait 0.0003
P982 = CurPos
''Print CX(P982), CY(P982), CY(P982), CY(P982)
Print #215, Time$, " Current_POS_is: ", "X:", CX(P982), " ,", "Y:", CY(P982), " ,", "Z:", CZ(P982), " ,", "U:", CU(P982)
Print Time$, " Current_POS_is: ", "X:", CX(P982), " ,", "Y:", CY(P982), " ,", "Z:", CZ(P982), " ,", "U:", CU(P982)
Integer fileNum6, XXX, YYY, ZZZ, UUU
String ZZZ$, UUU$, XXX$, YYY$
fileNum6 = FreeFile
XXX = CX(P982)
XXX$ = Str$(XXX)
YYY = CY(P982)
YYY$ = Str$(YYY)
ZZZ = CZ(P982)
ZZZ$ = Str$(ZZZ)
UUU = CU(P982)
UUU$ = Str$(UUU)
AOpen "C:\log\V555.txt" As #fileNum6
Write #fileNum6, Time$ + "Current_POS_is: " + "X:" + "" + XXX$ + "Y:" + "" + YYY$ + "Z:" + "" + ZZZ$ + "U:" + "" + UUU$ + CRLF
Print Time$, "--- Current_POS_is: ", "X:", CX(P982), " ,", "Y:", CY(P982), " ,", "Z:", CZ(P982), " ,", "U:", CU(P982)
Close #fileNum6
' EndIf
Loop
Fend
Function Move_Current_POS
Do
Jump A2_Alignmnet_Ref
BMove XY(100, 0, -58.888, -45) '锛堝湪鏈湴鍧愭爣绯讳腑锛夊悜 X 鏂瑰悜绉诲姩 100mm)
Go A1_Alignmnet_Ref
BGo XY(-80.88, 0, -18.888, -180) '锛堝湪鏈湴鍧愭爣绯讳腑锛夊悜 X 鏂瑰悜绉诲姩 100mm)
Print "Running_"
Wait 0.5
Loop
Fend
------------
Main.prg
------------
'
'Design By Tim
'
Global Integer h, InData, OutData, start_Awitch, Long_Tim, For_LS, fileNum, RecvData, For_LS_tim
Global Real CX_Here, X_Tim_Real, Y_Tim_Real, U_Tim_Real
Global Real CY_Here
Global Real CZ_Here
Global Real CU_Here
Global String datattt$, Data$, DataLS$, Response$, X_Tim_string$, Y_Tim_String$, Data_Client$, send_Data$, Read_file$, Data211$, X_String_211$, Y_String_211$, U_String_211$, Start_String_211$, Clean_Tim$, Data210$
Global String Pdata_x$(100), Pdata_y$(100), Pdata$(100), Pdata211$(100)
Global Real state216, state21666, numOfChars, state_client, state211, X_Real_211, Y_Real_211, U_Real_211, U_Real_211_Angle, Start_Real_211
Global Real state212, Pitch, Area_Sensor___, III, Check_215
Global String Data_212$, PData_212$(100), Data_212_Start$, Off_String_211$, Area_Sensor_$, Area_Sensor___$
Global Integer errnum, Data_212_Read, Status_212, Index, Order, Home_POS_Index
Function main
Motor On
Power High
Speed 100 'Go Speed Tim on High ,Off Low
SpeedS 2000 'MAX 2000
Print "Program Runing at: ", Time$
Print "The current control device is:", CtrlDev, " Remark锟斤拷21 PC锟斤拷22 Remote I/O锟斤拷26 Remote Ethernet锟斤拷29 Remote RS232C"
Print "Waiting... "
''
Xqt Big_TCP_212_Runmode, Normal 'Big_Vison
''
Xqt Current_POS, Normal 'NoPause
Xqt Welcome, Normal 'NoPauseWelcome
Xqt Recive_lendayu62, Normal 'Recive data Lens>62 Alarm
'Xqt TCP_209_AreaSensor_As_Client, Normal 'Big_AreaSensor
'Xqt To_Robot, Normal
'Xqt tcpip_208_Jog, Normal
'Xqt tcpip_211_1Cycle, Normal
'Xqt Rbt_PC216, Normal
'Xqt Vision_Process, Normal
'Xqt Process, Normal
'Xqt Running_time, NoPause
'Xqt Current_POS, Normal 'NoPause
'Xqt Move_Current_POS, Normal 'NoPause
'Xqt Alignment_TCP_212, Normal 'Aligenmnet
'Xqt Welcome, Normal
'Xqt Recive_lendayu62, Normal
'Xqt File, Normal
Fend
1.05m
2025-05-28 15:15:50
NPointCalib
9
0
0
0.63482422
-999
0.14751892
-999
0.23190695
0.2328483
0.23237759
1327.212
1867.099
0
1499.212
1867.099
0
1671.212
1867.099
0
1671.212
2039.99
0
1499.212
2039.99
0
1327.212
2039.99
0
1327.212
2212.1089
0
1499.212
2212.1089
0
1671.212
2212.1089
0
-617.96002
210.513
-0.0572
-617.96002
171.04201
-0.0502
-617.96002
130.737
0.36719999
-658.18103
130.737
-0.033399999
-658.18103
171.04201
0.62330002
-658.18103
210.513
-0.0502
-698.29498
210.513
-0.044100001
-698.29498
171.04201
-0.0502
-698.29498
130.737
-0.050299998
-999
1
0
0
-999
0
0
-999
1.0378213e-008
-0.2328483
-183.20914
-0.23190695
1.3837616e-008
518.30267
0
0
1
迭代 V3
#11:06:57Current_POS_is: X:77Y:471Z:0U:-2 C:\Log\V55.txt
import time
import tkinter as tk
from tkinter import messagebox
from PIL import Image, ImageTk
import socket
import threading
from datetime import datetime
import logging
import subprocess # 确保导入 subprocess 库
import os
import pyautogui
from HslCommunication import MelsecMcNet
import json
import random
import math
import matplotlib
matplotlib.use('TkAgg') # 设置matplotlib后端
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import numpy as np
#from sklearn.linear_model import LinearRegression
# 修正后的全局变量声明
Response = 0
Offset_X = 0
Offset_Y = 0
Offset_U = 0
Ares_Sensor=None
#定义文件夹路径
folder_path = r'c:\Log' #C:\v5\Public_Release
# 检查文件夹是否存在,如果不存在则创建
if not os.path.exists(folder_path):
os.makedirs(folder_path)
# 设置日志配置
#logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# 新增格式化器,精确到毫秒
formatter = logging.Formatter(
fmt='%(asctime)s,%(msecs)03d - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# 设置基础日志配置
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s,%(msecs)03d - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# 如果已有其他处理器(如 StreamHandler),也应设置相同格式
class TextHandler(logging.Handler):
def __init__(self, widget):
super().__init__()
self.widget = widget
self.formatter = logging.Formatter(
fmt='%(asctime)s,%(msecs)03d - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
def emit(self, record):
# 检查 widget 是否存在且未被销毁
if self.widget and self.widget.winfo_exists():
msg = self.formatter.format(record)
self.widget.insert(tk.END, msg + '\n')
self.widget.yview_moveto(1)
class MyClass(tk.Frame):
def __init__(self, root, parent):
super().__init__(parent) # 初始化父类
self.root = root
self.parent = parent
class TCPClientApp:
def __init__(self, root, parent=None):
self.root = root
self.vision_client_socket = None
self.robot_client_socket = None
self.connected_to_vision = False
self.connected_to_robot = False
self.vision_ip = "127.0.0.1"
self.vision_port = 8888
self.robot_ip = "192.168.0.1" #192.168.0.1
self.robot_port = 2009 #2004
self.is_engineering_mode = True # 新增模式标志
# 新增 CONFIG_PATH 定义
self.CONFIG_PATH = r'C:\Log\config.json' # 配置文件路径
# 确保 INDUSTRIAL_COLORS 初始化在 setup_ui 调用之前
self.INDUSTRIAL_COLORS = {
'bg_main': '#404040', # 主背景色
'fg_main': '#FFFFFF', # 主前景色
'accent': '#FFA500', # 强调色
}
self.setup_ui()
self.setup_logging()
self.app3_process = None # 用于存储子进程的引用
self.parent = parent or root # 自动降级处理
self.plc = None
self.last_y79_state = False # 新增状态缓存
self.last_X2F_state = True # 新增状态缓存
self.setup_plc()
self.start_plc_monitoring()
self.init_plc_connection() # PLC运行
self.run_button = None
self.image_label = None
self.images = []
self.image_index = 0 # 确保在类初始化时设置默认值
###开启程序后自动启动项目
self.connect_to_vision()
self.connect_to_robot()
###开启程序后自动加载offset
self.load_settings()
# 修改窗口关闭事件处理
self.root.protocol("WM_DELETE_WINDOW", self.on_exit)
# 数据存储 Chart
self.history_data = {
'X': [],
'Y': [],
'U': [],
'timestamps': []
}
# 启动定时更新
self.update_interval = 888 # 3.888秒
self.root.after(self.update_interval, self.update_display)
self.update_history_chart()
self.home_received = False # 新增状态变量
def update_image(self):
# 检查图片列表是否存在且非空
if not hasattr(self, 'images') or not self.images:
logging.warning("No Pictures")
self.root.after(333, self.update_image) # 使用 after 安排下一次更新
return
# 检查 image_label 是否初始化
if not hasattr(self, 'image_label') or self.image_label is None:
logging.error("Picture Ini...")
# 使用保存的 right_frame 重新初始化
if hasattr(self, 'right_frame'):
self.create_right_panel(self.right_frame)
else:
logging.error("无法找到 right_frame,无法重新初始化 image_label")
self.root.after(333, self.update_image) # 避免直接递归调用
return
try:
img = self.images[self.image_index]
self.image_label.config(image=img)
self.image_label.image = img
logging.debug(f"成功更新图片索引 {self.image_index}")
except Exception as e:
logging.error(f"更新图片失败: {str(e)}")
self.root.after(1000, self.update_image) # 避免直接递归调用
return
# 更新索引并触发下一次更新
self.image_index = (self.image_index + 1) % len(self.images)
self.root.after(1000, self.update_image) # 使用 after 安排下一次更新
def toggle_mode(self):
self.is_engineering_mode = not self.is_engineering_mode
if self.is_engineering_mode:
self.mode_button.config(text="切换到运转模式")
self.show_engineering_mode()
else:
self.mode_button.config(text="切换到工程模式")
self.show_operation_mode()
def start_run(self):
# 运行按钮点击事件处理
pass
def update_history_chart(self):
"""更新历史趋势图"""
if not self.history_data['timestamps']:
return
# 限制显示8个数据点
keep_points = 8
x_data = self.history_data['timestamps'][-keep_points:]
self.line_x.set_data(x_data, self.history_data['X'][-keep_points:])
self.line_y.set_data(x_data, self.history_data['Y'][-keep_points:])
self.line_u.set_data(x_data, self.history_data['U'][-keep_points:])
# 自动调整坐标轴
self.ax.relim()
self.ax.autoscale_view()
# 显示最新值 - 工业风格
if self.history_data['X']:
latest_x = self.history_data['X'][-1]
latest_y = self.history_data['Y'][-1]
latest_u = self.history_data['U'][-1]
# 清除之前的文本
for text in self.ax.texts:
text.remove()
# 添加新的值显示 - 工业风格
self.ax.text(0.02, 0.95,
f"Last: X={latest_x:.3f} Y={latest_y:.3f} U={latest_u:.5f}",
transform=self.ax.transAxes,
fontsize=12, # 工业标准字号
color='#FFA500', # 工业橙色
bbox=dict(facecolor='#404040', alpha=0.69, edgecolor='#333333')) # 工业灰色背景
# 显示在上还是曲线在上
self.chart_canvas.draw()
#
def toggle_mode(self):
self.is_engineering_mode = not self.is_engineering_mode
if self.is_engineering_mode:
self.mode_button.config(text="切换到运转模式")
self.show_engineering_mode()
else:
self.mode_button.config(text="切换到工程模式")
self.show_operation_mode()
def start_run(self):
# 运行按钮点击事件处理
pass
def update_display(self):
"""定时更新显示"""
try:
# 更新仪表盘
self.update_gauges()
# 更新趋势图
self.update_history_chart()
# 确保图表窗口仍然存在
if hasattr(self, 'chart_window') and self.chart_window.winfo_exists():
# 获取当前数据点限制
keep_points = getattr(self, 'point_limit', 8)
# 限制显示的数据点数量
x_data = self.history_data['timestamps'][-keep_points:]
# 更新X轴数据
self.line_x.set_data(x_data, self.history_data['X'][-keep_points:])
# 更新Y轴数据
self.line_y.set_data(x_data, self.history_data['Y'][-keep_points:])
# 更新U轴数据
self.line_u.set_data(x_data, self.history_data['U'][-keep_points:])
# 自动调整坐标轴
ax = self.line_x.axes
ax.relim()
ax.autoscale_view()
# 更新动态标题 - 工业风格
if self.history_data['X']:
latest_x = self.history_data['X'][-1]
latest_y = self.history_data['Y'][-1]
latest_u = self.history_data['U'][-1]
# 清除之前的文本
for text in ax.texts:
text.remove()
# 添加新的值显示 - 工业风格
ax.text(0.02, 0.95,
f"Last: X={latest_x:.3f} Y={latest_y:.3f} U={latest_u:.5f}",
transform=ax.transAxes,
fontsize=12,
color='#FFA500',
bbox=dict(facecolor='#404040', alpha=0.69, edgecolor='#333333'))
# 重新绘制图表
ax.figure.canvas.draw()
finally:
# 确保图表窗口仍然存在时才继续定时器
if hasattr(self, 'chart_window') and self.chart_window.winfo_exists():
self.root.after(1000, self.update_display)
def update_static_chart(self):
"""更新静态图表显示"""
try:
# 获取数据点限制
keep_points = 5 # 固定显示最后5个数据点
# 如果没有历史数据,直接返回
if not self.history_data or not self.history_data['timestamps']:
return
# 限制显示的数据点数量
x_data = self.history_data['timestamps'][-keep_points:]
# 更新X轴数据
self.line_x.set_data(x_data, self.history_data['X'][-keep_points:])
# 更新Y轴数据
self.line_y.set_data(x_data, self.history_data['Y'][-keep_points:])
# 更新U轴数据
self.line_u.set_data(x_data, self.history_data['U'][-keep_points:])
# 自动调整坐标轴
ax = self.line_x.axes
ax.relim()
ax.autoscale_view()
# 更新动态标题 - 工业风格
if self.history_data['X']:
latest_x = self.history_data['X'][-1]
latest_y = self.history_data['Y'][-1]
latest_u = self.history_data['U'][-1]
# 清除之前的文本
for text in ax.texts:
text.remove()
# 添加新的值显示 - 工业风格
ax.text(0.02, 0.95,
f"Last: X={latest_x:.3f} Y={latest_y:.3f} U={latest_u:.5f}",
transform=ax.transAxes,
fontsize=12,
color='#FFA500',
bbox=dict(facecolor='#404040', alpha=0.69, edgecolor='#333333'))
# 重新绘制图表
ax.figure.canvas.draw()
finally:
# 静态数据只需更新一次,不需要定时器
pass
# 确保仪表盘也更新
#self.update_gauges()
def setup_history_chart(self, ax):
"""初始化历史趋势图"""
self.line_x, = ax.plot([], [], color='#FF0000', linewidth=2, label='X_Pos', marker='o', markersize=3)
self.line_y, = ax.plot([], [], color='#00FF00', linewidth=2, label='Y_Pos', marker='o', markersize=3)
self.line_u, = ax.plot([], [], color='#00B0F0', linewidth=2, label='U_Pos', marker='o', markersize=3)
# 配置坐标轴和图例 - 工业风格
ax.set_title("XYU_Chart", fontsize=14, color='#FFFFFF', pad=20)
ax.set_xlabel("Time", fontsize=12, color='#CCCCCC')
ax.set_ylabel("Value(mm)", fontsize=12, color='#CCCCCC')
ax.grid(True, color='#555555', linestyle='--', alpha=0.7)
ax.legend(loc='upper right', fontsize=10)
# 设置背景色
ax.set_facecolor('#333333')
ax.figure.patch.set_facecolor('#404040')
# 设置刻度颜色
ax.tick_params(axis='x', colors='#CCCCCC')
ax.tick_params(axis='y', colors='#CCCCCC')
def update_history_chart(self):
"""更新历史趋势图"""
if not self.history_data['timestamps']:
return
# 限制显示8个数据点
keep_points = 8
x_data = self.history_data['timestamps'][-keep_points:]
# 确保所有三条曲线都正确更新
self.line_x.set_data(x_data, self.history_data['X'][-keep_points:])
self.line_y.set_data(x_data, self.history_data['Y'][-keep_points:])
self.line_u.set_data(x_data, self.history_data['U'][-keep_points:])
# 自动调整坐标轴
self.ax.relim()
self.ax.autoscale_view()
# 显示最新值 - 工业风格
if self.history_data['X']:
latest_x = self.history_data['X'][-1]
latest_y = self.history_data['Y'][-1]
latest_u = self.history_data['U'][-1]
# 清除之前的文本
for text in self.ax.texts:
text.remove()
# 添加新的值显示 - 工业风格
self.ax.text(0.02, 0.95,
f"Last: X={latest_x:.3f} Y={latest_y:.3f} U={latest_u:.5f}",
transform=self.ax.transAxes,
fontsize=12,
color='#FFA500',
bbox=dict(facecolor='#404040', alpha=0.69, edgecolor='#333333'))
# 确保图表刷新
self.chart_canvas.draw()
def setup_ui(self):
# 主窗口背景色
self.root.configure(bg=self.INDUSTRIAL_COLORS['bg_main'])
self.root.title("Design by Tim")
self.root.geometry("1924x968") #Display Pix_1024 768 Windows
# Grid weights for resizing behavior
self.root.grid_columnconfigure(0, weight=1)
self.root.grid_columnconfigure(1, weight=2)
self.root.grid_columnconfigure(2, weight=1)
self.root.grid_rowconfigure(0, weight=1)
self.root.grid_rowconfigure(1, weight=1)
# Left Frame
left_frame = tk.Frame(self.root)
left_frame.grid(row=0, column=0, padx=5, pady=5, sticky="nsew")
self.create_left_panel(left_frame)
# Right Frame
right_frame = tk.Frame(self.root)
right_frame.grid(row=0, column=2, padx=5, pady=5, sticky="nsew")
self.create_right_panel(right_frame)
# Bottom Frame
bottom_frame = tk.Frame(self.root, bg='lightgray')
bottom_frame.grid(row=1, column=0, columnspan=3, padx=5, pady=5, sticky="nsew")
self.create_bottom_panel(bottom_frame)
##
def load_images(self):
path = r'C:\Log\Picture'
# 新增:检查目录是否存在并记录日志
if not os.path.exists(path):
logging.error(f"图片文件夹路径不存在: {path}")
self.root.after(3000, self.load_images) # 3秒后重试(替换递归)
return
if not os.path.isdir(path):
logging.error(f"指定路径不是有效的文件夹: {path}")
self.root.after(3000, self.load_images) # 3秒后重试(替换递归)
return
# 新增:记录目录下所有文件(排查文件名问题)
dir_files = os.listdir(path)
logging.debug(f"目录 {path} 下的文件列表: {dir_files}")
extensions = ['.jpg', '.jpeg', '.png', '.bmp', '.gif']
self.images = [] # 清空旧数据
for ext in extensions:
for file in dir_files: # 使用已获取的文件列表(避免重复调用os.listdir)
if file.lower().endswith(ext):
img_path = os.path.join(path, file)
try:
# 新增:记录具体加载的文件
logging.info(f"Retry 2 Loading: {img_path}")
img = Image.open(img_path)
img.thumbnail((456, 456)) # 缩略图适配显示
self.images.append(ImageTk.PhotoImage(img))
logging.debug(f"Loading : {img_path}")
except Exception as e:
# 新增:记录具体错误(如文件被占用、格式损坏)
logging.error(f"Loading {file}: {str(e)} NG ")
# 新增:记录最终加载结果
if not self.images:
logging.warning(f"未找到有效图片文件(共扫描 {len(dir_files)} 个文件),3秒后重新加载...")
self.root.after(3000, self.load_images) # 用after代替递归,避免栈溢出
else:
logging.info(f"Loading {len(self.images)} Pictures")
##
def create_chart_area(self, parent=None):
"""显示为独立弹窗的工业级数据显示面板"""
# 创建新窗口
chart_window = tk.Toplevel(self.root)
chart_window.title("Chart")
# 设置窗口大小和位置(居中显示)
window_width = 1000
window_height = 600
screen_width = chart_window.winfo_screenwidth()
screen_height = chart_window.winfo_screenheight()
x = (screen_width - window_width) // 2
y = (screen_height - window_height) // 2
chart_window.geometry(f'{window_width}x{window_height}+{x}+{y}')
# 使用与show_animation相同的框架结构
fig = Figure(figsize=(8, 4), dpi=60)
ax = fig.add_subplot(111)
# 初始化三条曲线 - 使用工业颜色
self.line_x, = ax.plot([], [], color='#FF0000', linewidth=2, label='X_Pos') # 红色
self.line_y, = ax.plot([], [], color='#00FF00', linewidth=2, label='Y_Pos') # 绿色
self.line_u, = ax.plot([], [], color='#00B0F0', linewidth=2, label='U_Pos') # 科技蓝
# 配置坐标轴和图例 - 工业风格
ax.set_title("Real", fontsize=14, color='#FFFFFF', pad=20)
ax.set_xlabel("Time", fontsize=12, color='#CCCCCC')
ax.set_ylabel("Value(mm)", fontsize=12, color='#CCCCCC')
ax.grid(True, color='#555555', linestyle='--', alpha=0.7)
ax.legend(loc='upper right', fontsize=10)
# 设置背景色
ax.set_facecolor('#333333')
fig.patch.set_facecolor('#404040')
# 设置刻度颜色
ax.tick_params(axis='x', colors='#CCCCCC')
ax.tick_params(axis='y', colors='#CCCCCC')
# 嵌入到Tkinter
canvas = FigureCanvasTkAgg(fig, master=chart_window)
canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
# 创建仪表盘框架
gauge_frame = tk.Frame(chart_window, bg='#404040')
gauge_frame.pack(side=tk.BOTTOM, fill=tk.X, pady=10)
# X值仪表
self.x_gauge = self.create_gauge(gauge_frame, "X Axis")
# Y值仪表
self.y_gauge = self.create_gauge(gauge_frame, "Y Axis")
# U值仪表
self.u_gauge = self.create_gauge(gauge_frame, "U Axis")
# 创建控制面板
control_frame = tk.Frame(chart_window)
control_frame.pack(side=tk.BOTTOM, fill=tk.X, pady=5)
# 添加重置按钮
reset_button = tk.Button(control_frame, text="Reset Data",
command=self.reset_chart_data, width=10)
reset_button.pack(side=tk.LEFT, padx=5)
# 添加数据点数量设置
point_frame = tk.Frame(control_frame)
point_frame.pack(side=tk.LEFT, padx=5)
tk.Label(point_frame, text="Data Points:").pack(side=tk.LEFT)
self.point_entry = tk.Entry(point_frame, width=5)
self.point_entry.pack(side=tk.LEFT)
self.point_entry.insert(0, "5") # 默认显示5个数据点
apply_point_button = tk.Button(point_frame, text="Apply",
command=lambda: self.apply_point_limit_change(), width=5)
apply_point_button.pack(side=tk.LEFT, padx=2)
# 添加关闭按钮
close_button = tk.Button(control_frame, text="Close",
command=chart_window.destroy, width=10)
close_button.pack(side=tk.RIGHT, padx=5)
# 初始化历史数据存储
self.history_data = {
'X': [],
'Y': [],
'U': [],
'timestamps': []
}
# 读取文件中的最后5条记录
#file_path = r'C:\Log\log_His.txt'
file_path = r'C:\Log\Vision_Data_Log6_11.txt' ##Vision_Data_Log6_11.txt
trajectory_data = self.read_last_n_records(file_path, 5)
# 如果读取到数据,更新历史数据
if trajectory_data:
# 计算时间戳(假设每条记录间隔固定为1秒)
now = time.time()
timestamps = [now + i for i in range(len(trajectory_data))]
# 更新历史数据
for (x, y, z), t in zip(trajectory_data, timestamps):
self.history_data['X'].append(x)
self.history_data['Y'].append(y)
self.history_data['U'].append(z)
self.history_data['timestamps'].append(t)
# 初始化图表数据
self.setup_history_chart(ax)
# 创建并启动静态更新
self.update_static_chart()
# 在此处调用 draw()
self.chart_canvas.draw()
def setup_history_chart(self, parent):
"""初始化历史趋势图"""
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
def reset_chart_data(self):
"""重置图表数据"""
# 清空历史数据
self.history_data['X'] = []
self.history_data['Y'] = []
self.history_data['U'] = []
self.history_data['timestamps'] = []
# 重新读取文件中的最后5条记录
file_path = r'C:\Log\log_His.txt'
trajectory_data = self.read_last_n_records(file_path, 5)
# 如果读取到数据,更新历史数据
if trajectory_data:
# 计算时间戳(假设每条记录间隔固定为1秒)
now = time.time()
timestamps = [now + i for i in range(len(trajectory_data))]
# 更新历史数据
for (x, y, z), t in zip(trajectory_data, timestamps):
self.history_data['X'].append(x)
self.history_data['Y'].append(y)
self.history_data['U'].append(z)
self.history_data['timestamps'].append(t)
# 更新静态图表
self.update_static_chart()
# 日志记录
logging.info("图表数据已重置并重新加载")
def reset_chart_data(self):
"""重置图表数据"""
# 初始化历史数据存储
self.history_data = {
'X': [],
'Y': [],
'U': [],
'timestamps': []
}
# 读取文件中的最后5条记录
file_path = r'C:\Log\log_His.txt'
trajectory_data = self.read_last_n_records(file_path, 5)
# 如果读取到数据,更新历史数据
if trajectory_data:
# 计算时间戳(假设每条记录间隔固定为1秒)
now = time.time()
timestamps = [now + i for i in range(len(trajectory_data))]
# 更新历史数据
for (x, y, z), t in zip(trajectory_data, timestamps):
self.history_data['X'].append(x)
self.history_data['Y'].append(y)
self.history_data['U'].append(z)
self.history_data['timestamps'].append(t)
# 更新静态图表
self.update_static_chart()
# 日志记录
logging.info("图表数据已重置并重新加载")
def update_chart_style(self):
"""更新图表样式设置"""
# 设置坐标轴和图例 - 工业风格
self.ax.set_title("Real", fontsize=14, color='#FFFFFF', pad=20)
self.ax.set_xlabel("Time", fontsize=12, color='#CCCCCC')
self.ax.set_ylabel("Value(mm)", fontsize=12, color='#CCCCCC')
self.ax.grid(True, color='#555555', linestyle='--', alpha=0.7)
self.ax.legend(loc='upper right', fontsize=10)
# 设置背景色
self.ax.set_facecolor('#333333')
self.fig.patch.set_facecolor('#404040')
# 设置刻度颜色
self.ax.tick_params(axis='x', colors='#CCCCCC')
self.ax.tick_params(axis='y', colors='#CCCCCC')
# 重新绘制图表
self.ax.figure.canvas.draw()
# 更新图表样式
self.update_chart_style()
def create_left_panel(self, parent):
# 创建带滚动条的框架
left_container = tk.Frame(parent)
left_container.pack(fill=tk.BOTH, expand=True)
canvas = tk.Canvas(left_container, bg='#FFFFFF')
scrollbar = tk.Scrollbar(left_container, orient="vertical", command=canvas.yview)
scrollable_frame = tk.Frame(canvas, bg='#FFFFFF')
scrollable_frame.bind(
"",
lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
)
canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
canvas.configure(yscrollcommand=scrollbar.set)
# 设置左面板背景
left_frame = tk.Frame(scrollable_frame, bg='#FFFFFF')
left_frame.pack(fill=tk.BOTH, expand=True, padx=(5, 0)) # 左移调整并减小宽度
# MAIN标题,整体变小
main_title = tk.Label(left_frame,
text="Main",
font=("Arial", 38, "bold"),
fg="black",
bg="#FAFAD2",
anchor='center') # 标题居中对齐
main_title.pack(side=tk.TOP, pady=(53, 30), fill=tk.X)
# Launch Vision 按钮
launch_button = tk.Button(left_frame, text="Launch Vision", command=self.launch_application,
bg="#F0F552",
fg="black",
width=18, # 修改按钮宽度为原来的一半
font=("Segoe UI", 20))
launch_button.pack(pady=(10, 50), anchor='w', padx=30) # 左对齐并减小间距
# Start 按钮
start_button = tk.Button(left_frame, text="Start", command=self.start_auto_command,
bg="#32CD32",
fg="white",
width=18, # 修改按钮宽度为原来的一半
font=("Segoe UI", 20))
start_button.pack(pady=(0, 30), anchor='w', padx=30) # 左对齐并减小间距
###新增空白区域
# 空白区域
blank_frame = tk.Frame(left_frame, bg='#FFFFFF', height=10) # 高度为10像素
blank_frame.pack(fill=tk.X, pady=256) # 填充整个宽度并增加间距
# 水平按钮行框架(新增)
button_row_frame = tk.Frame(left_frame, bg='#FFFFFF')
button_row_frame.pack(pady=10, anchor='w', padx=5) # 整体间距
# 3D 按钮(修改父容器为 button_row_frame)
animation_button = tk.Button(button_row_frame, text="3D", command=self.show_animation,
bg="#00B0F0",
fg="white",
width=8, # 修改按钮宽度为原来的一半
font=("Segoe UI", 12))
animation_button.pack(side=tk.LEFT, padx=15) # 水平排列
# His Chart 按钮(修改父容器为 button_row_frame)
chart_button = tk.Button(button_row_frame, text="His Chart", command=self.create_chart_area,
bg="#00B0F0",
fg="white",
width=8, # 修改按钮宽度为原来的一半
font=("Segoe UI", 12))
chart_button.pack(side=tk.LEFT, padx=15) # 水平排列
# Log 按钮(修改父容器为 button_row_frame)
new_window_button = tk.Button(button_row_frame, text="Log", command=self.show_new_window,
bg="#00B0F0",
fg="white",
width=8, # 修改按钮宽度为原来的一半
font=("Segoe UI", 12))
new_window_button.pack(side=tk.LEFT, padx=15) # 水平排列
# 连接按钮(Vision和Robot)
self._create_connection_buttons(left_frame, "Vision", self.connect_to_vision, self.disconnect_from_vision)
self._create_connection_buttons(left_frame, "Robot", self.connect_to_robot, self.disconnect_from_robot)
# 备用端口按钮(PLC、Falco、Robot)
PLC_button = tk.Button(left_frame, text="PLC Port (Backup)", command=self.start_PLC_command,
bg="#CDCDCD",
fg="gray",
font=("Segoe UI", 12))
PLC_button.pack(side=tk.BOTTOM, fill=tk.X)
Falco_button = tk.Button(left_frame, text="Falco Port (Backup)", command=self.start_Falco_command,
bg="#CDCDCD",
fg="gray",
font=("Segoe UI", 12))
Falco_button.pack(side=tk.BOTTOM, fill=tk.X)
Robot_button = tk.Button(left_frame, text="Robot Port (Backup)", command=self.start_Robot_command,
bg="#CDCDCD",
fg="gray",
font=("Segoe UI", 12))
Robot_button.pack(side=tk.BOTTOM, fill=tk.X)
canvas.pack(side="left", fill="both", expand=True)
# ---新---区域22
blank_frame = tk.Frame(left_frame, bg='#FFFFFF', height=10) # 高度为10像素
blank_frame.pack(fill=tk.X, pady=120) # 填充整个宽度并增加间距
# ---新---区域33
blank_frame = tk.Frame(left_frame, bg='#FFFFFF', height=10) # 高度为10像素
blank_frame.pack(fill=tk.X, pady=120) # 填充整个宽度并增加间距
# 修改滚动条初始状态为隐藏,并绑定鼠标事件
scrollbar.place(relx=1, rely=0, relheight=1, anchor='ne')
scrollbar.lower() # 初始隐藏
left_container.bind("", lambda _: scrollbar.lift()) # 鼠标进入时显示
left_container.bind("", lambda _: scrollbar.lower()) # 鼠标离开时隐藏
def on_exit(self):
"""处理窗口关闭事件"""
# 弹出确认对话框,确保在主线程中执行
if messagebox.askokcancel("退出", "确定要退出程序吗?", parent=self.root):
logging.info("用户确认退出程序,开始清理资源...")
try:
# 保存配置
self.save_settings()
logging.info("配置已自动保存")
# 断开与 Vision 的连接
if self.connected_to_vision:
self.disconnect_from_vision()
logging.info("已断开与 Vision 的连接")
# 断开与 Robot 的连接
if self.connected_to_robot:
self.disconnect_from_robot()
logging.info("已断开与 Robot 的连接")
# 终止子进程
if hasattr(self, 'app3_process') and self.app3_process:
self.terminate_application3()
logging.info("已终止子进程")
# 清理日志处理器
if hasattr(self, 'new_window_handler'):
logger = logging.getLogger()
logger.removeHandler(self.new_window_handler)
logging.info("已移除日志处理器")
except Exception as e:
logging.error(f"退出时发生错误: {str(e)}")
messagebox.showerror("错误", f"退出时发生错误: {str(e)}")
finally:
# 安全关闭主窗口
self.root.destroy()
logging.info("主窗口已关闭")
else:
logging.info("用户取消退出程序")
def show_new_window(self):
"""显示一个新的弹窗"""
new_window = tk.Toplevel(self.root)
new_window.title("Log")
# 设置窗口大小和位置(居中显示)
window_width = 800
window_height = 600
screen_width = new_window.winfo_screenwidth()
screen_height = new_window.winfo_screenheight()
x = (screen_width - window_width) // 2
y = (screen_height - window_height) // 2
new_window.geometry(f'{window_width}x{window_height}+{x}+{y}')
# 创建 Text 组件用于显示日志
self.new_window_text = tk.Text(new_window, wrap=tk.WORD, bg='black', fg='white', font=("Helvetica", 18))
self.new_window_text.pack(fill=tk.BOTH, expand=True)
close_button = tk.Button(new_window, text="Close", command=lambda: self.close_new_window(new_window), width=10)
close_button.pack(pady=10)
# 获取右侧日志区域的全部内容
log_content = self.log_text.get("1.0", tk.END).strip()
# 将日志内容插入到新窗口的 Text 组件中
if log_content:
self.new_window_text.insert(tk.END, log_content)
self.new_window_text.yview_moveto(1) # 滚动到最新位置
# 添加日志处理器
self.new_window_handler = TextHandler(self.new_window_text)
logger = logging.getLogger()
logger.addHandler(self.new_window_handler)
def close_new_window(self, window):
"""关闭新窗口并移除日志处理器"""
if hasattr(self, 'new_window_handler'):
logger = logging.getLogger()
logger.removeHandler(self.new_window_handler)
window.destroy()
def update_new_window_log(self, record):
"""更新新窗口中的日志内容"""
if hasattr(self, 'new_window_text') and self.new_window_text.winfo_exists():
msg = self.formatter.format(record)
self.new_window_text.insert(tk.END, msg + '\n')
self.new_window_text.yview_moveto(1)
def setup_logging(self):
text_handler = TextHandler(self.log_text)
logger = logging.getLogger()
logger.addHandler(text_handler)
# 添加新的处理程序以支持新窗口日志
if hasattr(self, 'new_window_text'):
new_window_handler = TextHandler(self.new_window_text)
logger.addHandler(new_window_handler)
def _create_connection_buttons(self, parent, label_text, connect_cmd, disconnect_cmd):
# 创建连接按钮框架
button_frame = tk.Frame(parent)
button_frame.pack(pady=5)
connect_button = tk.Button(button_frame, text=f"Con. {label_text}", command=connect_cmd, width=14, height=1)
connect_button.pack(side=tk.LEFT, anchor='center', padx=5)
status_indicator = tk.Frame(button_frame, width=20, height=20, bg='red')
setattr(self, f"{label_text.lower()}_status_indicator", status_indicator) # Store as attribute
status_indicator.pack(side=tk.LEFT, anchor='center', padx=(0, 5))
disconnect_button = tk.Button(button_frame, text=f"Dis. {label_text}", command=disconnect_cmd, width=14, height=1)
disconnect_button.pack(side=tk.LEFT, anchor='center', padx=5)
def create_middle_panel(self, parent):
# 中间主框架
middle_frame = tk.Frame(parent, bg='#FFFFFF') #OLD #CCCCCC
middle_frame.pack(fill=tk.BOTH, expand=True)
# 修改 create_right_panel 方法中的标题和区域标识
def create_right_panel(self, parent):
# 保存 right_frame 作为类属性,避免重复初始化
self.right_frame = tk.Frame(parent, bg='#FFFFFF')
self.right_frame.pack(fill=tk.BOTH, expand=True)
# 清除之前的 image_title(如果存在)
if hasattr(self, 'image_title') and self.image_title:
self.image_title.destroy()
# 图片标题
self.image_title = tk.Label(self.right_frame,
text="Picture",
font=("Arial", 38, "bold"),
fg="black",
bg="#FAFAD2",
anchor='center')
self.image_title.pack(pady=(15, 30), fill=tk.X)
# 创建图片显示区域
self.image_label = tk.Label(self.right_frame, bg='white')
self.image_label.pack(fill=tk.BOTH, expand=True, padx=328, pady=10) #PosTimTimTim
# 加载图片
self.load_images()
# 确保 image_index 初始化
if not hasattr(self, 'image_index'):
logging.warning("image_index 未初始化,正在修复...")
self.image_index = 0
# 开始更新图片
self.root.after(333, self.update_image) # 使用 after 安排首次更新
def update_image(self):
# 检查图片列表是否存在且非空
if not hasattr(self, 'images') or not self.images:
logging.warning("Ini...")
self.root.after(333, self.update_image)
return
# 检查 image_label 是否初始化
if not hasattr(self, 'image_label') or self.image_label is None:
logging.error("Picture Ini...---")
# 使用保存的 right_frame 重新初始化
if hasattr(self, 'right_frame'):
self.create_right_panel(self.right_frame)
else:
logging.error("无法找到 right_frame,无法重新初始化 image_label")
self.root.after(333, self.update_image) # 避免直接递归调用
return
try:
img = self.images[self.image_index]
self.image_label.config(image=img)
self.image_label.image = img
logging.debug(f"成功更新图片索引 {self.image_index}")
except Exception as e:
try:
logging.error(f"更新图片失败: {str(e)}")
except RecursionError:
pass # 避免日志记录引发递归错误
self.root.after(333, self.update_image) # 避免直接递归调用
return
# 更新索引并触发下一次更新
self.image_index = (self.image_index + 1) % len(self.images)
self.root.after(333, self.update_image) # 使用 after 安排下一次更新
def load_default_image111(self):
"""加载默认图片到右侧显示区域"""
image_folder = r'C:\Log\Picture' # 默认图片文件夹路径
if not os.path.exists(image_folder):
logging.warning(f"图片文件夹路径不存在: {image_folder}")
return
images = []
for file in os.listdir(image_folder):
if file.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp', '.gif')):
img_path = os.path.join(image_folder, file)
try:
img = Image.open(img_path)
img.thumbnail((800, 600)) # 自适应缩放
images.append(ImageTk.PhotoImage(img))
except Exception as e:
#logging.error(f"无法加载图片 {img_path}: {str(e)}")
logging.error(f"Loading Picture NG... {img_path}: {str(e)}")
if images:
if self.image_label: # 确保 image_label 存在
self.image_label.config(image=images[0]) # 显示第一张图片
self.image_label.image = images[0]
#logging.info(f"成功加载图片: {len(images)} 张")
logging.info(f"Read: {len(images)} Pictures")
else:
logging.warning("未找到有效图片文件")
def create_bottom_panel(self, parent):
# 修改后的偏移量输入和写入按钮布局
offset_frame = tk.Frame(parent, bg='lightgray')
offset_frame.pack(fill=tk.X, pady=5, padx=5)
# X输入
tk.Label(offset_frame, text="X:", bg='lightgray', font=("Helvetica", 12)).grid(row=0, column=0, padx=2)
self.custom_command_entry5 = tk.Entry(offset_frame, width=8, font=("Helvetica", 12))
self.custom_command_entry5.grid(row=0, column=1, padx=2)
# Y输入
tk.Label(offset_frame, text="Y:", bg='lightgray', font=("Helvetica", 12)).grid(row=0, column=2, padx=2)
self.custom_command_entry6 = tk.Entry(offset_frame, width=8, font=("Helvetica", 12))
self.custom_command_entry6.grid(row=0, column=3, padx=2)
# U输入
tk.Label(offset_frame, text="U:", bg='lightgray', font=("Helvetica", 12)).grid(row=0, column=4, padx=2)
self.custom_command_entry7 = tk.Entry(offset_frame, width=8, font=("Helvetica", 12))
self.custom_command_entry7.grid(row=0, column=5, padx=2)
# 统一的写入按钮 ###Tim
write_button = tk.Button(offset_frame, text="Offset_Write", command=self.write_all_offsets,
bg="#32CD32",
fg="white",
width=12,
font=("Segoe UI", 12))
write_button.grid(row=0, column=6, padx=10)
#Enter 1 command
custom_command_frame = tk.Frame(parent)
custom_command_frame.pack(side=tk.TOP, pady=1, fill=tk.X, expand=True)
custom_command_label = tk.Label(custom_command_frame, text="Enter Vision Command:", font=("Helvetica", 1))
custom_command_label.pack(side=tk.LEFT, padx=5)
self.custom_command_entry1 = tk.Entry(custom_command_frame, font=("Helvetica", 1), fg="purple")
self.custom_command_entry1.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
send_command_button = tk.Button(custom_command_frame, text="Send", command=self.send_custom_command1, font=("Helvetica", 1))
send_command_button.pack(side=tk.LEFT, padx=5)
# 新增日志显示区域
log_frame = tk.Frame(parent, bg='black')
log_frame.pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
# 调整日志区域高度为原来的一半
self.log_text = tk.Text(log_frame, wrap=tk.WORD, bg='black', fg='white', font=("Helvetica", 12), height=10)
self.log_text.pack(fill=tk.BOTH, expand=True)
#Enter 2 command
custom_command_frame2 = tk.Frame(parent)
custom_command_frame2.pack(side=tk.TOP, pady=1, fill=tk.X, expand=True)
custom_command_label = tk.Label(custom_command_frame2, text="Enter Robot Command:", font=("Helvetica", 1))
custom_command_label.pack(side=tk.LEFT, padx=5)
self.custom_command_entry2 = tk.Entry(custom_command_frame2, font=("Helvetica", 1), fg="purple")
self.custom_command_entry2.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
send_command_button2 = tk.Button(custom_command_frame2, text="Send", command=self.send_custom_command2, font=("Helvetica", 1))
send_command_button2.pack(side=tk.LEFT, padx=5)
#Enter 3 command
custom_command_frame3= tk.Frame(parent)
custom_command_frame3.pack(side=tk.TOP, pady=1, fill=tk.X, expand=True)
custom_command_label = tk.Label(custom_command_frame3, text="Enter Send To Vision Command:", font=("Helvetica", 1))
custom_command_label.pack(side=tk.LEFT, padx=5)
self.custom_command_entry3 = tk.Entry(custom_command_frame3, font=("Helvetica", 1), fg="purple")
self.custom_command_entry3.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
send_command_button3 = tk.Button(custom_command_frame3, text="Send", command=self.send_custom_command3, font=("Helvetica", 1))
send_command_button3.pack(side=tk.LEFT, padx=5)
# 移除发送按钮并绑定 Enter 键事件到输入框
self.custom_command_entry3.bind('', lambda event: self.send_custom_command3())
def _validate_number(self, value):
"""数值输入验证"""
if value == "" or value == "-":
return True
try:
float(value)
return True
except ValueError:
return False
def setup_logging(self):
text_handler = TextHandler(self.log_text)
logger = logging.getLogger()
logger.addHandler(text_handler)
def connect_to_vision(self):
try:
self.vision_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.vision_client_socket.settimeout(65536)
self.vision_client_socket.connect((self.vision_ip, self.vision_port))
self.connected_to_vision = True
self.update_status_indicator(self.vision_status_indicator, 'green', "Connected to Vision")
logging.info(f"Connected to Vision at {self.vision_ip}:{self.vision_port}")
threading.Thread(target=self.receive_data, args=(self.vision_client_socket, 'vision'), daemon=True).start()
except Exception as e:
self.connected_to_vision = False
self.update_status_indicator(self.vision_status_indicator, 'red', f"Failed to connect to Vision: {e}")
logging.error(f"Failed to connect to Vision: {e}")
if self.vision_client_socket:
self.vision_client_socket.close()
def disconnect_from_vision(self):
if self.connected_to_vision:
self.vision_client_socket.close()
self.connected_to_vision = False
self.update_status_indicator(self.vision_status_indicator, 'red', "Disconnected from Vision")
logging.info("Disconnected from Vision")
##OutofRang
def Out_Of_Range_from_vision(self):
self.update_status_indicator2(self.vision_status_indicator, 'red', "Out_Of_Range_±10°")
logging.info("Out_Of_Range_from_vision_±10°")
def Out_Of_Range_from_vision2(self):
self.update_status_indicator2(self.vision_status_indicator, 'red', "Out_Of_Range_±90°")
logging.info("Out_Of_Range_from_vision_±90°")
##OutofRang
##Robot at Home
def Home_POS(self):
self.update_status_indicator2(self.vision_status_indicator, 'red', "Not Match,Pls Check and Put it Again,\n Then Connect Vision Again ")
logging.info("Not Match,Pls Check and Put it Again ...")
##Robot at Home
def ERROR_(self):
self.update_status_indicator2(self.robot_status_indicator, 'red', "ERROR,PLS Connect Robot\n\n Then, In Robot Software, Press Start to Run...")
logging.info("ERROR,PLS Connect Robot")
def Motor_Off(self):
self.update_status_indicator2(self.robot_status_indicator, 'red', " Area Semnsor \n\n Area Semnsor \n\nArea Semnsor \n\nThen, In Robot Software, Press Start to Run...")
logging.info("ERROR,Area Semnsor")
def connect_to_robot(self):
try:
self.robot_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.robot_client_socket.settimeout(65536)
self.robot_client_socket.connect((self.robot_ip, self.robot_port))
self.connected_to_robot = True
self.update_status_indicator(self.robot_status_indicator, 'green', "Connected to Robot")
logging.info(f"Connected to Robot at {self.robot_ip}:{self.robot_port}")
threading.Thread(target=self.receive_data, args=(self.robot_client_socket, 'robot'), daemon=True).start()
except Exception as e:
self.connected_to_robot = False
self.update_status_indicator(self.robot_status_indicator, 'red', f"Failed to connect to Robot: {e}")
logging.error(f"Failed to connect to Robot: {e}")
if self.robot_client_socket:
self.robot_client_socket.close()
def disconnect_from_robot(self):
if self.connected_to_robot:
self.robot_client_socket.close()
self.connected_to_robot = False
self.update_status_indicator(self.robot_status_indicator, 'red', "Disconnected from Robot")
logging.info("Disconnected from Robot")
def send_custom_command1(self):
command = self.custom_command_entry1.get()
if command:
logging.info(f"Send_Vision_Command2Start: {command}")
self.send_vision_command(command)
# 更新图片逻辑
self.load_images() # 重新加载图片
self.update_image() # 更新图片显示
def send_custom_command2(self):
command = self.custom_command_entry2.get()
if command:
logging.info(f"send_robot_command: {command}")
self.send_robot_command(command)
#self.custom_command_entry.delete(0, tk.END)
def send_custom_command3(self):
global Response # 使用全局变量
if Response == 'Camera_not_Match_Picture' :
##print("666",Response)
time.sleep(0.005)
else:
#global Response # 使用全局变量
#command = self.custom_command_entry2.get()
command = str(Response) # 获取全局变量 RES 的值作为命令内容
if command:
logging.info(f"Recive_Vision/Robot_Data_is_{command}")
logging.info(f"Then_Auto_send_Vision_Pos2robot")
self.send_robot_command(command)
#self.custom_command_entry.delete(0, tk.END)
##
def send_custom_command6_Offset(self):
command = self.custom_command_entry5.get()
if command:
logging.info(f"send_robot_command_X_Offset: {command}")
self.send_robot_command_Offset(command)
#self.custom_command_entry.delete(0, tk.END)
command = self.custom_command_entry6.get()
if command:
logging.info(f"send_robot_command_Y_Offset: {command}")
self.send_robot_command_Offset(command)
#self.custom_command_entry.delete(0, tk.END)
command = self.custom_command_entry7.get()
if command:
logging.info(f"send_robot_command_Z_Offset: {command}")
self.send_robot_command_Offset(command)
#self.custom_command_entry.delete(0, tk.END)
def send_x_offset(self):
self._send_offset("X", self.custom_command_entry5.get())
def send_y_offset(self):
self._send_offset("Y", self.custom_command_entry6.get())
def send_u_offset(self):
self._send_offset("U", self.custom_command_entry7.get())
def _send_offset(self, axis_type, value):
if not value:
return
try:
# 数值有效性验证
float(value)
except ValueError:
messagebox.showerror("Error", "Pls Inpout Number")
#messagebox.showerror("输入错误", "请输入有效的数字")
return
if self.connected_to_robot:
try:
cmd_template = {
"X": "Tim{}Tim0Tim0TimOKTim666666\r\n",
"Y": "Tim0Tim{}Tim0TimOKTim666666\r\n",
"U": "Tim0Tim0Tim{}TimOKTim666666\r\n"
}
command = cmd_template[axis_type].format(value)
self.robot_client_socket.sendall(command.encode('utf-8'))
logging.info(f"Sent {axis_type}_Offset: {command.strip()}")
except Exception as e:
#logging.error(f"发送{axis_type}偏移失败: {str(e)}")
#self.update_status_indicator2(self.robot_status
logging.error(f"Sent {axis_type}Fail,Message is: {str(e)}")
self.update_status_indicator2(self.robot_status_indicator, 'red', f"Sent Fail: {str(e)}")
else:
messagebox.showwarning("Connect Error", "Can not Connected Robot")
def receive_data(self, client_socket, source):
global Response # 使用全局变量
while client_socket and client_socket.fileno() >= 0:
try:
data = client_socket.recv(1024).decode('utf-8')
Response=data
##print (Response)
if not data:
break
# 加载图片
# self.load_images()
# 启动图片更新定时器
# self.update_image()
current_time = datetime.now().strftime("%H:%M:%S")
##print(current_time)
log_entry = f"[{current_time}] {data}\n"
# Append to log file
with open(r"c:\Log\log_His.txt", "a") as log_file:
log_file.write(log_entry)
# Append to log file
with open(r"c:\Log\log_His_BK.txt", "a") as log_file:
log_file.write(log_entry)
# Update the appropriate text widget
if source == 'vision':
data66=data
#print(data66)
if data66 == 'Out_Of_Range_CW10_CCW10Out_Of_Range_CW90_CCW90' or data66 == 'Out_Of_Range_CW10_CCW10' : #Out_Of_Range_CW10_CCW10
#self.disconnect_from_vision()
#print("111")
self.Out_Of_Range_from_vision()
#print("---111")
if data66 == 'Out_Of_Range_CW90_CCW90':
#self.disconnect_from_vision()
self.Out_Of_Range_from_vision2()
if data66 == 'Camera_not_Match_Picture' :
#self.disconnect_from_vision()
##print("666",data66)
#self.Home_POS()
self.root.after(200, lambda: self.Home_POS())
#print("11111111111")
# 解析数据并记录需格式调整 Chart 17:11:35 Tim-692.003Tim233.098Tim-177.533TimOKTim88888888
x_val = float(data66.split('Tim')[1].split('Tim')[0])
#print("22222222222")
y_val = float(data.split('Tim')[2])
#print("333")
u_val = float(data.split('Tim')[3])
#print("555")
#print(x_val)
#print(x_val,y_val,u_val)
self.history_data['X'].append(x_val)
self.history_data['Y'].append(y_val)
self.history_data['U'].append(u_val)
self.history_data['timestamps'].append(time.time())
## self.vision_data_text.insert(tk.END, f"\n«Vision» -Raw data1- \n\n{current_time} {data}\n")
#Response=data
#print (Response)
time.sleep(0.01)
## self.vision_data_text.yview_moveto(1)
data2=data #data = "-801.226XX218.608YY-13.962YY"
x_value = data2.split('X')[0].strip() #将字符串按 X 分割,取第一个部分,即 -801.226,并去除可能的前后空白字符。
start_y = data2.rfind('-')
y_valueLS = data2[start_y:]
y_value = y_valueLS[:-2]
## self.vision_char_text.insert(tk.END, f"\n«Vision» -Split data2- \n\n{current_time} Received: {x_val} {y_val} {u_val} \n")
#self.vision_char_text.insert(tk.END, f"\n«Vision» -Split data- \n\n{current_time} x:{x_value} y:{y_value} \n")
## self.vision_char_text.yview_moveto(1)
parts = data.split('Tim')
if len(parts) >= 4: # Ensure we have X, Y, U values
x_val = float(parts[1])
y_val = float(parts[2])
u_val = float(parts[3])
self.history_data['X'].append(x_val)
self.history_data['Y'].append(y_val)
self.history_data['U'].append(u_val)
self.history_data['timestamps'].append(time.time())
elif source == 'robot':
data666666 = str(Response).strip() # 去除前后空白
Real_Data=repr(Response)
##print("111 repr Real Data:", repr(Response)) # 显示原始字符串
#data666666=data
#data666666 = str(Response)
#print("111",Response)
#print("222",data666666)
if data666666 == 'Shot' or data666666 == 'Shot2':
#self.disconnect_from_vision()
#print("333",data666666)
#self.Home_POS()
self.root.after(200, lambda: self.Ali_Comand())
if data666666 == 'ERROR_' :
#self.disconnect_from_vision()
#print("333",data666666)
#self.Home_POS()
self.root.after(200, lambda: self.ERROR_())
if data666666 == 'Motor_Off' :
self.root.after(200, lambda: self.Motor_Off())
# 在接收数据时检查Home信号
if 'Home1' in data:
self.home_received = True
self.start_button.config(state=tk.NORMAL)
logging.info("Home position received - Start enabled")
elif 'NotHome' in data:
self.home_received = False
self.start_button.config(state=tk.DISABLED)
logging.info("Not in Home position - Start disabled")
## self.robot_data_text.insert(tk.END, f"\n«Robot_data1»\n{current_time} {data} Real_Data is {Real_Data}\n")
## self.robot_data_text.yview_moveto(1)
## self.robot_char_text.insert(tk.END, f"\n«Robot_data2»\n{current_time} {data} Data is {data666666}\n")
## self.robot_char_text.yview_moveto(1)
# Log the data to the log area
## self.log_text.insert(tk.END, log_entry)
## self.log_text.yview_moveto(1)
# 自动发送接收到的数据作为命令
self.send_custom_command3()
except Exception as e:
logging.error(f"Error receiving data: {e}")
logging.error(f"Data parsing error: {str(e)}")
break
if client_socket == self.vision_client_socket:
self.disconnect_from_vision()
elif client_socket == self.robot_client_socket:
self.disconnect_from_robot()
def send_custom_command(self, command=None):
global RES # 使用全局变量
# 如果没有提供命令,则使用全局变量 RES 的值
if command is None:
command = Response
if command:
logging.info(f"Auto_Custom command entered: {command}")
self.send_robot_command3(command)
self.custom_command_entry3.delete(0, tk.END)
def send_vision_command(self, command): #vision
if self.connect_to_vision and self.vision_client_socket:
try:
self.vision_client_socket.sendall(command.encode('utf-8'))
## logging.info(f"Command vision sent to vision: {command}")
except Exception as e:
logging.error(f"Failed to send command to vision: {e}")
def send_robot_command_Area_Sensor(self, command):
if self.connected_to_robot and self.robot_client_socket:
command345="Motor_Off"
try:
self.robot_client_socket.sendall(command345.encode('utf-8'))
# logging.info(f"Command sent to Robot: {command345.strip()}")
print("55555555555")
except Exception as e:
logging.error(f"Failed to send command to Robot: {e}")
def send_robot_command(self, command):
global Offset_X, Offset_Y, Offset_U
ABCDEFG=0
if self.connected_to_robot and self.robot_client_socket:
try:
# 解析原始命令并应用偏移量
parts = command.split('Tim')
if len(parts) >= 4:
x = float(parts[1]) + (Offset_X if Offset_X else 0)
y = float(parts[2]) + (Offset_Y if Offset_Y else 0)
u = float(parts[3]) + (Offset_U if Offset_U else 0)
command = f"Tim{x}Tim{y}Tim{u}TimOKTim666666\r\n"
# 分开记录日志
logging.info(f"Applied offsets - X: {Offset_X}, Y: {Offset_Y}, U: {Offset_U}")
self.robot_client_socket.sendall(command.encode('utf-8'))
logging.info(f"1、Send_Vision_Pos2robot 2、Robot_X_Y_U_Move_Data 3、 From_robot_command: {command.strip()}")
except Exception as e:
logging.error(f"Failed to send command to Robot: {e}")
##Offset
def send_robot_command_Offset(self, command):
if self.connect_to_vision and self.robot_client_socket:
try: #Tim-495.047Tim86.1133Tim-0.284364TimOKTim88888888 "Tim"(command)TimcommandTimcommandTimOKTim88888888"
send_robot_command_Offset=("Tim"+(command)+"Tim"+(command)+"Tim"+(command)+"Tim"+"OK"+"Tim"+"88888888"+"\r\n")
##print(send_robot_command_Offset)
send_robot_command_Offset66=((command)+"\r\n")
self.robot_client_socket.sendall(send_robot_command_Offset66.encode('utf-8'))
logging.info(f"Command robot sent to Robot66: {command}")
except Exception as e:
logging.error(f"Failed to send command to Robot: {e}")
##Offset
def launch_application(self):
#Demo app_path = r"C:\Users\ShineTek\Desktop\V1\Public_Release\v1.exe"
app_path = r"C:\Log\V5\Public_Release\V5.exe"
#app_path = r"C:\Study\Case\V5\Public_Release\V5.exe"
try:
subprocess.Popen(app_path)
logging.info("Launched application successfully.")
except Exception as e:
messagebox.showerror("Error", f"Failed to launch application: {e}")
logging.error(f"Failed to launch application: {e}")
def launch_application3(self):
app_path = r"C:\Users\ShineTek\AppData\Local\Programs\Python\Python37\Python.exe E:\Tim_Study\Python_Code\Ali_Show_Picture666.py"
#app_path = r"C:\Users\ShineTek\Desktop\大视野\V1_Big_OK_250219_AddCode\Ali_Show_Picture666.exe"
#app_path = r"C:\Users\ShineTek\AppData\Local\Programs\Python\Python37\Python.exe C:\Log\Ali_Show_Picture666.py"
### app_path = r"C:\Users\ShineTek\AppData\Local\Programs\Python\Python37\Python.exe E:\EpsonRC70\Projects\V999_1Cycle_\Show_Picture222.py"
try:
# 启动新进程并保存引用
self.app3_process = subprocess.Popen(app_path)
logging.info("Launched application successfully3.")
except Exception as e:
messagebox.showerror("Error", f"Failed to launch application3: {e}")
logging.error(f"Failed to launch application3: {e}")
def terminate_application3(self):
if self.app3_process and self.app3_process.poll() is None:
# 尝试终止进程
try:
self.app3_process.terminate()
self.app3_process.wait()
logging.info("Terminated application3 successfully.")
except Exception as e:
logging.error(f"Failed to terminate application3: {e}")
self.app3_process = None # 重置进程引用
def update_status_indicator(self, indicator, color, message):
indicator.config(bg=color)
self.root.update_idletasks()
messagebox.showinfo("Status", message)
def update_status_indicator2(self, indicator, color, message):
indicator.config(bg=color)
self.root.update_idletasks()
messagebox.showinfo("Waring", message)
##Tim
def update_status_indicator6(self, indicator, color, message):
indicator.config(bg=color)
self.root.update_idletasks()
messagebox.showinfo("ERROR", message)
self.update_status_indicator(self._status_indicator6, 'green', "Center")
self.update_status_indicator(self._status_indicator6, 'red', f"not Center")
def Auto_send(self):
# 等待3秒,以便用户将焦点切换到目标输入框
time.sleep(3)
# 在指定位置输入XXX
x1, y1 = map(int, input("请输入要输入XXX的位置坐标(以空格分隔,例如:100 200):").split())
pyautogui.click(x1, y1)
pyautogui.typewrite('XXX')
# 在指定位置输入YYY
x2, y2 = map(int, input("请输入要输入YYY的位置坐标(以空格分隔,例如:300 400):").split())
pyautogui.click(x2, y2)
pyautogui.typewrite('YYY')
# 找到send按钮的位置(这里假设已经知道send按钮的位置,假设为x_send, y_send)
x_send, y_send = map(int, input("请输入send按钮的位置坐标(以空格分隔,例如:500 600):").split())
# 点击send按钮
pyautogui.click(x_send, y_send)
time.sleep(0.5)
pyautogui.click(x_send, y_send)
def start_auto_command(self):
if self.connect_to_vision and self.vision_client_socket:
#self.connect_to_vision()
#self.connect_to_robot()
#self.root.after(200, lambda: self.connect_to_vision())
print("1111111111111")
#time.sleep(100)
self.custom_command_entry1.delete(0, tk.END)
self.custom_command_entry1.insert(0, "1st_Camera")
self.send_custom_command1()
# 先终止可能正在运行的进程
self.terminate_application3()
# 再启动新进程
self.root.after(200, lambda: self.launch_application3())
def Recive_PLC_start_command(self): #PC Start yeshi zouzheli
##print(Response)
data_Tim = str(Response).strip() # 去除前后空白
if data_Tim=="1NO_Home_Pos":
#if not data_Tim=="Home_Pos":
time.sleep(0.005)
self.root.after(200, lambda: self.Home_POS())
else:
if self.connect_to_vision and self.vision_client_socket:
#self.connect_to_vision()
#self.connect_to_robot()
#self.root.after(200, lambda: self.connect_to_vision())
#print("2222222222")
#time.sleep(100)
self.custom_command_entry1.delete(0, tk.END)
self.custom_command_entry1.insert(0, "1st_Camera")
self.send_custom_command1()
# 先终止可能正在运行的进程
self.terminate_application3()
# 再启动新进程
##self.root.after(200, lambda: self.launch_application3())
# 更新图片逻辑
self.root.after(5000, lambda: self.load_images())
self.root.after(500, lambda: self.update_image())
self.load_images() # 重新加载图片
self.update_image() # 更新图片显示
#self.root.after(200, lambda: self.Ali_Comand())
def Ali_Comand(self):
self.custom_command_entry1.delete(0, tk.END)
self.custom_command_entry1.insert(0, "2nd_Camera")
self.send_custom_command1()
# 先终止可能正在运行的进程
#self.terminate_application3()
# 再启动新进程
###self.root.after(200, lambda: self.launch_application3())
def continue_auto_command(self):
self.custom_command_entry1.delete(0, tk.END)
self.custom_command_entry1.insert(0, "YYY")
self.send_custom_command1()
self.root.after(200, lambda: self.continue_auto_command_U())
def continue_auto_command_U(self):
self.custom_command_entry1.delete(0, tk.END)
self.custom_command_entry1.insert(0, "UUU")
self.send_custom_command1()
def init_plc_connection(self):
"""增强型工业连接协议"""
try:
self.plc = MelsecMcNet("192.168.0.11", 1028)
conn = self.plc.ConnectServer()
if conn.IsSuccess:
#self.status_bar.config(text="PLC已连接 | 协议版本6.2", fg="green")
logging.info(f"Connected to PLC at IP:192.168.0.11 Port:1028 ")
else:
#self.status_bar.config(text=f"连接失败: {conn.Message}", fg="red")
logging.info(f"PLC Connect NG at [{datetime.now().strftime('%H:%M:%S')}]")
self.plc = None
except Exception as e:
#self.status_bar.config(text=f"初始化异常: {str(e)}", fg="orange")
logging.info(f"PLC Connect NG at [{datetime.now().strftime('%H:%M:%S')}]")
def setup_plc(self):
# PLC连接配置
self.plc = MelsecMcNet("192.168.0.11", 1028)
connect_result = self.plc.ConnectServer()
if not connect_result.IsSuccess:
print("PLC Connect NG:", connect_result.Message)
self.plc = None
def start_plc_monitoring(self):
"""智能重连监控系统"""
if self.plc and self._check_connection():
self._monitor_y79()
else:
self.parent.after(2000, self.start_plc_monitoring)
def _monitor_y79(self):
"""修正地址并增强监测"""
try:
# 使用八进制地址Y117(十进制79)
#read_result = self.plc.ReadBool("Y79")
read_result = self.plc.ReadBool("L801")
read_result3 = self.plc.ReadBool("X2F")
#self._log(f"Y79读取结果: 成功={read_result.IsSuccess} 状态={read_result.Content}")
#logging.info(f"Y79读取结果: 成功={read_result.IsSuccess} 状态={read_result.Content}")
#logging.info(f"成功读取到Y79状态:{read_result.Content}")
#logging.info(f"[{datetime.now().strftime('%H:%M:%S')}],Recive PLC Y79 Status is:{read_result.IsSuccess}")
Time_Tim=datetime.now().strftime('%H:%M:%S')
if read_result.Content is False:
print("Content is False")
#logging.info(f"[{datetime.now().strftime('%H:%M:%S')}],PLC No Command")
if read_result.Content is True:
time.sleep(0.005)
#print("Content is True")
#logging.info(f"[{Time_Tim}] Content is True")
#log_entry = f"[{Time_Tim}] Content is True\n"
#logging.info(f"[{datetime.now().strftime('%H:%M:%S')}],Recive PLC Start Command")
if read_result.IsSuccess:
current_state = read_result.Content
# 精确的上升沿检测
if current_state and not self.last_y79_state:
#self._log("检测到Y79上升沿,触发自动命令")
logging.info(f"Check PLC Start Command,UI Start")
#self.start_auto_command
#self.Recive_PLC_start_command
self.start_auto_command() ###Tim Modify
self.last_y79_state = current_state
if read_result3.Content is False:
time.sleep(0.00001)
# print("Content3 is False,Area Sensor On")
# global Ares_Sensor # 使用全局变量
# Ares_Sensor = 1
# print(Ares_Sensor)
if read_result3.Content is True:
time.sleep(0.005)
#print("222Content3 is False,Area Sensor On")
# if read_result3.IsSuccess:
# print("333Content3 is False,Area Sensor On")
# current_state3 = read_result.Content3
# # 精确的上升沿检测
# if current_state3 and not self.last_X2F_state:
# #self._log("检测到Y79上升沿,触发自动命令")
# logging.info(f"Check PLC Area Sensor Command,UI Start")
# print("444Content3 is False,Area Sensor On")
# self.send_robot_command_Area_Sensor() ########
# self.last_X2F_state = current_state3
else:
#self._log(f"通信失败: {read_result.Message}")
# logging.info(f"Recived PLC Area Sensor ...")
# print("Content PLC OK ,Area Sensor is On")
# SERVER_IP = "192.168.0.150" #192.168.0.1
# SERVER_PORT = 5670
# 创建TCP服务器
# server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# server.bind((SERVER_IP, SERVER_PORT))
# server.listen(1)
# print(f"Server OK,Waiting Robot Connect...")
# 接受EPSON控制器连接
# conn, addr = server.accept()
# print(f"Robot Connected: {addr}")
global Ares_Sensor # 使用全局变量
Ares_Sensor = 0 ##3Area Sensor On 1 off 0
if Ares_Sensor == 1:
#print(Ares_Sensor)
try:
# 创建TCP服务器
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定IP和端口
server.bind((SERVER_IP, SERVER_PORT))
# 开始监听,最大连接数为1
server.listen(1)
print(f"Server OK,Waiting Robot Connect...")
# 接受客户端连接
conn, addr = server.accept()
print(f"Robot Connected: {addr}")
# 使用全局变量
Ares_Sensor = 1
if Ares_Sensor == 1:
print(Ares_Sensor)
# 定义命令列表
commands222 = [
"STOP", # 紧急停止
"PAUSE", # 暂停运行
"RESUME", # 恢复运行
"STATUS", # 请求状态反馈
"RESET" # 复位错误
]
commands3333 = [
"STOP" ,1 # 紧急停止
]
# 要发送的命令列表
#commands = ["STOP", "PAUSE", "RESUME"]
commands = ["PAUSE"]
index = 0
#while True:
for aaaa in range(1):
# 获取当前要发送的命令
cmd = commands[index % len(commands)] + "\n"
try:
# 发送命令
conn.sendall(cmd.encode('utf-8')) # t66=((cmd)+"\r\n")
#conn.sendall((cmd)+"\n".encode())
#conn.sendall((cmd)+"\r\n".encode('utf-8'))
print(f"[{time.strftime('%H:%M:%S')}] Send OK。。。。。。 {cmd}")
except socket.error as e:
print(f"Send error: {e}")
break
index += 1
aaaa+=1
print(aaaa)
# 暂停一段时间
time.sleep(0.0001) # 修复括号未关闭的问题
except socket.error as e:
print(f"Socket error: {e}")
finally:
# 关闭服务器和连接
if 'server' in locals():
server.close()
if 'conn' in locals():
conn.close()
time.sleep(0.0001)
except Exception as e:
#self._log(f"监测异常: {str(e)}")
logging.info(f"Error to PLC,Message is : {str(e)}")
finally:
self.parent.after(333, self._monitor_y79)
def _check_connection(self):
"""工业级连接状态验证"""
try:
return self.plc.ConnectServer().IsSuccess
except:
return False
def start_auto_command(self):
"""修正后的自动控制流程,确保仅运行一次"""
logging.info("Start button triggered, running command sequence...")
time.sleep(0.00006)
# 确保仅执行一次流程
if not hasattr(self, '_is_running') or not self._is_running:
self._is_running = True
try:
self.Recive_PLC_start_command() # 执行主流程
finally:
self._is_running = False
def _safe_write(self, address, value, data_type):
"""通用安全写入模板"""
try:
if data_type == 'float':
result = self.plc.WriteFloat(address, value)
elif data_type == 'int32':
result = self.plc.WriteInt32(address, value)
elif data_type == 'bool':
result = self.plc.Write(address, [value])
if not result.IsSuccess:
print(f"Write {address} NG: {result.Message}")
except Exception as e:
print(f"Write NG,Message is : {str(e)}")
def check_y79_status(self):
try:
if self.plc:
# 读取Y79状态(注意地址格式需要根据实际PLC配置调整)
read_result = self.plc.ReadBool("Y79")
if read_result.IsSuccess and read_result.Content:
self.start_auto_command()
finally:
# 持续监控
self.parent.after(500, self.check_y79_status)
def start_Robot_command(self):
"""2025版自动控制流程""" #StartTim1Tim000Tim111Tim222Tim888Tim
##print("Running Command ...")
time.sleep (0.00006)
app_path = r"C:\Users\ShineTek\AppData\Local\Programs\Python\Python37\Python.exe E:\Tim_Study\Python_Code\V5_20250312_Robot_Client_UI_Control.py"
try:
# 启动新进程并保存引用
self.app3_process = subprocess.Popen(app_path)
logging.info("Launched start_Robot_command application successfully.")
except Exception as e:
messagebox.showerror("Error", f"Failed to launch start_Robot_command application: {e}")
logging.error(f"Failed to launch start_Robot_command application: {e}")
def start_Falco_command(self):
"""2025版自动控制流程"""
##print("Running Command ...")
time.sleep (0.00006)
#self.Recive_PLC_start_command() ###Tim Modify
# 保持原有写入逻辑
#self._safe_write("D390", 7777.888, 'float')
#self._safe_write("D397", 55, 'int32')
#self._safe_write("M260", True, 'bool')
def start_PLC_command(self):
"""2025版自动控制流程"""
##print("Running PLC Command ...")
app_path = r"C:\Users\ShineTek\AppData\Local\Programs\Python\Python37\Python.exe E:\Tim_Study\Python_Code\V6_PLC_BaseOn_Ali_Show_Picture666.py"
try:
# 启动新进程并保存引用
self.app3_process = subprocess.Popen(app_path)
logging.info("Launched start_PLC_command application successfully.")
except Exception as e:
messagebox.showerror("Error", f"Failed to launch start_PLC_command application: {e}")
logging.error(f"Failed to launch start_PLC_command application: {e}")
def save_settings(self):
"""增强型配置保存方法"""
config = {
'version': 1.0,
'offsets': {
'x': self.custom_command_entry5.get(),
'y': self.custom_command_entry6.get(),
'u': self.custom_command_entry7.get()
}
}
try:
# 确保目录存在
os.makedirs(os.path.dirname(self.CONFIG_PATH), exist_ok=True)
with open(self.CONFIG_PATH, 'w') as f:
json.dump(config, f, indent=2)
#logging.info("配置保存成功")
logging.info("Config Save")
except Exception as e:
logging.error(f"Save Config FAil,Message is: {str(e)}")
messagebox.showerror("Error", f"Can not Save Config:\n{str(e)}")
#logging.error(f"保存配置失败: {str(e)}")
#messagebox.showerror("错误", f"无法保存配置:\n{str(e)}")
def load_settings(self):
"""增强型配置加载方法"""
try:
if os.path.exists(self.CONFIG_PATH):
with open(self.CONFIG_PATH, 'r') as f:
config = json.load(f)
# 处理旧版本配置文件
if 'offsets' in config: # 新版本结构
offsets = config['offsets']
else: # 兼容旧版本
offsets = config
# 设置输入框值(带空值保护)
self.custom_command_entry5.delete(0, tk.END)
self.custom_command_entry5.insert(0, offsets.get('x', ''))
self.custom_command_entry6.delete(0, tk.END)
self.custom_command_entry6.insert(0, offsets.get('y', ''))
self.custom_command_entry7.delete(0, tk.END)
self.custom_command_entry7.insert(0, offsets.get('u', ''))
except json.JSONDecodeError:
#logging.warning("配置文件格式错误,已重置")
logging.warning("Config Format Error,Loading Def Config File")
self._create_default_config()
except Exception as e:
#logging.error(f"加载配置失败: {str(e)}")
#messagebox.showwarning("警告", "配置加载失败,已恢复默认值")
logging.error(f"Loading Config Fail,Message is: {str(e)}")
messagebox.showwarning("Waring", "Loading Config Fail,Loading Def Config File")
def _create_default_config(self):
"""创建默认配置文件"""
default_config = {
'version': 1.0,
'offsets': {
'x': "0.0",
'y': "0.0",
'u': "0.0"
}
}
try:
with open(self.CONFIG_PATH, 'w') as f:
json.dump(default_config, f, indent=2)
except Exception as e:
logging.error(f"Great Def Config Fail,Message is: {str(e)}")
def update_gauges(self):
# 从实际数据源获取值
speed = random.randint(0,100)
temp = random.randint(0,100)
#self.speed_gauge.update_value(speed)
#self.temp_gauge.update_value(temp)
self.root.after(1000, self.update_gauges)
def apply_point_limit_change(self):
"""应用数据点数量限制的变更"""
try:
new_limit = int(self.point_entry.get())
if new_limit > 0:
self.point_limit = new_limit
# 立即更新显示
self.update_display()
else:
messagebox.showwarning("输入无效", "数据点数量必须大于0")
except ValueError:
messagebox.showerror("输入错误", "请输入有效的整数")
def write_all_offsets(self):
global Offset_X, Offset_Y, Offset_U
# 获取输入值并验证
try:
Offset_X = float(self.custom_command_entry5.get()) if self.custom_command_entry5.get() else None
Offset_Y = float(self.custom_command_entry6.get()) if self.custom_command_entry6.get() else None
Offset_U = float(self.custom_command_entry7.get()) if self.custom_command_entry7.get() else None
except ValueError:
messagebox.showerror("错误", "请输入有效的数字")
return
# 写入日志
log_msg = f"Offset updated - X: {Offset_X}, Y: {Offset_Y}, U: {Offset_U}"
logging.info(log_msg)
# 更新界面
## self.robot_data_text.yview_moveto(1)
## self.robot_char_text.insert(tk.END, f"{datetime.now().strftime('%H:%M:%S')} {log_msg}\n")
## self.robot_char_text.yview_moveto(1)
def read_last_n_records(self, file_path, n=5):
"""读取文件中最后n条有效数据记录"""
data = []
try:
with open(file_path, 'r') as f:
# 读取所有行
lines = f.readlines()
# 倒序查找有效数据,最多检查最后20行
for line in reversed(lines[-20:]):
if "Tim" in line:
try:
# 使用正则表达式提取数值
import re
pos_match = re.search(r'Tim([-\d.]+)Tim([-\d.]+)Tim([-\d.]+)Tim', line)
if pos_match:
x, y, z = map(float, pos_match.groups())
data.append((x, y, z))
if len(data) >= n:
break # 达到所需数据量后停止搜索
except Exception as e:
logging.error(f"解析行失败: {str(e)}")
# 返回按时间顺序排列的数据
return data[::-1]
except FileNotFoundError:
logging.error("轨迹文件未找到,请确认路径是否正确")
return []
except Exception as e:
logging.error(f"读取文件时发生错误: {str(e)}")
return []
def read_trajectory_data(self, file_path):
"""使用正则表达式增强版轨迹读取"""
data = []
try:
with open(file_path, 'r') as f:
for line in f:
if "Current_POS_is:" in line:
try:
import re
pos_match = re.search(r'X:([\-0-9.]+)Y:([\-0-9.]+)Z:([\-0-9.]+)U:([\-0-9.]+)', line)
if pos_match:
x, y, z, u = map(float, pos_match.groups())
data.append((x, y, z, u))
except Exception as e:
logging.error(f"解析行失败: {str(e)}")
return data
except FileNotFoundError:
logging.error("轨迹文件未找到,请确认路径是否正确")
return []
def show_animation(self):
"""显示高科技风格的3D轨迹动画"""
file_path = r'C:\Log\Robot_POS.txt'
# 验证文件路径
if not os.path.exists(file_path):
messagebox.showerror("文件错误", f"轨迹文件未找到\n路径: {file_path}")
logging.error(f"轨迹文件不存在: {file_path}")
return
trajectory_data = self.read_trajectory_data(file_path)
if not trajectory_data:
logging.warning("没有读取到有效轨迹数据")
return
# 创建新窗口用于显示动画
animation_window = tk.Toplevel(self.root)
animation_window.title("Robot Trajectory Animation")
fig = Figure(figsize=(6, 4), dpi=100)
# 设置中文字体和负号显示
from matplotlib import rcParams
rcParams['font.sans-serif'] = ['SimHei'] # 使用黑体以支持中文
rcParams['axes.unicode_minus'] = False # 正常显示负号
ax = fig.add_subplot(111, projection='3d') # 启用3D绘图
ax.set_title("3D")
ax.set_xlabel("X Position")
ax.set_ylabel("Y Position")
ax.set_zlabel("Z Position") # 添加Z轴标签
ax.grid(True)
ax.set_facecolor('#f0f0f0')
# 修正后的坐标轴背景颜色设置
ax.xaxis.pane.fill = True
ax.xaxis.pane.set_alpha(0.94)
ax.yaxis.pane.fill = True
ax.yaxis.pane.set_alpha(0.90)
ax.zaxis.pane.fill = True
ax.zaxis.pane.set_alpha(0.85)
# 设置坐标轴面板颜色渐变
ax.xaxis.pane.set_facecolor((0.94, 0.94, 0.94))
ax.yaxis.pane.set_facecolor((0.90, 0.90, 0.90))
ax.zaxis.pane.set_facecolor((0.85, 0.85, 0.85))
canvas = FigureCanvasTkAgg(fig, master=animation_window)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
# 使用颜色映射来表示时间进程
from matplotlib import cm
colors = [cm.viridis(i / len(trajectory_data)) for i in range(len(trajectory_data))]
# 创建轨迹线对象
line, = ax.plot([], [], [], lw=2, label='') # 初始化3D线条 实时轨迹
yellow_line, = ax.plot([], [], [], c='gold', lw=2, label='His') # 历史路径标签
# 创建当前点标记
current_point, = ax.plot([], [], [], 'ro', markersize=10, label='Cur') # 当前位置标签
# 创建轨迹尾迹
trail, = ax.plot([], [], [], c='blue', alpha=0.3, lw=2, label='...') # 轨迹尾迹标签
# 添加图例说明
ax.legend(loc='upper left', fontsize=12, bbox_to_anchor=(0.0, 0.9))
def init():
xs = [d[0] for d in trajectory_data]
ys = [d[1] for d in trajectory_data]
zs = [d[2] for d in trajectory_data]
min_range = 20 # 最小显示范围
ax.set_xlim(min(xs) - 5, max(xs) + 5 if max(xs)-min(xs) > min_range else min(xs) + min_range)
ax.set_ylim(min(ys) - 5, max(ys) + 5 if max(ys)-min(ys) > min_range else min(ys) + min_range)
ax.set_zlim(min(zs) - 5, max(zs) + 5 if max(zs)-min(zs) > min_range else min(zs) + min_range)
ax.view_init(elev=20, azim=200) # 默认视角
return line, yellow_line, current_point, trail
def update(frame):
# 提取当前帧前的所有X、Y、Z值
x_values = [d[0] for d in trajectory_data[:frame+1]]
y_values = [d[1] for d in trajectory_data[:frame+1]]
z_values = [d[2] for d in trajectory_data[:frame+1]] # 提取Z值
# 更新轨迹线
line.set_data(x_values, y_values)
line.set_3d_properties(z_values)
line.set_color(colors[frame]) # 设置当前线段的颜色
# 更新黄色轨迹线(现为历史路径)
yellow_x = x_values[:max(0, frame-10)]
yellow_y = y_values[:max(0, frame-10)]
yellow_z = z_values[:max(0, frame-10)]
yellow_line.set_data(yellow_x, yellow_y)
yellow_line.set_3d_properties(yellow_z)
# 更新当前点标记
current_point.set_data([x_values[-1]], [y_values[-1]])
current_point.set_3d_properties([z_values[-1]])
# 更新轨迹尾迹(仅显示最近的20个点)
trail_start = max(0, frame-5)
trail.set_data(x_values[trail_start:], y_values[trail_start:])
trail.set_3d_properties(z_values[trail_start:])
trail.set_alpha(np.linspace(0.2, 0.8, frame - trail_start + 1)[-1])
# 动态更新标题显示当前帧信息
#ax.set_title(f"智能制造演示 | 当前帧: {frame} | X:{x_values[-1]:.2f}, Y:{y_values[-1]:.2f}, Z:{z_values[-1]:.2f} (mm)")
ax.set_title(f"3D")
# 每50帧自动调整视角
if frame % 50 == 0:
ax.view_init(elev=20, azim=35 + frame//10)
return line, yellow_line, current_point, trail
from matplotlib.animation import FuncAnimation
ani = FuncAnimation(fig, update, frames=len(trajectory_data), init_func=init,
blit=True, interval=250, repeat=False) # 运行速度降为原始速度的 1/5 运行速度
ani._start() # 使用TkAgg推荐的启动方式
# 添加动画控制面板
control_frame = tk.Frame(animation_window)
control_frame.pack(side=tk.BOTTOM, fill=tk.X)
# 添加动画控制按钮
btn_frame = tk.Frame(control_frame)
btn_frame.pack(pady=10)
def toggle_animation():
if ani.event_source is None:
return
if ani.event_source.is_running():
ani.event_source.stop()
toggle_btn.config(text="Play")
else:
ani.event_source.start()
toggle_btn.config(text="Pause")
toggle_btn.config(command=toggle_animation)
def reset_animation():
ani.event_source.stop()
init()
toggle_btn.config(text="Play")
reset_btn = tk.Button(btn_frame, text="Reset", command=reset_animation,
bg="#FFA500", fg="white", width=6, font=("Segoe UI", 10))
reset_btn.pack(side=tk.LEFT, padx=5)
close_btn = tk.Button(btn_frame, text="Close", command=animation_window.destroy,
bg="#C0C0C0", fg="black", width=6, font=("Segoe UI", 10))
close_btn.pack(side=tk.RIGHT, padx=5)
#C:\Users\SKD\AppData\Local\Programs\Python\Python311\Scripts\pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ pyautogui
if __name__ == "__main__":
root = tk.Tk()
app = TCPClientApp(root)
root.mainloop()
--------------------------------------------
'
'Design By Tim Process.prg
'
Function Alignment_TCP_212
GoTo lblOpenPort
lblOpenPort:
CloseNet #212
Print "Waiting Servers Open ", Time$
SetNet #212, "192.168.0.150", 7777, CRLF, NONE, 0
OpenNet #212 As Client
WaitNet #212
Print "IP:192.168.0.150 Port:7777 Open at ", Time$
MemOff 18 'Clean
''14:28:13 Tim-682.789Tim289.271Tim89.7095TimOKTim888888
'Recive data DOWNTimNoneAUOTim11.999Tim1061.1652Tim1612.829Tim90.005055Tim
Do
'MemOn 18
If MemSw(18) = Off Then
Wait 0.6
Status_212 = ChkNet(212)
Print "Recive data Len/Status is ", Status_212
If Status_212 > 0 And Status_212 < 62 Then
Read #212, Data_212$, Status_212
Print "Recive data1 ", Status_212, "Recive data2 ", Data_212$, "Recive data3 ", Data_212_Read
'ParseStr Data_212$, PData_212$(), "Tim" '锟街革拷锟街凤拷
'Print "Recive data sp is ", PData_212$(0), PData_212$(1), PData_212$(2)
MemOn 18
ElseIf Status_212 > 62 Then
Print "Recive len is so long"
String msg2$, title2$
Integer mFlag2s, answer2
msg2$ = "Recive len is so long" + CRLF
msg2$ = msg2$ + "Press Y or N to Exit..." + CRLF
msg2$ = msg2$ + "Press N or Y to Exit..." + CRLF
title2$ = "Recive Title"
mFlag2s = MB_YESNO + MB_ICONQUESTION
MsgBox msg2$, mFlag2s, title2$, answer2
If answer2 = IDNO Or answer2 = IDYES Then
Quit All
EndIf
Exit Do
ElseIf Status_212 = -3 Then
MemOff 2 'Ethernet Connect Status
Print "Ethernet is Close,Pls Check it...", Time$
GoTo lblOpenPort
EndIf
EndIf
If MemSw(18) = On Then
Wait 0.022
ParseStr Data_212$, PData_212$(), "Tim" '锟街革拷锟街凤拷
'Print "Recive data sp is ", PData_212$(0), PData_212$(1), PData_212$(2), PData_212$(3), PData_212$(4), PData_212$(5)
''Order:1=Ref_A1 2=Ref_A2 3=Ref_A3 4=Ref_A4 5=Start Index:888888
Order = Val(PData_212$(1))
'Index = Val(PData_212$(5))
Pitch = Val(PData_212$(2))
''RIGHTTim2Tim11.999Tim1061.1652Tim1612.829Tim90.005055Tim
''if Pdate 0 1 2 = None, No Action
''Data_212_Start$ = PData_212$(0)=LEFRUPDOWNSAVE
''Data_212_Start$ = PData_212$(1)=Order
''Data_212_Start$ = PData_212$(2)=Pitch
If Order = 0 Then
Print "Home Pos Send", P986
Print #212, "Home Pos Send", P986
Go P986 'Home_Ref
ElseIf Order = 1 Then
Print "Go Ref_A1"
Wait 0.3
P987 = RealPos
Print #212, "Go Ref_A1", P987
Go P985 'A1_Ref
ElseIf Order = 2 Then
Print "Go Ref_A2"
Wait 0.3
P987 = RealPos
Print #212, "Go Ref_A2", P987
Go P984 'A2_Ref
EndIf
Wait 0.88
'
CX_Here = CX(Here)
CY_Here = CY(Here)
CZ_Here = CZ(Here)
CU_Here = CU(Here)
Print "Now pos is :", Here
Data_212_Start$ = PData_212$(0)
If Data_212_Start$ = "UP" Then
Print "Recive UP = ", Data_212_Start$
Go XY(CX(Here) + Pitch, CY(Here), CZ(Here), CU(Here))
Print "Now pos is :", Here
ElseIf Data_212_Start$ = "LEF" Then
Print "Recive Left = ", Data_212_Start$
Go XY(CX(Here), CY(Here) + Pitch, CZ(Here), CU(Here))
Print "Now pos is :", Here
ElseIf Data_212_Start$ = "RIGH" Then
Print "Recive Right = ", Data_212_Start$
Go XY(CX(Here), CY(Here) - Pitch, CZ(Here), CU(Here))
Print "Now pos is :", Here
ElseIf Data_212_Start$ = "DOWN" Then
Print "Recive Down = ", Data_212_Start$
Go XY(CX(Here) - Pitch, CY(Here), CZ(Here), CU(Here))
Print "Now pos is :", Here
ElseIf Data_212_Start$ = "CW" Then
Print "Recive CW = ", Data_212_Start$
Go XY(CX(Here), CY(Here), CZ(Here), CU(Here) - Pitch)
Print "Now pos is :", Here
ElseIf Data_212_Start$ = "CCW" Then
Print "Recive CCW = ", Data_212_Start$
Go XY(CX(Here), CY(Here), CZ(Here), CU(Here) + Pitch)
Print "Now pos is :", Here
ElseIf Data_212_Start$ = "SAVE" Then
Print "Saving Aligment OK Pos ", Here
String msg$, title$
Integer mFlags, answer
msg$ = "Save Pos" + CRLF
msg$ = msg$ + "Are U Sure?"
title$ = "Setting 2 Save"
mFlags = MB_YESNO + MB_ICONQUESTION
MsgBox msg$, mFlags, title$, answer
If answer = IDNO Then
Quit All
ElseIf answer = IDYES Then
PLabel 988, "Aligment"
Here P988
Print "Save Pos ", CRLF, Here
Print #212, "Save Pos ", CRLF, Here
EndIf
EndIf
SavePoints "rbtPoints_212.pts"
Print "Eecive data OK...Start 2 Waiting Order..."
MemOff 18 'Clean
EndIf
Print #212, "---", Time$
Print "---", Time$
MemOff 18 'Clean
Loop
ErrorHandle:
'errnum = Err
Print "ERROR", errnum
Quit All
Fend
Function Welcome
Do
If MemSw(2) = Off Then
Print "Welcome 2 Use"
String msg$, title$
Integer mFlags, answer
msg$ = "Welcome 2 Use" + CRLF
msg$ = msg$ + "Do not Press Or Press Y to Continue..." + CRLF
msg$ = msg$ + "Press N to Exit..." + CRLF
title$ = "Robot Control Tool"
mFlags = MB_YESNO + MB_ICONQUESTION
MsgBox msg$, mFlags, title$, answer
If answer = IDNO Then
Quit All
EndIf
EndIf
'CloseNet #212
Exit Do
Loop
Fend
Function Recive_lendayu62
Do
If Status_212 > 62 Then
Print "Recive len is so long"
String msg$, title$
Integer mFlags, answer
msg$ = "Recive len is so long" + CRLF
msg$ = msg$ + "Press Y to Continue..." + CRLF
msg$ = msg$ + "Press N to Exit..." + CRLF
title$ = "Recive Title"
mFlags = MB_YESNO + MB_ICONQUESTION
MsgBox msg$, mFlags, title$, answer
If answer = IDNO Or answer = IDYES Then
Quit All
EndIf
EndIf
Exit Do
Loop
Fend
Function TCP_209_AreaSensor_As_Client
' 锟截憋拷锟斤拷锟斤拷锟斤拷锟紼S THEN
CloseNet #209
Print "#209 Config Waiting Servers Open ", Time$
' 锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟絆pen ", Time$
SetNet #209, "192.168.0.150", 5670, CRLF, NONE, 0
' 锟皆客伙拷锟斤拷模式锟斤拷锟斤拷锟斤拷锟斤拷, 0
OpenNet #209 As Client
' 锟饺达拷锟斤拷锟斤拷锟斤拷锟接斤拷锟斤拷锟浇, 0
WaitNet #209
Print "#209 Config IP:192.168.0.150 Port:5678 Open at ", Time$
' 锟饺达拷1锟斤拷
Wait 1
Do
' 锟截憋拷锟斤拷锟斤拷锟斤拷锟接斤拷锟斤拷锟浇, 0
CloseNet #209
Print "#209 Waiting Servers Open ", Time$
' 锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟?, TIME$
SetNet #209, "192.168.0.150", 5670, CRLF, NONE, 0
' 锟皆客伙拷锟斤拷模式锟斤拷锟斤拷锟斤拷锟斤拷E, 0
OpenNet #209 As Client
' 锟饺达拷锟斤拷锟斤拷锟斤拷锟接斤拷锟?29Tim90.005055Tim
WaitNet #209
Print "#209 IP:192.168.0.150 Port:5678 Open at ", Time$
' 锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟捷筹拷锟絠me$
Area_Sensor___ = ChkNet(209)
Print "#209 Recived Lens: ", Area_Sensor___
' 锟斤拷锟斤拷锟斤拷锟斤拷萁锟斤拷锟?
If ChkNet(209) > 0 Then
' 锟斤拷取一锟斤拷锟斤拷锟斤拷
''Line Input #209, Area_Sensor_$
Read #209, Area_Sensor_$, Area_Sensor___
Print "data is : ", Area_Sensor_$
' 锟斤拷锟斤拷锟斤拷盏锟斤拷锟斤拷锟斤拷锟?
Select Case UCase$(Trim$(Area_Sensor_$))
Case "PAUSE"
Print "Pause"
Pause ' 锟斤拷停
Case "RESET"
Print "RESUME"
Reset ' 锟斤拷锟斤拷锟斤拷锟阶刺?锟斤拷位锟斤拷锟斤拷
Case "STOP"
Print "Motor_Off"
Motor Off ' 锟截闭碉拷锟?
Case "ESTOPON"
Print "ESTOPON"
'SafeguardOn ' 锟截闭碉拷锟?
'EStopOn
Case "1"
Print "Other command: ", Area_Sensor_$
Motor Off
Send
EndIf
If Area_Sensor___ = -3 Then
Pause ' 锟斤拷停
'Motor Off
String msg6_$, title_6$
Integer mFlags_6, answer_6
msg6_$ = "Waring" + CRLF
msg6_$ = msg6_$ + "Area Sensor !!!" + CRLF
msg6_$ = msg6_$ + "Area Sensor !!!" + CRLF
msg6_$ = msg6_$ + "Area Sensor !!!" + CRLF
msg6_$ = msg6_$ + " " + CRLF
msg6_$ = msg6_$ + "Press N to STOP !!!" + CRLF
msg6_$ = msg6_$ + "Press Y to Continue" + CRLF
title_6$ = "Robot Control Tool"
mFlags_6 = MB_YESNO + MB_ICONQUESTION
MsgBox msg6_$, mFlags_6, title_6$, answer_6
If answer_6 = IDNO Then
Quit All
EndIf
If answer_6 = IDYES Then
Wait 0.0001
EndIf
EndIf
Loop
Fend
Function Big_TCP_212_Runmode
CloseNet #210
SetNet #210, "192.168.0.1", 2009, CRLF, NONE, 0
OpenNet #210 As Server
WaitNet #210
Print "#210 Open at ", Time$
MemOff RecvData 'Clean
Jump P988 LimZ (0) 'NG_Port
'Jump P988
Off 9
Off 8
Wait 0.8
Jump P999 LimZ (0) 'home_Standby
Do
Off 9
Off 8
Wait 0.05 '<1 3 Cycle
If MemSw(RecvData) = Off Then
state211 = ChkNet(210)
Print "Recived Lens: ", state211
Print "For_Index:", For_LS_tim
If state211 > 0 Then
If For_LS_tim = 3 Then
'cLANE
'Input #211, Data211$
Print #210, Clean_Tim$
Clean_Tim$ = ""
Wait 2
Input #210, Data210$
Print Time$, " Recive data: ", Data210$ 'recive data
state211 = ChkNet(210)
'Input #211, Data211$
'Print Time$, " Recive data: ", Data211$ 'recive data
'cLANE ok
Input #210, Data211$
Print Time$, " Recive data_Clean: ", Data211$ 'recive data
ParseStr Data211$, Pdata211$(), "Tim" 'spilt data
MemOn RecvData
Start_String_211$ = Data211$
'Start_Real_211 = Val(Start_String_211$)
Start_Real_211 = Val(Right$(Start_String_211$, 6))
Print "Start index: ", Start_Real_211
ElseIf For_LS_tim = 1 Or For_LS_tim = 2 Then
Input #210, Data211$
Print Time$, " Recive data_Clean: ", Data211$ 'recive data
ParseStr Data211$, Pdata211$(), "Tim" 'spilt data
MemOn RecvData
Start_String_211$ = Data211$
'Start_Real_211 = Val(Start_String_211$)
Start_Real_211 = Val(Right$(Start_String_211$, 6))
Print "Start index: ", Start_Real_211
ElseIf For_LS_tim = 0 Then
Input #210, Data211$
Print Time$, " Recive data: ", Data211$ 'recive data
ParseStr Data211$, Pdata211$(), "Tim" 'spilt data
MemOn RecvData
Start_String_211$ = Data211$
'Start_Real_211 = Val(Start_String_211$)
Start_Real_211 = Val(Right$(Start_String_211$, 6))
Print "Start index: ", Start_Real_211
EndIf
ElseIf state211 = -3 Then
Print Time$, "Ethernet NG ,Pls Connect it."
Print Time$, "Ethernet NG ,Pls Connect it.."
Print Time$, "Ethernet NG ,Pls Connect it..."
''
Do
CloseNet #210
SetNet #210, "192.168.0.1", 2009, CRLF, NONE, 0
OpenNet #210 As Server
WaitNet #210
Print "#210 Open at ", Time$
If state211 <> -3 Then
Quit All
EndIf
Exit Do
Loop
''
EndIf
EndIf
If MemSw(RecvData) = On And For_LS_tim = 0 Or Start_Real_211 = 888888 Or Start_Real_211 = 666666 Then
Home_POS_Index = 0
'Print "x:", Pdata211$(0), "y:", Pdata211$(1), "u:", Pdata211$(2)
X_String_211$ = Pdata211$(0)
X_Real_211 = Val(X_String_211$)
Y_String_211$ = Pdata211$(1)
Y_Real_211 = Val(Y_String_211$)
U_String_211$ = Pdata211$(2)
U_Real_211 = Val(U_String_211$)
If U_Real_211 > 0 Then
U_Real_211_Angle = -U_Real_211
ElseIf U_Real_211 < 0 Then
U_Real_211_Angle = -U_Real_211
EndIf
'' Off_String_211$ = Pdata211$(3)
'' Print "Off_String_211$", (Off_String_211$)
'' If Off_String_211$ = "Motor_off" Then
'' Print #210, "Motor_Off"
'' Print "Off"
'' Motor Off
'' EndIf
'Print U_Real_211_Angle
Print "Spilt data: ", "x_Real:", X_Real_211, "y_Real:", Y_Real_211, "u_Real:", U_Real_211_Angle
Print #210, "x_Real:", X_Real_211, "y_Real:", Y_Real_211, "u_Real:", U_Real_211_Angle
''
' X_Max = 542.666 -386 -372 -355
' X_Min = -990.222 -915 -805
' Y_Max = 836.666 217 206 286 310
' Y_Min = -122.222 -400 -400 -124
If X_Real_211 >= -805 And X_Real_211 <= -355 And Y_Real_211 >= -124 And Y_Real_211 <= 310 Then
P993 = XY(X_Real_211, Y_Real_211, -6.6666, U_Real_211_Angle)
Jump P993 'Vision_Pre
''Go XY(X_Real_211 + 20, Y_Real_211, -1.666, U_Real_211_Angle)
Else
Print "Error 4007, Target position out of range"
String msg$, title$
Integer mFlags, answer
msg$ = "There has An Error" + CRLF
msg$ = msg$ + "Press Y to Close and Call Tim"
title$ = "Error Message From Robot"
mFlags = MB_YESNO + MB_ICONQUESTION
MsgBox msg$, mFlags, title$, answer
If answer = IDNO Then
Quit All
EndIf
CloseNet #210
Exit Do
EndIf
If U_Real_211_Angle >= 0 Then
X_Real_211 = X_Real_211 + 0
Y_Real_211 = Y_Real_211 + 0
U_Real_211_Angle = U_Real_211_Angle + 0
'' ElseIf U_Real_211_Angle >= -16 And U_Real_211_Angle <= 45 Then
'' X_Real_211 = X_Real_211 + 21.237
'' Y_Real_211 = Y_Real_211 + -6.463
'' U_Real_211_Angle = U_Real_211_Angle + -3.065
'' ElseIf U_Real_211_Angle >= -46 And U_Real_211_Angle <= 75 Then
'' X_Real_211 = X_Real_211 + 24.166
'' Y_Real_211 = Y_Real_211 + -10.672
'' U_Real_211_Angle = U_Real_211_Angle + -2.829
'' ElseIf U_Real_211_Angle >= -76 And U_Real_211_Angle <= 105 Then
'' X_Real_211 = X_Real_211 + 25.630
'' Y_Real_211 = Y_Real_211 + -14.882
'' U_Real_211_Angle = U_Real_211_Angle + -2.592
'' ElseIf U_Real_211_Angle >= -106 And U_Real_211_Angle <= 135 Then
'' X_Real_211 = X_Real_211 + 20.834
'' Y_Real_211 = Y_Real_211 + -13.221
'' U_Real_211_Angle = U_Real_211_Angle + -2.728
'' ElseIf U_Real_211_Angle >= -136 And U_Real_211_Angle <= 165 Then
'' X_Real_211 = X_Real_211 + 16.037
'' Y_Real_211 = Y_Real_211 + -11.559
'' U_Real_211_Angle = U_Real_211_Angle + -2.864
'' ElseIf U_Real_211_Angle >= -166 And U_Real_211_Angle <= 195 Then
'' X_Real_211 = X_Real_211 + 11.241
'' Y_Real_211 = Y_Real_211 + -10.063
'' U_Real_211_Angle = U_Real_211_Angle + -2.728
'' ElseIf U_Real_211_Angle >= -196 And U_Real_211_Angle <= 225 Then
'' X_Real_211 = X_Real_211 + 12.060
'' Y_Real_211 = Y_Real_211 + -7.852
'' U_Real_211_Angle = U_Real_211_Angle + -2.852
'' ElseIf U_Real_211_Angle >= -226 And U_Real_211_Angle <= 255 Then
'' X_Real_211 = X_Real_211 + 12.880
'' Y_Real_211 = Y_Real_211 + -5.641
'' U_Real_211_Angle = U_Real_211_Angle + -2.976
'' ElseIf U_Real_211_Angle >= -256 And U_Real_211_Angle <= 285 Then
'' X_Real_211 = X_Real_211 + 13.699
'' Y_Real_211 = Y_Real_211 + 2.791
'' U_Real_211_Angle = U_Real_211_Angle + -2.976
'' ElseIf U_Real_211_Angle >= -286 And U_Real_211_Angle <= 315 Then
'' X_Real_211 = X_Real_211 + 16.212
'' Y_Real_211 = Y_Real_211 + -0.529
'' U_Real_211_Angle = U_Real_211_Angle + -3.102
'' ElseIf U_Real_211_Angle >= -316 And U_Real_211_Angle <= 345 Then
'' X_Real_211 = X_Real_211 + 18.724
'' Y_Real_211 = Y_Real_211 + -3.849
'' U_Real_211_Angle = U_Real_211_Angle + -3.228
'' ElseIf U_Real_211_Angle >= -346 And U_Real_211_Angle <= -15 Then
'' X_Real_211 = X_Real_211 + +20.082
'' Y_Real_211 = Y_Real_211 + 0.812
'' U_Real_211_Angle = U_Real_211_Angle + -3.302
EndIf
'ADD
Go XY(X_Real_211, Y_Real_211, -247.387, U_Real_211_Angle) 'Down -247.387
On 8 'Vacuum
Wait 3.8
''锟斤拷Go XY(X_Real_211, Y_Real_211, -116, U_Real_211_Angle) 'Up
'Jump S_put
'Go Put
'Wait 1.8
''Jump Put2
Jump P983 'Place
Wait 3.8
Off 8
On 9
Wait 0.6
Off 9
'ADD
Jump P999 'home_Standby
Print "home_Pos"
Print #210, "Home_Pos", "Tim", "OK", "Tim"
Home_POS_Index = 1
For_LS_tim = 1 + For_LS_tim
EndIf
If For_LS_tim = 3 Then
For_LS_tim = 1
EndIf
MemOff RecvData
If Home_POS_Index = 1 Then
Wait 0.00001
''Print #210, "Home"
EndIf
Loop
Fend
Function Rbt_PC216
CloseNet #216
OpenNet #216 As Server
WaitNet #216
Print "Open #216 at ", Time$
For_LS = 1
Print For_LS
Do
'Print #216, "Send data from robot "
Wait 3
Print For_LS
state216 = ChkNet(216)
Print "ChkNet= data", state216
If state216 > 0 And For_LS = 2 Then
'If state216 = 23 Or state216 = 25 Then
Wait 0.01
'Print "Send data XXX"
'send_Data$ = "XXXYYUUU"
'Print #216, send_Data$
'Print #216, "ABCC"
'Input #216, Response$
'Print "ChkNet(216) Line Input: "
'Print Response$
Print "Has data"
Read #216, Data$, state216
DataLS$ = Data$
Print #216, Data$
Print "ChkNet(216) Read: "
Print Data$
Print state216
Integer fileNum2, i, j
fileNum2 = FreeFile
AOpen "D:\V80.txt" As #fileNum2
Line Input #fileNum2, Read_file$
Y_Tim_Real = Val(Read_file$)
Print "Y:", Y_Tim_Real
Print "---"
Close #fileNum2
'Input #216, Data$
'Print "Receive data: ", Data$, Time$
'ParseStr Data$, Pdata_x$(), "XX"
'X_Tim_Real = Val(Pdata_x$)
'Print "X:", X_Tim_Real
X_Tim_Real = Val(Left$(Data$, 8))
Print "X:", X_Tim_Real,
ParseStr DataLS$, Pdata_x$(), "YYY"
Y_Tim_Real = Val(Pdata_x$)
Print "Y:", Y_Tim_Real,
U_Tim_Real = Val(Right$(DataLS$, 13))
Print "U:", U_Tim_Real
'Vision_Process
'Wait start_Awitch = True
Print "Process_锟竭讹拷锟斤拷锟斤拷锟教筹拷锟斤拷执锟斤拷锟叫★拷锟斤拷锟斤拷"
'Call Rbt_PC216
Print "Process_Going 2 St_Pick Pos"
'Speed 100, 100, 100
Go P993
'Go P992
'Speed 100, 100, 5
Print "Process_St_Pick Pos"
'Print Here
'Go XY(X_Tim_Real, Y_Tim_Real, -246.628, 5)
Print Here
Wait 0.1
On 8
'Wait Sw(8) = 1
'Wait 1
'Go P990 'OK POS_LS
Go P992 'OK POS
Off 8
'Wait 1
Go P993
'Go pick
'Print "Process_Pick Pos"
'Vision_Process
'Read #216, Data$, numOfChars
'numOfChars = ChkNet(216)
'Print numOfChars
ElseIf state216 = -3 Then
Print "#216 Close ,Pls open #216 "
ElseIf state216 = 0 Then
Print "#216 Net no data ,Pls check it "
' 锟斤拷止锟斤拷锟斤拷65536
ElseIf state216 > 0 And For_LS = 6 Then
For_LS = 10
ElseIf state216 > 0 And For_LS = 12 Then
For_LS = 5
' 锟斤拷止锟斤拷锟斤拷65536
EndIf
state216 = 25
' If Data$ = 3.15 Then
' Select Pdata$(5)
' Case "10000"
' Print #216, "SHAKEHAND 10000"
' Case "31"
' Print #216, "SHAKEHAND 31"
' Go P999
' Send
' EndIf
For_LS = 1 + For_LS
Loop
Fend
Function Vision_Process
Do
'Wait start_Awitch = True
Print "Process_锟竭讹拷锟斤拷锟斤拷锟教筹拷锟斤拷执锟斤拷锟叫★拷锟斤拷锟斤拷"
'Call Rbt_PC216
Print "Process_Going 2 St_Pick Pos"
'Speed 100, 100, 100
Go S_pick
'Speed 100, 100, 5
Print "Process_St_Pick Pos"
Print Here
Go XY(X_Tim_Real, Y_Tim_Real, -216, 5)
Print Here
'Go pick
'Print "Process_Pick Pos"
Loop
Fend
Function File
Do
Print "File"
Wait 2
Integer fileNu, i, j
' fileNum = FreeFile
' WOpen "timTEST.DAT " As #fileNum
' For i = 0 To 100
'Print #fileNum, i
'Next I
'Close #fileNum
'........
fileNu = FreeFile
ROpen "timTEST88.DAT" As #fileNu
For j = 4 To 8
Input #fileNu, j
Print j
Next j
Close #fileNu
Loop
Fend
Function tcpip_211_1Cycle
CloseNet #210
SetNet #210, "192.168.0.1", 2009, CRLF, NONE, 0
OpenNet #210 As Server
WaitNet #210
Print " #210 Open at ", Time$
MemOff RecvData 'Clean
For_LS = 0
Do
Wait 2
If MemSw(RecvData) = Off Then
state211 = ChkNet(210)
Print "state211: ", state211
Print "For_LS_tim", For_LS_tim
If state211 > 0 And For_LS_tim = 0 Then
Input #210, Data211$
Print Time$, " Recive data: ", Data211$ 'recive data
ParseStr Data211$, Pdata211$(), "Tim" 'spilt data
MemOn RecvData
ElseIf state211 = -3 Then
Print "锟斤拷太锟斤拷通讯锟较匡拷锟斤拷锟斤拷锟铰达拷"
EndIf
EndIf
If MemSw(RecvData) = On And For_LS_tim = 0 Then
'Print "x:", Pdata211$(0), "y:", Pdata211$(1), "u:", Pdata211$(2)
X_String_211$ = Pdata211$(0)
X_Real_211 = Val(X_String_211$)
Y_String_211$ = Pdata211$(1)
Y_Real_211 = Val(Y_String_211$)
U_String_211$ = Pdata211$(2)
U_Real_211 = Val(U_String_211$)
Print " Spilt data: ", "x_Real:", X_Real_211, "y_Real:", Y_Real_211, "u_Real:", U_Real_211
Print #210, "x_Real:", X_Real_211, "y_Real:", Y_Real_211, "u_Real:", U_Real_211
Go XY(X_Real_211, Y_Real_211, -216, U_Real_211)
Wait 3
Go P993
' 锟斤拷止锟斤拷锟斤拷65536
' If state211 > 0 And For_LS = 6 Then
' For_LS_tim = 10
' ElseIf state211 > 0 And For_LS = 12 Then
' For_LS_tim = 5
' EndIf
For_LS_tim = 2 + For_LS_tim
Print "For_LS_tim222", For_LS_tim
' 锟斤拷止锟斤拷锟斤拷65536
' Select Pdata211$(0)
' Case "Tim"
' Print "SHAKEHAND 10000"
' Case "31"
' Print "SHAKEHAND 31"
' Send
EndIf
MemOff RecvData
Loop
Fend
Function To_Robot
Print "To_Robot_锟斤拷始锟斤拷锟斤拷Robot 锟斤拷 PC 通讯锟斤拷锟斤拷"
SetNet #205, "192.168.0.1", 2004, CRLF, NONE, 0
OpenNet #205 As Server
Print "To_Robot_锟皆凤拷锟斤拷锟斤拷锟斤拷式锟斤拷205锟剿匡拷"
Print "To_Robot_锟饺达拷锟斤拷锟斤拷"
WaitNet #205
Print "To_Robot_锟斤拷锟接★拷锟斤拷锟斤拷"
Do
Print "To_Robot_Robot 锟斤拷 PC 通讯锟斤拷锟斤拷锟斤拷锟叫★拷锟斤拷锟斤拷"
Wait 1
Print #205, "Robot used: ", h
'Print #205, ""
Print "Robot used: ", h
ATCLR
Wait 1
'Print #205, "Axis Runing Status not 0 is OK : ", "X=", ATRQ(1), "/", "Y=", ATRQ(2), "/", "Z=", ATRQ(3), "/", "U=", ATRQ(4) 'Send Tor data2
Real statustim
statustim = ChkNet(205)
If statustim > 0 Then
Print "#205 锟斤拷锟斤拷锟斤拷"
Print #205, "Robot used: ", h
Print #205, ""
Print "From #205 Recive data "
Print #205, "send data From Robot 192.168.0.1:205"
Wait .5
Input #205, datattt$
ElseIf statustim = -3 Then
Print "锟斤拷太锟斤拷通讯锟较匡拷锟斤拷锟斤拷锟斤拷锟铰打开斤拷锟斤拷头
'Input #205, datatt$
EndIf
Loop
Fend
Function Process
Do
Print "Process_锟竭讹拷锟斤拷锟斤拷锟教筹拷锟斤拷执锟斤拷锟叫★拷锟斤拷锟斤拷"
Print "Process_Standby Pos"
Go P999
Print "Process_Pick_Standby Pos"
Go S_pick
Print "Process_Pick Pos"
Go pick
Off 8
Wait 1
On 8
Print "Vacuum"
Print "Process_Pick_Standby Pos"
Go S_pick
Print "Process_Put_Standby Pos"
Go S_put
Print "Process_Put"
Go Put
Off 8
Wait 1
Print "Process_Put_Standby Pos"
Go S_put
Wait .6
On 9
Off 9
Print "blow"
Loop
Fend
Function Running_time
Do
h = Time(0) '锟斤拷小时锟斤拷锟斤拷通锟斤拷时锟斤拷
Print "Running_time_Robot 锟窖撅拷使锟斤拷: ", h, "小时 ", ",", " 1锟斤拷锟接回憋拷一锟斤拷"
Wait 60
Loop
Fend
Function Current_POS
CloseNet #215
Print "#215 Config Waiting Servers Open ", Time$
SetNet #215, "192.168.0.150", 1122, CRLF, NONE, 0
OpenNet #215 As Client
WaitNet #215
Print "#215 Config IP:192.168.0.150 Port:1122 Open at ", Time$
Wait 1
Do
' CloseNet #215
' Print "#215 Waiting Servers Open ", Time$
' SetNet #215, "192.168.0.150", 1122, CRLF, NONE, 0
' OpenNet #215 As Client
' WaitNet #215
' Print "#215 IP:192.168.0.150 Port:1122 Open at ", Time$
Check_215 = ChkNet(215)
' Print "#215 Recived Lens: ", Check_215
' If ChkNet(215) > 0 Then
'Print Time$, " Current_POS_is: ", "X:", CX_Here, " ,", "Y:", CY_Here, " ,", "Z:", CZ_Here, " ,", "U:", CU_Here
Wait 0.0003
P982 = CurPos
''Print CX(P982), CY(P982), CY(P982), CY(P982)
Print #215, Time$, " Current_POS_is: ", "X:", CX(P982), " ,", "Y:", CY(P982), " ,", "Z:", CZ(P982), " ,", "U:", CU(P982)
Print Time$, " Current_POS_is: ", "X:", CX(P982), " ,", "Y:", CY(P982), " ,", "Z:", CZ(P982), " ,", "U:", CU(P982)
Integer fileNum6, XXX, YYY, ZZZ, UUU
String ZZZ$, UUU$, XXX$, YYY$
fileNum6 = FreeFile
XXX = CX(P982)
XXX$ = Str$(XXX)
YYY = CY(P982)
YYY$ = Str$(YYY)
ZZZ = CZ(P982)
ZZZ$ = Str$(ZZZ)
UUU = CU(P982)
UUU$ = Str$(UUU)
AOpen "C:\log\Robot_POS.txt" As #fileNum6
Write #fileNum6, Time$ + "Current_POS_is: " + "X:" + "" + XXX$ + "Y:" + "" + YYY$ + "Z:" + "" + ZZZ$ + "U:" + "" + UUU$ + CRLF
Print Time$, "--- Current_POS_is: ", "X:", CX(P982), " ,", "Y:", CY(P982), " ,", "Z:", CZ(P982), " ,", "U:", CU(P982)
Close #fileNum6
' EndIf
Loop
Fend
Function Current_POS_2
Do
Wait 0.25
P982 = CurPos
Integer fileNum6
Real XXX, YYY, ZZZ, UUU, LS_Z, LS_U
String ZZZ$, UUU$, XXX$, YYY$
fileNum6 = FreeFile
XXX = CX(P982)
XXX$ = Str$(XXX)
YYY = CY(P982)
YYY$ = Str$(YYY)
ZZZ = CZ(P982)
ZZZ$ = Str$(ZZZ)
UUU = CU(P982)
UUU$ = Str$(UUU)
AOpen "C:\log\Robot_POS.txt" As #fileNum6
LS_U = Val(Left$(Str$(CU(P982)), 6))
LS_Z = Val(Left$(Str$(CZ(P982)), 6))
If LS_U <> CU(P999) And LS_Z <> CZ(P999) Then ''ZU
Print Time$, "Save POS Data", LS_U, LS_Z, "VS", CU(P999), CZ(P999)
Write #fileNum6, Time$ + "Current_POS_is: " + "X:" + "" + XXX$ + "Y:" + "" + YYY$ + "Z:" + "" + ZZZ$ + "U:" + "" + UUU$ + CRLF
Print Time$, "--- Current_POS_is: ", "X:", CX(P982), " ,", "Y:", CY(P982), " ,", "Z:", CZ(P982), " ,", "U:", CU(P982)
EndIf
Close #fileNum6
Loop
Fend
Function Move_Current_POS
Do
Jump A2_Alignmnet_Ref
BMove XY(100, 0, -58.888, -45) '锛堝湪鏈湴鍧愭爣绯讳腑锛夊悜 X 鏂瑰悜绉诲姩 100mm)
Go A1_Alignmnet_Ref
BGo XY(-80.88, 0, -18.888, -180) '锛堝湪鏈湴鍧愭爣绯讳腑锛夊悜 X 鏂瑰悜绉诲姩 100mm)
Print "Running_"
Wait 0.5
Loop
Fend
--------------------------------------------
'
'Design By Tim main.prg
'
Global Integer h, InData, OutData, start_Awitch, Long_Tim, For_LS, fileNum, RecvData, For_LS_tim
Global Real CX_Here, X_Tim_Real, Y_Tim_Real, U_Tim_Real
Global Real CY_Here
Global Real CZ_Here
Global Real CU_Here
Global String datattt$, Data$, DataLS$, Response$, X_Tim_string$, Y_Tim_String$, Data_Client$, send_Data$, Read_file$, Data211$, X_String_211$, Y_String_211$, U_String_211$, Start_String_211$, Clean_Tim$, Data210$
Global String Pdata_x$(100), Pdata_y$(100), Pdata$(100), Pdata211$(100)
Global Real state216, state21666, numOfChars, state_client, state211, X_Real_211, Y_Real_211, U_Real_211, U_Real_211_Angle, Start_Real_211
Global Real state212, Pitch, Area_Sensor___, III, Check_215
Global String Data_212$, PData_212$(100), Data_212_Start$, Off_String_211$, Area_Sensor_$, Area_Sensor___$
Global Integer errnum, Data_212_Read, Status_212, Index, Order, Home_POS_Index
Function main
Motor On
Power High
Speed 100 'Go Speed Tim on High ,Off Low
SpeedS 2000 'MAX 2000
Print "Program Runing at: ", Time$
Print "The current control device is:", CtrlDev, " Remark锟斤拷21 PC锟斤拷22 Remote I/O锟斤拷26 Remote Ethernet锟斤拷29 Remote RS232C"
Print "Waiting... "
''
Xqt Big_TCP_212_Runmode, Normal 'Big_Vison
''
Xqt Current_POS_2, Normal 'NoPause
Xqt Welcome, Normal 'NoPauseWelcome
Xqt Recive_lendayu62, Normal 'Recive data Lens>62 Alarm
'Xqt TCP_209_AreaSensor_As_Client, Normal 'Big_AreaSensor
'Xqt To_Robot, Normal
'Xqt tcpip_208_Jog, Normal
'Xqt tcpip_211_1Cycle, Normal
'Xqt Rbt_PC216, Normal
'Xqt Vision_Process, Normal
'Xqt Process, Normal
'Xqt Running_time, NoPause
'Xqt Current_POS, Normal 'NoPause
'Xqt Move_Current_POS, Normal 'NoPause
'Xqt Alignment_TCP_212, Normal 'Aligenmnet
'Xqt Welcome, Normal
'Xqt Recive_lendayu62, Normal
'Xqt File, Normal
Fend
3rd
NEW Page to bigger