从 MT2-AM8 模拟量模块迁移到 Easy521 PLC(Modbus TCP)

- 读取 D700(阀后流量)、D710(阀后压力)、D720(阀前压力),
  读用功能码 03,0~32000 线性映射到各自量程(300 SLM / 400 kPa / 300 kPa)
- 输出 D730(电机位置,0~10V),写用功能码 06,行程仍为 0~1000、死区 800
- 复用 MT2 骨架,保留 get_flow/get_pressure/set_motor_position 接口,
  channel 参数改为直接 Modbus 地址
- config.py 新增 PLC 设置,保留 MT2AM8 设置为死代码(MT2AM8Client 类保留)
- 同步更新 README.md 中的硬件接线、配置默认值与模块职责描述
This commit is contained in:
2026-09-01 17:03:26 +08:00
parent abab25326a
commit 5888b4ccce
10 changed files with 507 additions and 374 deletions
+34 -21
View File
@@ -1,11 +1,11 @@
"""气体流量闭环控制的集中配置。
首次连接真实设备前,请重点核对:MT2-AM8 地址、AI/AO 通道、压力上限、
阀门打开端行程和关闭端行程。PID 参数是安全起步值,不是最终整定结果。
首次连接真实设备前,请重点核对:PLC 寄存器地址、量程、阀门打开端行程和
关闭端行程。PID 参数是安全起步值,不是最终整定结果。
"""
# ---------------------------------------------------------------------------
# MT2-AM8 通讯与量程
# MT2-AM8 通讯与量程(旧方案;代码保留但当前不再使用)
# ---------------------------------------------------------------------------
MT2AM8_HOST = "192.168.1.12"
@@ -13,13 +13,27 @@ MT2AM8_PORT = 502
MT2AM8_SLAVE_ID = 1
# MT2AM8Client 用这些量程把模拟量转换成物理量。
PRESSURE_RANGE_KPA = 1600.0
PRESSURE_RANGE_KPA = 400.0
FLOW_METER_RANGE_SLM = 300.0
# AI/AO 通道均从 0 开始。AI0 和 AO0 属于不同的寄存器区,可以同时使用。
FLOW_INPUT_CHANNEL = 1
PRESSURE_INPUT_CHANNEL = 0 # 没有压力传感器时改为 None
MOTOR_OUTPUT_CHANNEL = 1
# ---------------------------------------------------------------------------
# PLCEasy521Modbus TCP 通讯与寄存器地址
# ---------------------------------------------------------------------------
PLC_HOST = "192.168.1.88"
PLC_PORT = 502
PLC_SLAVE_ID = 1
# D 寄存器为直接 Modbus 地址:读用功能码 03(保持寄存器),写用功能码 06。
# 模拟量 0~32000 线性对应各量程满量程(映射常量在 PcControl.py)。
# 三个测量量 + 一个输出,地址与量程集中放在一起(名称区分阀前 / 阀后)。
FLOW_AFTER_ADDR = 700 # 阀后流量 D700,量程 0~300 SLM
FLOW_AFTER_RANGE_SLM = 300.0
PRESSURE_AFTER_ADDR = 710 # 阀后压力 D710,量程 0~400 kPa
PRESSURE_AFTER_RANGE_KPA = 400.0
PRESSURE_BEFORE_ADDR = 720 # 阀前压力 D720,量程 0~300 kPa
PRESSURE_BEFORE_RANGE_KPA = 300.0
MOTOR_OUTPUT_ADDR = 730 # 电机输出 D7300~10V,行程 0~1000 映射 0~32000
# ---------------------------------------------------------------------------
# 控制目标和控制周期
@@ -49,8 +63,8 @@ PID_NEAR_KD = 0.0
OPENING_MIN_PCT = 0.0
OPENING_MAX_PCT = 100.0
MAX_OPENING_RATE_FAR_PCT_S = 20.0
MAX_OPENING_RATE_NEAR_PCT_S = 2.0
MAX_OPENING_RATE_FAR_PCT_S = 200.0
MAX_OPENING_RATE_NEAR_PCT_S = 20.0
# FAR -> NEAR:绝对误差连续满足 near 阈值指定周期数后切换。
# NEAR -> FAR:绝对误差连续达到 far 阈值指定周期数后切换。
@@ -87,8 +101,7 @@ INITIAL_OPENING_PCT = 100.0
# 前馈 + 增益调度(默认关闭,便于与纯 PID 做 A/B 对比;接线确认后再开启)
# ---------------------------------------------------------------------------
# 阀前压力 P1(前馈缩放 / 判阻塞 / 增益调度用),按实际接线确认
PRESSURE_BEFORE_CHANNEL = 2
# 阀前压力 P1(前馈缩放 / 判阻塞 / 增益调度用),地址见上 PLC 段 PRESSURE_BEFORE_ADDR
# 阀特性表 JSONidentify_valve.py 产出)。空字符串表示关闭前馈。
VALVE_MODEL_PATH = ""
@@ -138,18 +151,18 @@ def validate_config():
raise ValueError("MAX_CONTROL_DT_S 不得小于 CONTROL_PERIOD_S")
if TARGET_FLOW_MIN_SLM > TARGET_FLOW_MAX_SLM:
raise ValueError("目标流量上下限配置错误")
if TARGET_FLOW_MAX_SLM > FLOW_METER_RANGE_SLM:
if TARGET_FLOW_MAX_SLM > FLOW_AFTER_RANGE_SLM:
raise ValueError("目标流量上限不得超过流量计量程")
if FLOW_VALID_MIN_SLM > FLOW_VALID_MAX_SLM:
raise ValueError("流量有效范围上下限配置错误")
if FLOW_VALID_MAX_SLM > FLOW_METER_RANGE_SLM:
if FLOW_VALID_MAX_SLM > FLOW_AFTER_RANGE_SLM:
raise ValueError("流量有效范围上限不得超过流量计量程")
if not 0 <= OPENING_MIN_PCT < OPENING_MAX_PCT <= 100:
raise ValueError("阀门开度范围必须位于 0~100%,且下限小于上限")
if MOTOR_OPEN_POSITION >= MOTOR_CLOSED_POSITION:
raise ValueError("本系统行程越大开度越小,因此打开端行程必须小于关闭端行程")
if MOTOR_OPEN_POSITION < 0 or MOTOR_CLOSED_POSITION > 1000:
raise ValueError("电机行程必须位于 MT2AM8Client 当前采用的 0~1000 范围")
raise ValueError("电机行程必须位于当前采用的 0~1000 范围")
pid_gains = (
PID_FAR_KP,
PID_FAR_KI,
@@ -181,13 +194,13 @@ def validate_config():
raise ValueError("PID_MODE_SWITCH_CONFIRM_CYCLES 必须至少为 1")
if MAX_CONSECUTIVE_FLOW_FAILURES < 1:
raise ValueError("MAX_CONSECUTIVE_FLOW_FAILURES 必须至少为 1")
if PRESSURE_INPUT_CHANNEL is not None and MAX_PRESSURE_KPA is None:
if PRESSURE_AFTER_ADDR is not None and MAX_PRESSURE_KPA is None:
raise ValueError("启用压力通道时必须配置 MAX_PRESSURE_KPA")
if PRESSURE_BEFORE_CHANNEL is not None:
if not isinstance(PRESSURE_BEFORE_CHANNEL, int):
raise ValueError("PRESSURE_BEFORE_CHANNEL 必须为整数通道号或 None")
if PRESSURE_BEFORE_CHANNEL < 0:
raise ValueError("PRESSURE_BEFORE_CHANNEL 不得为负数")
if PRESSURE_BEFORE_ADDR is not None:
if not isinstance(PRESSURE_BEFORE_ADDR, int):
raise ValueError("PRESSURE_BEFORE_ADDR 必须为整数地址或 None")
if PRESSURE_BEFORE_ADDR < 0:
raise ValueError("PRESSURE_BEFORE_ADDR 不得为负数")
if MAX_PRESSURE_KPA is None:
raise ValueError("启用阀前压力通道时必须配置 MAX_PRESSURE_KPA")
if GAIN_SCHEDULE_REF_ABS_KPA <= 0: