Files
Feeding_control_system/feeding/controller.py
2025-09-26 13:32:34 +08:00

176 lines
8.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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)