# feeding/controller.py import time from core.state import FeedStatus from feeding.process import FeedingProcess from busisness.blls import ArtifactBll from config.settings import app_set_config class FeedingController: def __init__(self, relay_controller, inverter_controller, transmitter_controller, vision_detector, camera_controller, rfid_controller,state): self.relay_controller = relay_controller self.inverter_controller = inverter_controller self.transmitter_controller = transmitter_controller self.vision_detector = vision_detector self.camera_controller = camera_controller self.rfid_controller = rfid_controller self.state = state self.artifact_bll = ArtifactBll() # 初始化下料流程 self.process = FeedingProcess( relay_controller, inverter_controller, transmitter_controller, vision_detector, camera_controller, state ) def start_feeding(self): #获取当前的管片任务 #API读取生产任务 --》RFID读取模具配对检测--数据库入库》生产-》同步到数据库 #API读取生产任务--》未读到--》RFID读取模具-数据库入库》生产 --》同步到数据库 #从数据库获取当前的管片任务 """启动下料流程""" self.process.start_feeding() def check_upper_material_request(self): """检查是否需要要料""" current_weight = self.transmitter_controller.read_data(1) if current_weight is None: self.state.upper_weight_error_count += 1 print(f"上料斗重量读取失败,错误计数: {self.state.upper_weight_error_count}") if self.state.upper_weight_error_count >= app_set_config.max_error_count: print("警告:上料斗传感器连续读取失败,请检查连接") return False #需要搅拌楼通知下完料后移到上料斗上方 self.state.upper_weight_error_count = 0 # 判断是否需要要料:当前重量 < 目标重量 + 缓冲重量 if self.state._feed_status != FeedStatus.FUpperToLower: if current_weight < (app_set_config.min_required_weight): print("上料斗重量不足,通知搅拌楼要料") self.request_material_from_mixing_building() # 请求搅拌楼下料 return True else: if self.state._upper_door_position != 'over_lower': self.state._upper_door_position = 'over_lower' return False def request_material_from_mixing_building(self): """ 请求搅拌楼下料 """ print("发送要料请求至搅拌楼...") # self.process.return_upper_door_to_default() # 这里需要与同事对接具体的通信方式 # 可能是Modbus写寄存器、TCP通信、HTTP请求等 pass def check_arch_blocking(self): """检查是否需要破拱""" current_time = time.time() # 检查下料斗破拱(只有在下料过程中才检查) if self.state.lower_feeding_stage in [1, 2, 3]: # 在所有下料阶段检查 lower_weight = self.transmitter_controller.read_data(2) if lower_weight is not None: # 检查重量变化是否过慢(小于0.1kg变化且时间超过10秒) if (abs(lower_weight - self.state.last_lower_weight) < 10) and \ (current_time - self.state.last_weight_time) > 1: print("下料斗可能堵塞,启动破拱") self.state._lower_is_arch_=True self.relay_controller.control(self.relay_controller.BREAK_ARCH_LOWER, 'open') time.sleep(2) self.relay_controller.control(self.relay_controller.BREAK_ARCH_LOWER, 'close') self.state._lower_is_arch_=False self.state.last_lower_weight = lower_weight # 检查上料斗破拱(在上料斗向下料斗下料时检查) if self.state._feed_status == FeedStatus.FUpperToLower: # 在任何阶段都可能需要上料斗破拱 print('上料斗振动线程启用中...') upper_weight = self.transmitter_controller.read_data(1) if upper_weight is not None: # 检查重量变化是否过慢(小于0.1kg变化且时间超过10秒),觉得有点小。改成 if (abs(upper_weight - self.state.last_upper_weight) < 25) and \ (current_time - self.state.last_weight_time) > 1: print("上料斗可能堵塞,启动破拱") self.state._upper_is_arch_=True self.relay_controller.control(self.relay_controller.BREAK_ARCH_UPPER, 'open') time.sleep(5) self.relay_controller.control(self.relay_controller.BREAK_ARCH_UPPER, 'close') self.state._upper_is_arch_=False self.state.last_upper_weight = upper_weight # 更新最后读取时间 if (self.transmitter_controller.read_data(1) is not None or self.transmitter_controller.read_data(2) is not None): self.state.last_weight_time = current_time def visual_control(self, current_frame): """ 视觉控制主逻辑 """ # 检测是否溢料 # print('视觉控制线程启用中...') # self.state.overflow_detected = self.vision_detector.detect_overflow(current_frame) overflow=self.state.overflow_detected in ["大堆料", "小堆料"] current_angle =self.vision_detector.detect_angle(image=current_frame) if current_angle is None: print("无法获取当前角度,跳过本次调整") return self.state.last_angle = current_angle self.state._lower_angle=current_angle print(f"当前角度: {current_angle:.2f}°") # return if self.state.overflow_detected!="浇筑满": if current_angle is None: print("无法获取当前角度,跳过本次调整") return # print(f"当前角度: {current_angle:.2f}°, 溢料状态: {overflow}, 控制模式: {self.state.angle_control_mode}") # 状态机控制逻辑 if self.state.angle_control_mode == "normal": # 正常模式大于app_set_config.angle_threshold=60度 if overflow: # if current_angle > app_set_config.angle_threshold: # # 检测到堆料且角度过大,进入角度减小模式 # print("检测到堆料且角度过大,关闭出砼门开始减小角度") # self.relay_controller.control(self.relay_controller.DOOR_LOWER_OPEN, 'close') # self.relay_controller.control(self.relay_controller.DOOR_LOWER_CLOSE, 'open') self.state.angle_control_mode = "reducing" else: # 保持正常开门 30 # self.relay_controller.control(self.relay_controller.DOOR_LOWER_OPEN, 'open') print(f'当前重量:{self.state._mould_finish_weight:.2f}kg, 目标重量:{self.state._mould_need_weight:.2f}kg') if self.state._mould_need_weight>0: if self.state._mould_finish_weight/self.state._mould_need_weight>=0.8: print(f"完成重量占比{self.state._mould_finish_weight/self.state._mould_need_weight:.2f},半开出砼门") #半开出砼门 if current_angle >app_set_config.target_angle: # 角度已降至目标范围,关闭出砼门 self.relay_controller.control(self.relay_controller.DOOR_LOWER_OPEN, 'close') self.relay_controller.control(self.relay_controller.DOOR_LOWER_CLOSE, 'open') time.sleep(0.3) self.relay_controller.control(self.relay_controller.DOOR_LOWER_CLOSE, 'close') else: self.relay_controller.control(self.relay_controller.DOOR_LOWER_CLOSE, 'close') self.relay_controller.control(self.relay_controller.DOOR_LOWER_OPEN, 'open') time.sleep(0.32) self.relay_controller.control(self.relay_controller.DOOR_LOWER_OPEN, 'close') else: #全开砼门 if current_angle > app_set_config.angle_threshold: self.relay_controller.control(self.relay_controller.DOOR_LOWER_OPEN, 'close') elif self.state.angle_control_mode == "reducing": # 角度减小模式 if overflow: if current_angle <= app_set_config.target_angle: # 角度已达到目标范围 # 仍有堆料,进入维持模式 print(f"角度已降至{current_angle:.2f}°,仍有堆料,进入维持模式") if current_angle<=app_set_config.min_angle: self.relay_controller.control(self.relay_controller.DOOR_LOWER_CLOSE, 'close') self.relay_controller.control(self.relay_controller.DOOR_LOWER_OPEN, 'open') time.sleep(0.1) self.state.angle_control_mode = "maintaining" # self.relay_controller.control(self.relay_controller.DOOR_LOWER_OPEN, 'close') # self.relay_controller.control(self.relay_controller.DOOR_LOWER_CLOSE, 'open') else: self.relay_controller.control(self.relay_controller.DOOR_LOWER_OPEN, 'close') self.relay_controller.control(self.relay_controller.DOOR_LOWER_CLOSE, 'open') # time.sleep(0.05) # 先打开门 else: # 无堆料,恢复正常模式 print(f"角度已降至{current_angle:.2f}°,无堆料,恢复正常模式") # self.relay_controller.control(self.relay_controller.DOOR_LOWER_OPEN, 'open') # self.relay_controller.control(self.relay_controller.DOOR_LOWER_CLOSE, 'close') self.state.angle_control_mode = "normal" elif self.state.angle_control_mode == "maintaining": # 维持模式 - 使用脉冲控制 if not overflow: # 堆料已消除,恢复正常模式 print("堆料已消除,恢复正常模式") # self.relay_controller.control(self.relay_controller.DOOR_LOWER_OPEN, 'open') # self.relay_controller.control(self.relay_controller.DOOR_LOWER_CLOSE, 'close') self.state.angle_control_mode = "normal" else: # 继续维持角度控制 self.pulse_control_door_for_maintaining() elif self.state.angle_control_mode == "recovery": # 恢复模式 - 逐步打开门 if overflow: # 又出现堆料,回到角度减小模式 print("恢复过程中又检测到堆料,回到角度减小模式") self.state.angle_control_mode = "maintaining" else: # 堆料已消除,恢复正常模式 print("堆料已消除,恢复正常模式") self.relay_controller.control(self.relay_controller.DOOR_LOWER_OPEN, 'open') self.relay_controller.control(self.relay_controller.DOOR_LOWER_CLOSE, 'close') self.state.angle_control_mode = "normal" else: # self.relay_controller.control(self.relay_controller.DOOR_LOWER_OPEN, 'close') self.relay_controller.control_lower_close() def pulse_control_door_for_maintaining(self): """ 用于维持模式的脉冲控制 保持角度在目标范围内 """ print("进入维持模式") # 关门时间 self.relay_controller.control(self.relay_controller.DOOR_LOWER_OPEN, 'close') self.relay_controller.control(self.relay_controller.DOOR_LOWER_CLOSE, 'open') time.sleep(0.2) # 开门时间 self.relay_controller.control(self.relay_controller.DOOR_LOWER_CLOSE, 'close') self.relay_controller.control(self.relay_controller.DOOR_LOWER_OPEN, 'open') time.sleep(0.25) self.relay_controller.control(self.relay_controller.DOOR_LOWER_OPEN, 'close')