176 lines
8.0 KiB
Python
176 lines
8.0 KiB
Python
|
|
# feeding/controller.py
|
|||
|
|
import time
|
|||
|
|
from feeding.process import FeedingProcess
|
|||
|
|
|
|||
|
|
|
|||
|
|
class FeedingController:
|
|||
|
|
def __init__(self, relay_controller, inverter_controller,
|
|||
|
|
transmitter_controller, vision_detector,
|
|||
|
|
camera_controller, state, settings):
|
|||
|
|
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.state = state
|
|||
|
|
self.settings = settings
|
|||
|
|
|
|||
|
|
# 初始化下料流程
|
|||
|
|
self.process = FeedingProcess(
|
|||
|
|
relay_controller, inverter_controller,
|
|||
|
|
transmitter_controller, vision_detector,
|
|||
|
|
camera_controller, state, settings
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
def start_feeding(self):
|
|||
|
|
"""启动下料流程"""
|
|||
|
|
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 >= self.settings.max_error_count:
|
|||
|
|
print("警告:上料斗传感器连续读取失败,请检查连接")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
self.state.upper_weight_error_count = 0
|
|||
|
|
# 判断是否需要要料:当前重量 < 目标重量 + 缓冲重量
|
|||
|
|
if current_weight < (self.settings.single_batch_weight + self.settings.min_required_weight):
|
|||
|
|
print("上料斗重量不足,通知搅拌楼要料")
|
|||
|
|
self.request_material_from_mixing_building() # 请求搅拌楼下料
|
|||
|
|
return True
|
|||
|
|
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) < 0.1) and \
|
|||
|
|
(current_time - self.state.last_weight_time) > 10:
|
|||
|
|
print("下料斗可能堵塞,启动破拱")
|
|||
|
|
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.last_lower_weight = lower_weight
|
|||
|
|
|
|||
|
|
# 检查上料斗破拱(在上料斗向下料斗下料时检查)
|
|||
|
|
if (self.state.upper_door_position == 'over_lower' and
|
|||
|
|
self.state.lower_feeding_stage in [0, 1, 2, 3, 4]): # 在任何阶段都可能需要上料斗破拱
|
|||
|
|
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) < 0.1) and \
|
|||
|
|
(current_time - self.state.last_weight_time) > 10:
|
|||
|
|
print("上料斗可能堵塞,启动破拱")
|
|||
|
|
self.relay_controller.control(self.relay_controller.BREAK_ARCH_UPPER, 'open')
|
|||
|
|
time.sleep(2)
|
|||
|
|
self.relay_controller.control(self.relay_controller.BREAK_ARCH_UPPER, 'close')
|
|||
|
|
|
|||
|
|
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):
|
|||
|
|
"""
|
|||
|
|
视觉控制主逻辑
|
|||
|
|
"""
|
|||
|
|
# 检测是否溢料
|
|||
|
|
overflow = self.vision_detector.detect_overflow(current_frame)
|
|||
|
|
|
|||
|
|
# 获取当前角度
|
|||
|
|
current_angle = self.vision_detector.detect_angle(image=current_frame)
|
|||
|
|
|
|||
|
|
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":
|
|||
|
|
# 正常模式
|
|||
|
|
if overflow and current_angle > self.settings.angle_threshold:
|
|||
|
|
# 检测到堆料且角度过大,进入角度减小模式
|
|||
|
|
print("检测到堆料且角度过大,关闭出砼门开始减小角度")
|
|||
|
|
self.relay_controller.control(self.relay_controller.DOOR_LOWER_2, 'close')
|
|||
|
|
self.state.angle_control_mode = "reducing"
|
|||
|
|
else:
|
|||
|
|
# 保持正常开门
|
|||
|
|
self.relay_controller.control(self.relay_controller.DOOR_LOWER_2, 'open')
|
|||
|
|
|
|||
|
|
elif self.state.angle_control_mode == "reducing":
|
|||
|
|
# 角度减小模式
|
|||
|
|
if current_angle <= self.settings.target_angle + self.settings.angle_tolerance:
|
|||
|
|
# 角度已达到目标范围
|
|||
|
|
if overflow:
|
|||
|
|
# 仍有堆料,进入维持模式
|
|||
|
|
print(f"角度已降至{current_angle:.2f}°,仍有堆料,进入维持模式")
|
|||
|
|
self.state.angle_control_mode = "maintaining"
|
|||
|
|
self.relay_controller.control(self.relay_controller.DOOR_LOWER_2, 'open') # 先打开门
|
|||
|
|
else:
|
|||
|
|
# 无堆料,恢复正常模式
|
|||
|
|
print(f"角度已降至{current_angle:.2f}°,无堆料,恢复正常模式")
|
|||
|
|
self.relay_controller.control(self.relay_controller.DOOR_LOWER_2, 'open')
|
|||
|
|
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_2, 'open')
|
|||
|
|
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_2, 'open')
|
|||
|
|
self.state.angle_control_mode = "normal"
|
|||
|
|
|
|||
|
|
self.state.last_angle = current_angle
|
|||
|
|
|
|||
|
|
def pulse_control_door_for_maintaining(self):
|
|||
|
|
"""
|
|||
|
|
用于维持模式的脉冲控制
|
|||
|
|
保持角度在目标范围内
|
|||
|
|
"""
|
|||
|
|
print("执行维持脉冲控制")
|
|||
|
|
# 关门1秒
|
|||
|
|
self.relay_controller.control(self.relay_controller.DOOR_LOWER_2, 'close')
|
|||
|
|
time.sleep(1.0)
|
|||
|
|
# 开门1秒
|
|||
|
|
self.relay_controller.control(self.relay_controller.DOOR_LOWER_2, 'open')
|
|||
|
|
time.sleep(1.0)
|