From 6b280e75fe4168fdbc72c2d3fd52b0a8b426198d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=90=89=E7=92=83=E6=9C=88=E5=85=89?= <15630071+llyg777@user.noreply.gitee.com> Date: Fri, 15 Aug 2025 14:03:07 +0800 Subject: [PATCH] =?UTF-8?q?EMV=E5=BB=B6=E8=BF=9F=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E9=9B=86=E6=88=90=EF=BC=8C=E6=97=A7EMV=E5=9C=A8=E5=90=8C?= =?UTF-8?q?=E5=90=8D=E6=96=87=E4=BB=B6=E5=A4=B9=E4=B8=8BEMV=5Fold=5Fsave?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EMV/EMV.py | 210 ++++----- EMV/EMV_old_save.py | 401 ++++++++++++++++++ ...MV_reneer.py => EMV_reneer_pengqi_save.py} | 0 EMV/__pycache__/EMV.cpython-39.pyc | Bin 10015 -> 9524 bytes ...ALL_test.py => all_sensors_device_test.py} | 0 EMV/{code_statue.py => code_statue_test.py} | 0 ...MV_test_sensor.py => only_sensor1_test.py} | 0 EMV/{test_EMV.py => sensors_test.py} | 0 EMV/test.py | 2 - 9 files changed, 489 insertions(+), 124 deletions(-) create mode 100644 EMV/EMV_old_save.py rename EMV/{EMV_reneer.py => EMV_reneer_pengqi_save.py} (100%) rename EMV/{ALL_test.py => all_sensors_device_test.py} (100%) rename EMV/{code_statue.py => code_statue_test.py} (100%) rename EMV/{EMV_test_sensor.py => only_sensor1_test.py} (100%) rename EMV/{test_EMV.py => sensors_test.py} (100%) delete mode 100644 EMV/test.py diff --git a/EMV/EMV.py b/EMV/EMV.py index b3c3d48..91a8f93 100644 --- a/EMV/EMV.py +++ b/EMV/EMV.py @@ -8,15 +8,37 @@ import logging from PySide6.QtCore import Signal, QObject import numpy as np + class RelayController: need_origin_signal = Signal(str) take_no_photo_sigal = Signal() update_detect_image = Signal(np.ndarray) log_signal = Signal(int, str) + def __init__(self, host='192.168.0.18', port=50000): + # ===================== 全局线程延时参数 ===================== + self.sensor1_loop_delay = 0.2 # SENSOR1 线程轮询间隔(秒) + self.sensor1_error_delay = 1.0 # SENSOR1 出错时延时(秒) + self.sensor1_post_action_delay = 0.2 # SENSOR1 每次循环后延时(秒) + + self.sensor2_loop_delay = 0.5 # SENSOR2 线程轮询间隔(秒) + self.sensor2_error_delay = 0.5 # SENSOR2 出错时延时(秒) + self.sensor2_post_action_delay = 0.2 # SENSOR2 每次循环后延时(秒) + # ===================== 全局动作延时参数 ===================== + self.delay_conveyor = 0.5 # 传送带开/关动作延时(一半时间,我在控制程序和线程都加了一样的延时) + self.delay_pusher = 0.05 # 推板开/关动作延时 + self.delay_clamp = 0.5 # 夹爪动作延时 + self.delay_after_pusher = 3.0 # 推板推出后到重启传动带时间 + + # ===================== 传感器稳定检测参数 ===================== + self.sensor_stable_duration = 1.0 # 传感器状态稳定检测时间(秒) + self.sensor_max_attempts = 3 # 连续检测次数达到此值判定有效 + self.sensor1_debounce_time = 1.0 # 传感器1防抖时间(秒) + + # ===================== 网络与设备映射 ===================== self.host = host self.port = port - # 控件映射 + self.CONVEYOR1 = 'conveyor1' self.PUSHER = 'pusher' self.CONVEYOR2 = 'conveyor2' @@ -28,10 +50,9 @@ class RelayController: self.valve_commands = { self.CONVEYOR1: {'open': '00000000000601050000FF00', 'close': '000000000006010500000000'}, self.PUSHER: {'open': '00000000000601050001FF00', 'close': '000000000006010500010000'}, - #self.CONVEYOR2: {'open': '00000000000601050002FF00', 'close': '000000000006010500020000'}, self.CONVEYOR2: {'open': '000100000006020620000012', 'close': '000100000006020620000001'}, self.CLAMP: {'open': '00000000000601050003FF00', 'close': '000000000006010500030000'}, - self.PUSHER1: {'open': '00000000000601050004FF00', 'close': '000000000006010500040000'}# + self.PUSHER1: {'open': '00000000000601050004FF00', 'close': '000000000006010500040000'} } self.read_status_command = { @@ -39,7 +60,6 @@ class RelayController: 'sensors': '000000000006010200000008' } - self.device_bit_map = { self.CONVEYOR1: 0, self.PUSHER: 1, @@ -50,7 +70,7 @@ class RelayController: self.sensor_bit_map = { self.SENSOR1: 0, - self.SENSOR2: 1,# + self.SENSOR2: 1, } self.device_name_map = { @@ -66,27 +86,21 @@ class RelayController: self.SENSOR2: '位置传感器2', } - # 传感器状态变量 + # ===================== 状态控制变量 ===================== self._running = False self._sensor1_thread = None self._sensor2_thread = None - # 配置项 - self.required_codes = {'0101', '0103'} # 有效状态码 - self.required_codes_1 = { '0102', '0103'} # 有效状态码(需要修改) - self.stable_duration = 1.0 # 稳定检测时间(秒) - self.max_attempts = 3 # 连续检测次数 - self.poll_interval = 0.2 # 检测间隔 + self.required_codes = {'0101', '0103'} # 有效状态码(传感器1) + self.required_codes_1 = {'0102', '0103'} # 有效状态码(传感器2) - # 状态锁和防抖 self.sensor1_triggered = False self.sensor1_last_time = 0 - self.sensor1_debounce = 2.0 - # 传感器2状态变量 self.sensor2_ready = True self.motor_stopped_by_sensor2 = False + # ===================== 基础通信方法 ===================== def send_command(self, command_hex, retry_count=2, source='unknown'): byte_data = binascii.unhexlify(command_hex) for attempt in range(retry_count): @@ -113,6 +127,7 @@ class RelayController: def trigger_alarm(self): print("警告:连续多次通信失败,请检查设备连接!") + # ===================== 状态读取方法 ===================== def get_all_device_status(self, command_type='devices'): command = self.read_status_command.get(command_type) if not command: @@ -126,7 +141,6 @@ class RelayController: if response and len(response) >= 10: status_byte = response[9] status_bin = f"{status_byte:08b}"[::-1] - bit_map = self.device_bit_map if command_type == 'devices' else self.sensor_bit_map name_map = self.device_name_map if command_type == 'devices' else self.sensor_name_map @@ -175,36 +189,28 @@ class RelayController: return response[16:20] return None - def is_valid_sensor_status(self, sensor_name: object) -> object: - """ - 检查传感器是否在稳定时间内连续返回有效状态码(01 或 03) - """ + def is_valid_sensor_status(self, sensor_name): stable_count = 0 - for _ in range(int(self.stable_duration / self.poll_interval)): + for _ in range(int(self.sensor_stable_duration / self.sensor1_loop_delay)): responses = self.get_all_sensor_responses('sensors') response = responses.get(sensor_name) if not response: - print(f"[警告] 无法获取 {sensor_name} 的响应,尝试重试...") stable_count = 0 else: status_code = self.parse_status_code(response) if status_code in self.required_codes: stable_count += 1 - if stable_count >= self.max_attempts: + if stable_count >= self.sensor_max_attempts: return True else: stable_count = 0 - print(f"[警告] {sensor_name} 状态码无效: {status_code}") - time.sleep(self.poll_interval) + time.sleep(self.sensor1_loop_delay) return False - def is_valid_sensor_status_1(self, sensor_name: object) -> object: - """ - 检查传感器是否在稳定时间内连续返回有效状态码(01 或 03) - """ + def is_valid_sensor_status_1(self, sensor_name): stable_count = 0 - for _ in range(int(self.stable_duration / self.poll_interval)): + for _ in range(int(self.sensor_stable_duration / self.sensor2_loop_delay)): responses = self.get_all_sensor_responses('sensors') response = responses.get(sensor_name) @@ -215,149 +221,109 @@ class RelayController: status_code = self.parse_status_code(response) if status_code in self.required_codes_1: stable_count += 1 - if stable_count >= self.max_attempts: + if stable_count >= self.sensor_max_attempts: return True else: stable_count = 0 - print(f"[警告] {sensor_name} 状态码无效: {status_code}") - time.sleep(self.poll_interval) + time.sleep(self.sensor2_loop_delay) return False - + # ===================== 动作控制方法 ===================== def open(self, conveyor1=False, pusher=False, conveyor2=False, clamp=False, pusher1=False): status = self.get_all_device_status() if conveyor1 and not status.get(self.CONVEYOR1, False): - print("打开传送带1") - self.send_command(self.valve_commands[self.CONVEYOR1]['open'], source='device') - time.sleep(1) - + self.send_command(self.valve_commands[self.CONVEYOR1]['open']) + time.sleep(self.delay_conveyor) if pusher and not status.get(self.PUSHER, False): - print("打开推板") - self.send_command(self.valve_commands[self.PUSHER]['open'], source='device') - time.sleep(0.05) - + self.send_command(self.valve_commands[self.PUSHER]['open']) + time.sleep(self.delay_pusher) if conveyor2 and not status.get(self.CONVEYOR2, False): - print("打开传送带2") - self.send_command(self.valve_commands[self.CONVEYOR2]['open'], source='device') - time.sleep(1) - + self.send_command(self.valve_commands[self.CONVEYOR2]['open']) + time.sleep(self.delay_conveyor) if clamp and not status.get(self.CLAMP, False): - print("启动机械臂抓夹") - self.send_command(self.valve_commands[self.CLAMP]['open'], source='device') - time.sleep(0.5) - + self.send_command(self.valve_commands[self.CLAMP]['open']) + time.sleep(self.delay_clamp) if pusher1 and not status.get(self.PUSHER1, False): - print("关闭推板") - self.send_command(self.valve_commands[self.PUSHER1]['open'], source='device') - time.sleep(0.05) - + self.send_command(self.valve_commands[self.PUSHER1]['open']) + time.sleep(self.delay_pusher) def close(self, conveyor1=False, pusher=False, conveyor2=False, clamp=False, pusher1=False): - status = self.get_all_device_status() - if conveyor1 : - #if conveyor1 and status.get(self.CONVEYOR1, True): - print("关闭传送带1") - self.send_command(self.valve_commands[self.CONVEYOR1]['close'], source='device') - time.sleep(1) - - if pusher : - #if pusher and status.get(self.PUSHER, True): - print("关闭推板") - self.send_command(self.valve_commands[self.PUSHER]['close'], source='device') - time.sleep(0.05) - - if conveyor2 : - #if conveyor2 and status.get(self.CONVEYOR2, True): - print("关闭传送带2") - self.send_command(self.valve_commands[self.CONVEYOR2]['close'], source='device') - time.sleep(1) - - if clamp : - #if clamp and status.get(self.CLAMP, True): - print("停止机械臂抓夹") - self.send_command(self.valve_commands[self.CLAMP]['close'], source='device') - time.sleep(0.5) - - if pusher1 : - #if pusher and status.get(self.PUSHER1, True): - print("关闭推板_1") - self.send_command(self.valve_commands[self.PUSHER1]['close'], source='device') - time.sleep(0.05) + if conveyor1: + self.send_command(self.valve_commands[self.CONVEYOR1]['close']) + time.sleep(self.delay_conveyor) + if pusher: + self.send_command(self.valve_commands[self.PUSHER]['close']) + time.sleep(self.delay_pusher) + if conveyor2: + self.send_command(self.valve_commands[self.CONVEYOR2]['close']) + time.sleep(self.delay_conveyor) + if clamp: + self.send_command(self.valve_commands[self.CLAMP]['close']) + time.sleep(self.delay_clamp) + if pusher1: + self.send_command(self.valve_commands[self.PUSHER1]['close']) + time.sleep(self.delay_pusher) + # ===================== 传感器处理线程 ===================== def handle_sensor1(self): while self._running: try: - # 检查传感器是否返回有效状态码(01 或 03) if self.is_valid_sensor_status(self.SENSOR1): current_time = time.time() - # 判断是否已触发 或 是否在防抖时间内 - if not self.sensor1_triggered and (current_time - self.sensor1_last_time) > self.sensor1_debounce: - print("✅ SENSOR1 检测到有效信号,开始执行推料流程") - # 标记已触发,防止重复执行 + if not self.sensor1_triggered and ( + current_time - self.sensor1_last_time) > self.sensor1_debounce_time: self.sensor1_triggered = True self.sensor1_last_time = current_time - # 1. 停止包装机皮带电机(关闭) + # 1.停止包装机皮带电机:关闭 conveyor1 self.close(conveyor1=True) - time.sleep(0.5) - # 2. 推板开启 + time.sleep(self.delay_conveyor) + # 2.推板开启:推出去动作 self.open(pusher=True) - time.sleep(0.1) + time.sleep(self.delay_pusher) self.close(pusher=True) - # 2结束 - time.sleep(3) # 保持 3 秒 - # 3. 包装机皮带电机开启 + # 推板推出后重新启动电机时间传送带1延时 + time.sleep(self.delay_after_pusher) + # 3.重新开启包装机皮带电机: 开启conveyor1 self.open(conveyor1=True) - time.sleep(0.5) - # 4. 推板关闭 - #self.close(pusher=True) + time.sleep(self.delay_conveyor) + # 4.推板关闭:推板收回来动作 self.open(pusher1=True) - time.sleep(0.1) + time.sleep(self.delay_pusher) self.close(pusher1=True) time.sleep(1) # 5. 状态检查(可选) status = self.get_all_device_status() if status.get('conveyor1') and not status.get('pusher'): - print("🟢流程完成1:皮带运行中,推板已收回") + print("流程完成1:皮带运行中,推板已收回") else: - print("⚠️ 状态异常,请检查设备") + print("状态异常,请检查设备") # 流程结束,重置触发标志 self.sensor1_triggered = False - # 如果传感器无效,确保触发标志可重置(可选) - time.sleep(0.2) - + time.sleep(self.sensor1_loop_delay) except Exception as e: print(f"SENSOR1 处理错误: {e}") self.sensor1_triggered = False - time.sleep(1) + time.sleep(self.sensor1_error_delay) - - #传感器2检测到料包 → 立即停止 conveyor2」这个逻辑 放在传感器线程中处理 def handle_sensor2(self): while self._running: try: - # 检测传感器2状态 - #self.sensor2_ready = None if self.is_valid_sensor_status_1(self.SENSOR2): - print("✅ SENSOR2 检测到有效信号,开始执行关闭滚筒电机流程") if not self.sensor2_ready: - #self.log_signal.emit(logging.INFO, "🟢 传感器2检测到料包到位,立即停止 conveyor2") - # ✅ 立即停止电机(不管机器人是否在抓取) self.close(conveyor2=True) - print("执行关闭") - self.motor_stopped_by_sensor2 = True # 标记为传感器2触发停止 + self.motor_stopped_by_sensor2 = True self.sensor2_ready = True else: if self.sensor2_ready and self.motor_stopped_by_sensor2: - #self.log_signal.emit(logging.INFO, "🟡 传感器2未检测到料包,准备重新启动 conveyor2") - # ✅ 重新启动 conveyor2(可选) self.open(conveyor2=True) self.motor_stopped_by_sensor2 = False self.sensor2_ready = False - - time.sleep(0.5) + time.sleep(self.sensor2_loop_delay) except Exception as e: - self.log_signal.emit(logging.ERROR, f"🔴 SENSOR2 处理错误: {e}") - time.sleep(1) + print(f"SENSOR2 处理错误: {e}") + time.sleep(self.sensor2_error_delay) + + # ===================== 线程控制方法 ===================== def start(self): if self._running: print("线程已经在运行") @@ -398,4 +364,4 @@ if __name__ == '__main__': while True: time.sleep(1) except KeyboardInterrupt: - controller.stop() \ No newline at end of file + controller.stop() diff --git a/EMV/EMV_old_save.py b/EMV/EMV_old_save.py new file mode 100644 index 0000000..b3c3d48 --- /dev/null +++ b/EMV/EMV_old_save.py @@ -0,0 +1,401 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import socket +import binascii +import time +import threading +import logging +from PySide6.QtCore import Signal, QObject +import numpy as np + +class RelayController: + need_origin_signal = Signal(str) + take_no_photo_sigal = Signal() + update_detect_image = Signal(np.ndarray) + log_signal = Signal(int, str) + def __init__(self, host='192.168.0.18', port=50000): + self.host = host + self.port = port + # 控件映射 + self.CONVEYOR1 = 'conveyor1' + self.PUSHER = 'pusher' + self.CONVEYOR2 = 'conveyor2' + self.CLAMP = 'clamp' + self.PUSHER1 = 'pusher1' + self.SENSOR1 = 'sensor1' + self.SENSOR2 = 'sensor2' + + self.valve_commands = { + self.CONVEYOR1: {'open': '00000000000601050000FF00', 'close': '000000000006010500000000'}, + self.PUSHER: {'open': '00000000000601050001FF00', 'close': '000000000006010500010000'}, + #self.CONVEYOR2: {'open': '00000000000601050002FF00', 'close': '000000000006010500020000'}, + self.CONVEYOR2: {'open': '000100000006020620000012', 'close': '000100000006020620000001'}, + self.CLAMP: {'open': '00000000000601050003FF00', 'close': '000000000006010500030000'}, + self.PUSHER1: {'open': '00000000000601050004FF00', 'close': '000000000006010500040000'}# + } + + self.read_status_command = { + 'devices': '000000000006010100000008', + 'sensors': '000000000006010200000008' + } + + + self.device_bit_map = { + self.CONVEYOR1: 0, + self.PUSHER: 1, + self.CONVEYOR2: 2, + self.CLAMP: 3, + self.PUSHER1: 4, + } + + self.sensor_bit_map = { + self.SENSOR1: 0, + self.SENSOR2: 1,# + } + + self.device_name_map = { + self.CONVEYOR1: "传送带1", + self.PUSHER: "推板开", + self.CONVEYOR2: "传送带2", + self.CLAMP: "机械臂夹爪", + self.PUSHER1: "推板关", + } + + self.sensor_name_map = { + self.SENSOR1: '位置传感器1', + self.SENSOR2: '位置传感器2', + } + + # 传感器状态变量 + self._running = False + self._sensor1_thread = None + self._sensor2_thread = None + + # 配置项 + self.required_codes = {'0101', '0103'} # 有效状态码 + self.required_codes_1 = { '0102', '0103'} # 有效状态码(需要修改) + self.stable_duration = 1.0 # 稳定检测时间(秒) + self.max_attempts = 3 # 连续检测次数 + self.poll_interval = 0.2 # 检测间隔 + + # 状态锁和防抖 + self.sensor1_triggered = False + self.sensor1_last_time = 0 + self.sensor1_debounce = 2.0 + + # 传感器2状态变量 + self.sensor2_ready = True + self.motor_stopped_by_sensor2 = False + + def send_command(self, command_hex, retry_count=2, source='unknown'): + byte_data = binascii.unhexlify(command_hex) + for attempt in range(retry_count): + try: + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: + sock.settimeout(10) + sock.connect((self.host, self.port)) + sock.send(byte_data) + response = sock.recv(1024) + hex_response = binascii.hexlify(response).decode('utf-8') + #if source == 'sensor': + #print(f"[传感器响应] {hex_response}") + #elif source == 'device': + #print(f"[设备控制响应] {hex_response}") + #else: + #print(f"[通信响应] {hex_response}") + return response + except Exception as e: + print(f"通信错误 ({source}): {e}, 尝试重连... ({attempt + 1}/{retry_count})") + time.sleep(5) + self.trigger_alarm() + return None + + def trigger_alarm(self): + print("警告:连续多次通信失败,请检查设备连接!") + + def get_all_device_status(self, command_type='devices'): + command = self.read_status_command.get(command_type) + if not command: + print(f"未知的读取类型: {command_type}") + return {} + + source = 'sensor' if command_type == 'sensors' else 'device' + response = self.send_command(command, source=source) + status_dict = {} + + if response and len(response) >= 10: + status_byte = response[9] + status_bin = f"{status_byte:08b}"[::-1] + + bit_map = self.device_bit_map if command_type == 'devices' else self.sensor_bit_map + name_map = self.device_name_map if command_type == 'devices' else self.sensor_name_map + + for key, bit_index in bit_map.items(): + status_dict[key] = status_bin[bit_index] == '1' + else: + print(f"[{command_type}] 读取状态失败或响应无效") + + return status_dict + + def get_all_sensor_responses(self, command_type='sensors'): + """ + 获取所有传感器的原始 Modbus 响应字符串 + 示例:{'sensor1': '00000000000401020101', 'sensor2': '00000000000401020100'} + """ + command = self.read_status_command.get(command_type) + if not command: + print(f"未知的读取类型: {command_type}") + return {} + + source = 'sensor' if command_type == 'sensors' else 'device' + response = self.send_command(command, source=source) + responses = {} + + if response and len(response) >= 10: + hex_response = binascii.hexlify(response).decode('utf-8') + print(f"[原始响应][{command_type}] {hex_response}") + + # 假设传感器数据从第 9 字节开始,长度为 2 字节 + for name, bit_index in self.sensor_bit_map.items(): + offset = 9 + (bit_index // 8) + bit_pos = bit_index % 8 + byte = response[offset] + status = (byte >> bit_pos) & 1 + responses[name] = hex_response + else: + print(f"[{command_type}] 无法获取响应数据") + return responses + + def parse_status_code(self, response): + """ + 从 Modbus 响应字符串中提取状态码(后两位) + 示例:00000000000401020101 -> '01' + """ + if isinstance(response, str) and len(response) >= 18: + return response[16:20] + return None + + def is_valid_sensor_status(self, sensor_name: object) -> object: + """ + 检查传感器是否在稳定时间内连续返回有效状态码(01 或 03) + """ + stable_count = 0 + for _ in range(int(self.stable_duration / self.poll_interval)): + responses = self.get_all_sensor_responses('sensors') + response = responses.get(sensor_name) + + if not response: + print(f"[警告] 无法获取 {sensor_name} 的响应,尝试重试...") + stable_count = 0 + else: + status_code = self.parse_status_code(response) + if status_code in self.required_codes: + stable_count += 1 + if stable_count >= self.max_attempts: + return True + else: + stable_count = 0 + print(f"[警告] {sensor_name} 状态码无效: {status_code}") + time.sleep(self.poll_interval) + return False + + def is_valid_sensor_status_1(self, sensor_name: object) -> object: + """ + 检查传感器是否在稳定时间内连续返回有效状态码(01 或 03) + """ + stable_count = 0 + for _ in range(int(self.stable_duration / self.poll_interval)): + responses = self.get_all_sensor_responses('sensors') + response = responses.get(sensor_name) + + if not response: + print(f"[警告] 无法获取 {sensor_name} 的响应,尝试重试...") + stable_count = 0 + else: + status_code = self.parse_status_code(response) + if status_code in self.required_codes_1: + stable_count += 1 + if stable_count >= self.max_attempts: + return True + else: + stable_count = 0 + print(f"[警告] {sensor_name} 状态码无效: {status_code}") + time.sleep(self.poll_interval) + return False + + + def open(self, conveyor1=False, pusher=False, conveyor2=False, clamp=False, pusher1=False): + status = self.get_all_device_status() + if conveyor1 and not status.get(self.CONVEYOR1, False): + print("打开传送带1") + self.send_command(self.valve_commands[self.CONVEYOR1]['open'], source='device') + time.sleep(1) + + if pusher and not status.get(self.PUSHER, False): + print("打开推板") + self.send_command(self.valve_commands[self.PUSHER]['open'], source='device') + time.sleep(0.05) + + if conveyor2 and not status.get(self.CONVEYOR2, False): + print("打开传送带2") + self.send_command(self.valve_commands[self.CONVEYOR2]['open'], source='device') + time.sleep(1) + + if clamp and not status.get(self.CLAMP, False): + print("启动机械臂抓夹") + self.send_command(self.valve_commands[self.CLAMP]['open'], source='device') + time.sleep(0.5) + + if pusher1 and not status.get(self.PUSHER1, False): + print("关闭推板") + self.send_command(self.valve_commands[self.PUSHER1]['open'], source='device') + time.sleep(0.05) + + + def close(self, conveyor1=False, pusher=False, conveyor2=False, clamp=False, pusher1=False): + status = self.get_all_device_status() + if conveyor1 : + #if conveyor1 and status.get(self.CONVEYOR1, True): + print("关闭传送带1") + self.send_command(self.valve_commands[self.CONVEYOR1]['close'], source='device') + time.sleep(1) + + if pusher : + #if pusher and status.get(self.PUSHER, True): + print("关闭推板") + self.send_command(self.valve_commands[self.PUSHER]['close'], source='device') + time.sleep(0.05) + + if conveyor2 : + #if conveyor2 and status.get(self.CONVEYOR2, True): + print("关闭传送带2") + self.send_command(self.valve_commands[self.CONVEYOR2]['close'], source='device') + time.sleep(1) + + if clamp : + #if clamp and status.get(self.CLAMP, True): + print("停止机械臂抓夹") + self.send_command(self.valve_commands[self.CLAMP]['close'], source='device') + time.sleep(0.5) + + if pusher1 : + #if pusher and status.get(self.PUSHER1, True): + print("关闭推板_1") + self.send_command(self.valve_commands[self.PUSHER1]['close'], source='device') + time.sleep(0.05) + + def handle_sensor1(self): + while self._running: + try: + # 检查传感器是否返回有效状态码(01 或 03) + if self.is_valid_sensor_status(self.SENSOR1): + current_time = time.time() + # 判断是否已触发 或 是否在防抖时间内 + if not self.sensor1_triggered and (current_time - self.sensor1_last_time) > self.sensor1_debounce: + print("✅ SENSOR1 检测到有效信号,开始执行推料流程") + # 标记已触发,防止重复执行 + self.sensor1_triggered = True + self.sensor1_last_time = current_time + # 1. 停止包装机皮带电机(关闭) + self.close(conveyor1=True) + time.sleep(0.5) + # 2. 推板开启 + self.open(pusher=True) + time.sleep(0.1) + self.close(pusher=True) + # 2结束 + time.sleep(3) # 保持 3 秒 + # 3. 包装机皮带电机开启 + self.open(conveyor1=True) + time.sleep(0.5) + # 4. 推板关闭 + #self.close(pusher=True) + self.open(pusher1=True) + time.sleep(0.1) + self.close(pusher1=True) + time.sleep(1) + # 5. 状态检查(可选) + status = self.get_all_device_status() + if status.get('conveyor1') and not status.get('pusher'): + print("🟢流程完成1:皮带运行中,推板已收回") + else: + print("⚠️ 状态异常,请检查设备") + # 流程结束,重置触发标志 + self.sensor1_triggered = False + # 如果传感器无效,确保触发标志可重置(可选) + time.sleep(0.2) + + except Exception as e: + print(f"SENSOR1 处理错误: {e}") + self.sensor1_triggered = False + time.sleep(1) + + + #传感器2检测到料包 → 立即停止 conveyor2」这个逻辑 放在传感器线程中处理 + def handle_sensor2(self): + while self._running: + try: + # 检测传感器2状态 + #self.sensor2_ready = None + if self.is_valid_sensor_status_1(self.SENSOR2): + print("✅ SENSOR2 检测到有效信号,开始执行关闭滚筒电机流程") + if not self.sensor2_ready: + #self.log_signal.emit(logging.INFO, "🟢 传感器2检测到料包到位,立即停止 conveyor2") + # ✅ 立即停止电机(不管机器人是否在抓取) + self.close(conveyor2=True) + print("执行关闭") + self.motor_stopped_by_sensor2 = True # 标记为传感器2触发停止 + self.sensor2_ready = True + else: + if self.sensor2_ready and self.motor_stopped_by_sensor2: + #self.log_signal.emit(logging.INFO, "🟡 传感器2未检测到料包,准备重新启动 conveyor2") + # ✅ 重新启动 conveyor2(可选) + self.open(conveyor2=True) + self.motor_stopped_by_sensor2 = False + self.sensor2_ready = False + + time.sleep(0.5) + except Exception as e: + self.log_signal.emit(logging.ERROR, f"🔴 SENSOR2 处理错误: {e}") + time.sleep(1) + def start(self): + if self._running: + print("线程已经在运行") + return + print("启动传感器线程") + self._running = True + self._sensor1_thread = threading.Thread(target=self.handle_sensor1, daemon=True) + self._sensor2_thread = threading.Thread(target=self.handle_sensor2, daemon=True) + self._sensor1_thread.start() + self._sensor2_thread.start() + + def stop(self): + if not self._running: + print("线程未在运行") + return + print("停止传感器线程") + self._running = False + if self._sensor1_thread: + self._sensor1_thread.join() + if self._sensor2_thread: + self._sensor2_thread.join() + print("传感器线程已终止。") + + def start_sensor1_only(self): + if self._running: + print("传感器线程已经在运行") + return + print("启动传感器1监听线程...") + self._running = True + self._sensor1_thread = threading.Thread(target=self.handle_sensor1, daemon=True) + self._sensor1_thread.start() + + +if __name__ == '__main__': + controller = RelayController() + controller.start() + try: + while True: + time.sleep(1) + except KeyboardInterrupt: + controller.stop() \ No newline at end of file diff --git a/EMV/EMV_reneer.py b/EMV/EMV_reneer_pengqi_save.py similarity index 100% rename from EMV/EMV_reneer.py rename to EMV/EMV_reneer_pengqi_save.py diff --git a/EMV/__pycache__/EMV.cpython-39.pyc b/EMV/__pycache__/EMV.cpython-39.pyc index 54c702a2eaa18a53913cb0a8fccefb3864e717ee..aa84c29a552c121584360ec0dfb6baa0a9a6c406 100644 GIT binary patch delta 4711 zcmai1U2Ggz6`ngYJ3Bl3Z;x^7cD>PP+Thg73!U5w&*8km17@jzh1qO)zFnU2s|`1l4{c0tU}MtWz{aF4 zZM1JQl9J!HXBzG~XQ9D6iQv6C?^PV$iHD>0@?5i%4PMG;eTUnjKp~i(?fK>Dx?{sU zFVhTH)?&|#)Qa4_l*ss7x@Un zRfT^HAO9qJPo**E?5RAz=g+_R+ReA$7SBcp#TBsp!?@i|%N&&b!hEsiM=pVuBwKPbCKoY3!7EF8RbGcT7Hy2JLdajxnJRQzZR)?O8G)~aB)%EacdVPrCD8VrTxw09gipjvCKwO6)SQb*97;-?D#wn| zID6J}{8Dtf>Qf1nbP8uDX9PXS%*pli_;;7Mz zAkS#gP8dC>@Jb6e`vc07N*i{~d^W=COac9*;^M}?r24UC+_r1lWyX}}`XGWkl`+Nf z%m|}E9zJ!X80QaTo?*gNU7ruqXfJ_FAe~O7!}k#k5j;uo6vEZ0TyrNLmNq%Eln4ua z2Fup(Fq_v%oZM212X2%exYI|63RTZOSFTsV4y^^kzd=QhCZ%9<^)aeN9cvMv%%p#O zOR>cX@k(Jr?9FGa2uk8|6z?14Rn`=h{2n$bUd@jeTj(2O)i>5M9%ie)iK1`J72k*( zxx=NzBbkHOX-0mQLj(B&JQJ;9d&=>zBj(A%T6ejA0&EhMC z$J)IZ8jP}XS-}`Hez0XM<8fS5fn8R;gE)d2Qo}>MruO53->*G)FGq=@&5iFMSj|h`N3UB6`U$oXj1g=m7)K}u zsmtX~6Cp6(xO8z`*fzs$(rB7tGW z?qeClT$7>2C9^P)+A@U}3tR^BSeKNsPAZ6k#(9?%1^5nIZD~yBuXc&W)`?j`c=)fn zq$r5D8#+vVCDAom_jV}Di2pGYJ*&P8CUkkt;zNb(A8~?+i(WU1% z#>M;zYLgyrh;I$-XrGl;RZ}qirZ2EX>{o-Ty3CMc`P#CE^+v(aF(EB#fNPOH3Xt(E zayS+RwtKp4jImR#MS+3(b*emV85`tUP(?}&o#J;Dc%hAF^cRiM<-nc{(w~4~8an z+UCT&L&NQP+B{D_I(72N6Z=NqyK??77hb;g?bmL;`Q`&7#T>sI2l)cQ1cA(^dx+Xk zKt^QV$)hJIaoQ1r1REf#LQp1%k}CF$^iQ}(<4I+*UPA01)A&oN%n-Xr zM?`FRp#5XCgxRC;A1e^m))-Bgd!X59k zN>LZeoR=3$;=*{oO-)V7syAjsA^rd|f=&H6QL>&~qGW?3OH(F+40wtL8m;baw@`|dvOKiuFBS4mDoC`H`)x#j}@ zDlv2l7k?R{W8tON=Z$(D@4|8&)ZKP6N1cV~Mw!DWUA)Kg`KHh1`Zicv$2>UKfcd&} eh(06R1KJ;gUz(X(s*N4?XB2$M#M}It`4_^oY|v z1Sum&7_hk*P-1My7|h6v9Y`5)d?i54miJ|MANFCNw)$x+W=7JJ{gSE_yOr$spY9n+ z!(eBt_GL%af1h*uoWD>1=ld_`Kgu*Ug(Upeu0OSX@+dq&B{!n5*rtXuNx>resj4;!7D16Ka z?UhmyBT{M_mt<+U#ZXF7rjN_Av~%lIlDSBgjOL-EGM>p2dbLomrzKNKU^YEc+&_hx zN!@Y9(R;Gn%*=q}|Iw!2exuLsqX#p88Y=5?S)YR#5`92QF?@!)S59e$57W?5^Y;f( z526&p6D1X9E5x+rRD{Kup9S{GsU{X=p?y*+%I;wi)`XU3_HEY8T2N|Xb66{$%`sYy zRyOyf!rIupeQIiMtv;VEK)sEvWDD6MjF`vnWsBJol;*SB*zFj*fZf4jxVN)A*;3pW zvTw1wa9_mkX3KD2%$DQRJDldt#z1ChL*BG`eqg}hHzLXJb#^3Iujxp1B-czm@lTS} z=flTVe^id(+JMV?M3$tYT$IvMQ2~`1l@&&1AM=5#Oa;}L2C6e1)X)5&fuhu}umH*6 zBzpJzSQt`p%PMPPQLn6#M7*+2QlWB|xCPlLvY$2%57K#30 zl>LnQ1lWQsjf$YGu*IN0wggmVw}EQxc2J$&Ax1T!>}N610J~F+in65`+sq`;7D4Bb zWVaK?R>;;Z&1K6_Z=)Hc=dtCW^ToIYG=p?ITLHR|#X%Q|_Qg!XYTVQ91pD&lE@LRq zla4-Eu(lg~x~bFA`UWz&LC5btNv8akVOr>0Ep(>Z6Vt!diDcqCRPE|YBpN@Vr@+0M zA2dwjp0|vK9h0|Ykt7ykj3}Y9I?f{#(xN z{)S_!vsrT!H+RyB#2Sdi&x~E!KErZ68Cx7!m!h|rGga5{$0OXni}0xzVvRg z5Ja_d^latSwer=`*$+Dl&Ghi(<;vUdPrmd*`ONPp4*YiJfc+m9T8P^pj!gXF0(e&T zoi4v|Hrc4Lvn!=yfs=yXCurw3jK%M(brUDvpx?i&^ID|!TjEO`b$i~j9d$6zZ6~;4 zQ}>e_pWd_?KzriHJr8Z%JlzDKZFua#$DeTg?vteB@7dVhLw&tMrxV?k8Q5i{`|`P5 z#$=W=mm3+Dw(N{uu&S+2)D>d7H*2SJnL#J&;7>()`SlJMX;$DFJDWG1NG`KGow02r zH)vZ<(;!S>I&0bn$JaS?YA@v3ZQBemo^Be*Sa#aZ<_xE$+KU;z`GVPJI8AO#XPTxt z?7T%{zyflxP;gEGYYm;l8f@V zJfhl4QQ0g1Kzi;!MzrDQZC}Y}`}$Q}+PHEoHKG^wlFrammQaH4=qKM1+^Tpjp`z-Q z!VGOAesGQy{o`_}iTO|u6#Y+03IYffe|vqhL^T=KHYr&L5+Wp^V1U|pwyKgH9h#J- zks!i|wRSVSm+wsp-YW>I7d7TzAfXf}Dxkqr!M&K3-BOyvLNte`z=vV%^TD01?mZzT zz_loqS}EiZHa^@vMZ(BpHqs5PU~j#5O@SmcHG1OuwehLrZ%kgi7+W#yi$4%6kUUq$ z%I}|=y!h(WOGhTJz17jt5nI7q(SAc-bwiF%Q9u%(>jZkUX2$BvW}RTc+-~e1$Zj2S zG@dcH8IEq{`*s+%) zsjz1<(%_Z~bHnCC(ANS6W168iFx27oB%hh!Mtf1P6VT&UtUc% zgx>JOXYw(yrdr4Gnw>}>978% zOkP0XnZh9(p(LR}tg+HvSc|sF^Y4~_dFaclC$Ml6SI(EuoT$7v?yhtB%Ydgsfl zFHc_lwDJ$5mDBG`Uihqh<|Xv397X${xXd2`i*vFNTHV+2$MI+8h%6x07V6rfU7g@ig@L@TQNvaJ>o3Nw9ໍ=3gk00<*xI6wyOv_WRJ{2d@x#6~RL@ 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 diff --git a/EMV/ALL_test.py b/EMV/all_sensors_device_test.py similarity index 100% rename from EMV/ALL_test.py rename to EMV/all_sensors_device_test.py diff --git a/EMV/code_statue.py b/EMV/code_statue_test.py similarity index 100% rename from EMV/code_statue.py rename to EMV/code_statue_test.py diff --git a/EMV/EMV_test_sensor.py b/EMV/only_sensor1_test.py similarity index 100% rename from EMV/EMV_test_sensor.py rename to EMV/only_sensor1_test.py diff --git a/EMV/test_EMV.py b/EMV/sensors_test.py similarity index 100% rename from EMV/test_EMV.py rename to EMV/sensors_test.py diff --git a/EMV/test.py b/EMV/test.py deleted file mode 100644 index 139597f..0000000 --- a/EMV/test.py +++ /dev/null @@ -1,2 +0,0 @@ - -