完善流量控制前馈、稳态判定与阀门标定流程
- 前馈冻结改用可配置的 3 秒流量绝对误差滑窗,修复采样抖动造成的重复解冻,并保留下游扰动后的自动更新 - 支持非单调阀特性反解、最小可测面积以下直接全关,以及闭阀端精细扫点与辨识开关 - 调整双压力判稳、最长等待时间、在线入口全开收尾和闭环四联图 - 更新配置、README、阀模型及离线测试,归档本轮实验数据与诊断产物
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
关闭端行程。PID 参数是安全起步值,不是最终整定结果。
|
||||
"""
|
||||
|
||||
import math
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# MT2-AM8 通讯与量程(旧方案;代码保留但当前不再使用)
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -57,20 +59,23 @@ STATUS_PRINT_PERIOD_S = 1.0
|
||||
PID_FAR_KP = 0.5
|
||||
PID_FAR_KI = 0.5
|
||||
PID_FAR_KD = 0.0
|
||||
PID_NEAR_KP = 0.05
|
||||
PID_NEAR_KI = 0.01
|
||||
PID_NEAR_KP = 0.1
|
||||
PID_NEAR_KI = 0.1
|
||||
PID_NEAR_KD = 0.0
|
||||
|
||||
OPENING_MIN_PCT = 0.0
|
||||
OPENING_MAX_PCT = 100.0
|
||||
MAX_OPENING_RATE_FAR_PCT_S = 200.0
|
||||
MAX_OPENING_RATE_NEAR_PCT_S = 20.0
|
||||
MAX_OPENING_RATE_NEAR_PCT_S = 2.0
|
||||
|
||||
# FAR -> NEAR:绝对误差连续满足 near 阈值指定周期数后切换。
|
||||
# NEAR -> FAR:绝对误差连续达到 far 阈值指定周期数后切换。
|
||||
PID_NEAR_ERROR_MIN_SLM = 3.0
|
||||
# 比例阈值会被限制在各自的 MIN~MAX 范围内。
|
||||
PID_NEAR_ERROR_MIN_SLM = 1.0
|
||||
PID_NEAR_ERROR_MAX_SLM = 2.0
|
||||
PID_NEAR_ERROR_TARGET_RATIO = 0.05
|
||||
PID_FAR_ERROR_MIN_SLM = 12.0
|
||||
PID_FAR_ERROR_MIN_SLM = 4.0
|
||||
PID_FAR_ERROR_MAX_SLM = 8.0
|
||||
PID_FAR_ERROR_TARGET_RATIO = 0.20
|
||||
PID_MODE_SWITCH_CONFIRM_CYCLES = 10
|
||||
|
||||
@@ -78,12 +83,25 @@ PID_MODE_SWITCH_CONFIRM_CYCLES = 10
|
||||
# 稳态判定(用于控制性能报告)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
STEADY_STATE_WINDOW_S = 10.0 # 滑动时间窗口长度
|
||||
STEADY_STATE_WINDOW_S = 5.0 # 滑动时间窗口长度,单位:秒
|
||||
STEADY_STATE_MAX_WAIT_S = 30.0 # 单个开环扫点等待稳态的最长时间
|
||||
STEADY_STATE_BAND_PCT = 1.0 # 滑窗均值相对目标的允许误差带(±1%)
|
||||
STEADY_STATE_STD_PCT = 1.0 # 滑窗标准差阈值(相对目标百分比)
|
||||
STEADY_STATE_PRESSURE_BAND_KPA = 1.0 # 压力样本相对滑窗均值的允许误差带(±kPa)
|
||||
# 仅供 open_loop.py 使用;开环没有目标流量,仍用相对标准差判断流量稳定。
|
||||
STEADY_STATE_STD_PCT = 1.0
|
||||
|
||||
AUTO_STOP_ON_STEADY = False # 达到稳态后是否自动停止控制(False 则持续控制)
|
||||
|
||||
# 开环随机开度扫描结束后,追加闭阀端精细行程扫描。
|
||||
OPEN_LOOP_FINE_STROKE_START = 970.0
|
||||
OPEN_LOOP_FINE_STROKE_STEP = 3.0
|
||||
|
||||
# identify_valve.py 是否检查单调性并只保留最长单调连续段。
|
||||
#True:保持原逻辑,检测非单调并只保留最长单调连续段。
|
||||
#False:不丢弃非单调点,保留所有按行程平均后的数据,关闭检查后生成的 JSON 会记录"enforce_monotonic": false
|
||||
#非单调表可能对应多个反解行程,此时选择数值更大的行程,即更接近关闭端的解。
|
||||
IDENTIFY_VALVE_MONOTONIC_CHECK_ENABLED = False
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 阀门执行机构
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -98,18 +116,22 @@ MOTOR_OPEN_POSITION = 800.0
|
||||
INITIAL_OPENING_PCT = 100.0
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 前馈 + 增益调度(默认关闭,便于与纯 PID 做 A/B 对比;接线确认后再开启)
|
||||
# 前馈 + 增益调度(前馈默认开启,增益调度默认关闭)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# 阀前压力 P1(前馈缩放 / 判阻塞 / 增益调度用),地址见上 PLC 段 PRESSURE_BEFORE_ADDR。
|
||||
|
||||
# 阀特性表 JSON(identify_valve.py 产出)。空字符串表示关闭前馈。
|
||||
VALVE_MODEL_PATH = ""
|
||||
VALVE_MODEL_PATH = "valve_model_004.json"
|
||||
|
||||
# 前馈反解打底 + PI 修残差(市面 MFC 结构)。
|
||||
FEEDFORWARD_ENABLED = False
|
||||
FEEDFORWARD_ENABLED = True
|
||||
# 前馈开启时,PI 输出是“围绕前馈的修正量”,限幅为对称小范围(±%)。
|
||||
FEEDFORWARD_CORRECTION_BAND_PCT = 20.0
|
||||
FEEDFORWARD_CORRECTION_BAND_PCT = 50.0
|
||||
# |目标流量-实测流量| 不超过此值时冻结前馈,只更新 PID correction。
|
||||
FEEDFORWARD_UPDATE_ERROR_THRESHOLD_SLM = 2.0
|
||||
# 前馈冻结/更新判断所用的“流量绝对误差均值”滑动窗口长度。
|
||||
FEEDFORWARD_UPDATE_WINDOW_S = 3.0
|
||||
|
||||
# PI 增益按阀前压力 P1 缩放(摊平 K_x ∝ P1 的非线性)。
|
||||
GAIN_SCHEDULE_ENABLED = False
|
||||
@@ -145,8 +167,14 @@ def validate_config():
|
||||
raise ValueError("CONTROL_PERIOD_S 必须大于 0")
|
||||
if STEADY_STATE_WINDOW_S <= CONTROL_PERIOD_S:
|
||||
raise ValueError("STEADY_STATE_WINDOW_S 必须大于 CONTROL_PERIOD_S")
|
||||
if STEADY_STATE_BAND_PCT < 0 or STEADY_STATE_STD_PCT < 0:
|
||||
raise ValueError("稳态误差带和标准差阈值不得为负数")
|
||||
if STEADY_STATE_MAX_WAIT_S <= 0:
|
||||
raise ValueError("STEADY_STATE_MAX_WAIT_S 必须大于 0")
|
||||
if (
|
||||
STEADY_STATE_BAND_PCT < 0
|
||||
or STEADY_STATE_PRESSURE_BAND_KPA < 0
|
||||
or STEADY_STATE_STD_PCT < 0
|
||||
):
|
||||
raise ValueError("稳态误差带、压力带和标准差阈值不得为负数")
|
||||
if MAX_CONTROL_DT_S < CONTROL_PERIOD_S:
|
||||
raise ValueError("MAX_CONTROL_DT_S 不得小于 CONTROL_PERIOD_S")
|
||||
if TARGET_FLOW_MIN_SLM > TARGET_FLOW_MAX_SLM:
|
||||
@@ -178,18 +206,28 @@ def validate_config():
|
||||
or MAX_OPENING_RATE_NEAR_PCT_S <= 0
|
||||
):
|
||||
raise ValueError("FAR/NEAR 最大开度变化速度必须大于 0")
|
||||
if PID_NEAR_ERROR_MIN_SLM < 0 or PID_FAR_ERROR_MIN_SLM < 0:
|
||||
raise ValueError("PID 模式切换误差下限不得为负数")
|
||||
pid_error_limits = (
|
||||
PID_NEAR_ERROR_MIN_SLM,
|
||||
PID_NEAR_ERROR_MAX_SLM,
|
||||
PID_FAR_ERROR_MIN_SLM,
|
||||
PID_FAR_ERROR_MAX_SLM,
|
||||
)
|
||||
if any(value < 0 for value in pid_error_limits):
|
||||
raise ValueError("PID 模式切换误差上下限不得为负数")
|
||||
if PID_NEAR_ERROR_MIN_SLM > PID_NEAR_ERROR_MAX_SLM:
|
||||
raise ValueError("PID NEAR 误差下限不得大于上限")
|
||||
if PID_FAR_ERROR_MIN_SLM > PID_FAR_ERROR_MAX_SLM:
|
||||
raise ValueError("PID FAR 误差下限不得大于上限")
|
||||
if (
|
||||
PID_NEAR_ERROR_TARGET_RATIO < 0
|
||||
or PID_FAR_ERROR_TARGET_RATIO < 0
|
||||
):
|
||||
raise ValueError("PID 模式切换目标比例不得为负数")
|
||||
if (
|
||||
PID_NEAR_ERROR_MIN_SLM >= PID_FAR_ERROR_MIN_SLM
|
||||
PID_NEAR_ERROR_MAX_SLM >= PID_FAR_ERROR_MIN_SLM
|
||||
or PID_NEAR_ERROR_TARGET_RATIO >= PID_FAR_ERROR_TARGET_RATIO
|
||||
):
|
||||
raise ValueError("PID NEAR 阈值必须小于 FAR 阈值")
|
||||
raise ValueError("PID NEAR 阈值范围必须整体小于 FAR 阈值范围")
|
||||
if PID_MODE_SWITCH_CONFIRM_CYCLES < 1:
|
||||
raise ValueError("PID_MODE_SWITCH_CONFIRM_CYCLES 必须至少为 1")
|
||||
if MAX_CONSECUTIVE_FLOW_FAILURES < 1:
|
||||
@@ -209,5 +247,31 @@ def validate_config():
|
||||
raise ValueError("GAIN_SCHEDULE_FLOOR_ABS_KPA 必须大于 0")
|
||||
if not 0 < FEEDFORWARD_CORRECTION_BAND_PCT <= 100:
|
||||
raise ValueError("FEEDFORWARD_CORRECTION_BAND_PCT 必须位于 0~100")
|
||||
if (
|
||||
not isinstance(FEEDFORWARD_UPDATE_ERROR_THRESHOLD_SLM, (int, float))
|
||||
or not math.isfinite(FEEDFORWARD_UPDATE_ERROR_THRESHOLD_SLM)
|
||||
or FEEDFORWARD_UPDATE_ERROR_THRESHOLD_SLM < 0
|
||||
):
|
||||
raise ValueError(
|
||||
"FEEDFORWARD_UPDATE_ERROR_THRESHOLD_SLM 必须是非负有限数值"
|
||||
)
|
||||
if (
|
||||
not isinstance(FEEDFORWARD_UPDATE_WINDOW_S, (int, float))
|
||||
or not math.isfinite(FEEDFORWARD_UPDATE_WINDOW_S)
|
||||
or FEEDFORWARD_UPDATE_WINDOW_S <= 0
|
||||
):
|
||||
raise ValueError("FEEDFORWARD_UPDATE_WINDOW_S 必须是正的有限数值")
|
||||
if not MOTOR_OPEN_POSITION <= OPEN_LOOP_FINE_STROKE_START < MOTOR_CLOSED_POSITION:
|
||||
raise ValueError(
|
||||
"OPEN_LOOP_FINE_STROKE_START 必须位于电机开端和闭端行程之间"
|
||||
)
|
||||
if (
|
||||
not isinstance(OPEN_LOOP_FINE_STROKE_STEP, (int, float))
|
||||
or not math.isfinite(OPEN_LOOP_FINE_STROKE_STEP)
|
||||
or OPEN_LOOP_FINE_STROKE_STEP <= 0
|
||||
):
|
||||
raise ValueError("OPEN_LOOP_FINE_STROKE_STEP 必须是正的有限数值")
|
||||
if not isinstance(IDENTIFY_VALVE_MONOTONIC_CHECK_ENABLED, bool):
|
||||
raise ValueError("IDENTIFY_VALVE_MONOTONIC_CHECK_ENABLED 必须是布尔值")
|
||||
if GAIN_SCHEDULE_SCALE_CHANGE_THRESHOLD <= 0:
|
||||
raise ValueError("GAIN_SCHEDULE_SCALE_CHANGE_THRESHOLD 必须大于 0")
|
||||
|
||||
Reference in New Issue
Block a user