Files
Feeding_control_system/feeding/controller.py
2025-11-21 14:55:52 +08:00

219 lines
11 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 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) < 0.1) and \
# (current_time - self.state.last_weight_time) > 10:
# 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) < 100) and \
(current_time - self.state.last_weight_time) > 5:
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):
"""
视觉控制主逻辑
"""
# 检测是否溢料
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}°, 溢料状态: {overflow}, 溢料返回: {self.state.overflow_detected}")
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 and 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')
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')
else:
self.relay_controller.control(self.relay_controller.DOOR_LOWER_OPEN, 'open')
self.relay_controller.control(self.relay_controller.DOOR_LOWER_CLOSE, 'close')
elif self.state.angle_control_mode == "reducing":
# 角度减小模式
if current_angle <= app_set_config.target_angle + app_set_config.angle_tolerance:
# 角度已达到目标范围
if overflow:
# 仍有堆料,进入维持模式
print(f"角度已降至{current_angle:.2f}°,仍有堆料,进入维持模式")
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:
# 无堆料,恢复正常模式
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("执行维持脉冲控制")
# 关门1秒
self.relay_controller.control(self.relay_controller.DOOR_LOWER_OPEN, 'close')
self.relay_controller.control(self.relay_controller.DOOR_LOWER_CLOSE, 'open')
time.sleep(1.0)
# 开门1秒
self.relay_controller.control(self.relay_controller.DOOR_LOWER_OPEN, 'open')
self.relay_controller.control(self.relay_controller.DOOR_LOWER_CLOSE, 'close')
time.sleep(1.0)