完善流量控制前馈、稳态判定与阀门标定流程
- 前馈冻结改用可配置的 3 秒流量绝对误差滑窗,修复采样抖动造成的重复解冻,并保留下游扰动后的自动更新 - 支持非单调阀特性反解、最小可测面积以下直接全关,以及闭阀端精细扫点与辨识开关 - 调整双压力判稳、最长等待时间、在线入口全开收尾和闭环四联图 - 更新配置、README、阀模型及离线测试,归档本轮实验数据与诊断产物
This commit is contained in:
@@ -3,8 +3,8 @@
|
||||
本项目基于信捷 **Easy521 PLC**(Modbus TCP)提供三个可独立运行的在线入口和两个离线工具:
|
||||
|
||||
- [main.py](main.py):以 10 Hz 周期运行单回路气体流量闭环控制,支持增量式 PID,并可选“前馈反解打底 + PI 修残差”与按阀前压力缩放增益的增益调度;
|
||||
- [open_loop.py](open_loop.py):随机扫描阀门开度,采集阀前/阀后的压力与阀后流量,用于开环标定、动态特性观察和临界压力比分析。
|
||||
- [test_valve.py](test_valve.py):在 Windows 终端中手动切换阀门开度,同时观察并记录流量、压力和电机行程。
|
||||
- [open_loop.py](open_loop.py):随机扫描阀门开度,并在末尾追加闭阀端精细行程扫描;采集阀前/阀后的压力与阀后流量,用于开环标定、动态特性观察和临界压力比分析。
|
||||
- [test_valve.py](test_valve.py):在 Windows 终端中手动切换阀门开度,同时观察并记录阀后流量、阀前/阀后压力和电机行程。
|
||||
- [identify_valve.py](identify_valve.py):离线从开环扫点 CSV 拟合阀特性表,产出供前馈使用的 `valve_model.json`。
|
||||
- [test_valve_model.py](test_valve_model.py):阀特性模型与前馈反解的离线自测,不接触硬件。
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
|
||||
> 本项目会直接控制真实阀门。首次运行前必须核对 IP、站号、寄存器地址、传感器量程、阀门行程方向、压力上限和执行机构的断电/失驱位置,并准备独立的机械或电气急停手段。
|
||||
|
||||
三个入口当前采用不同的阀门初始化与退出策略:
|
||||
三个入口当前的阀门初始化与退出策略如下:
|
||||
|
||||
- **闭环 `main.py`**:启动时不再预先下发关闭位置,PID 内部输出由 `INITIAL_OPENING_PCT=100%` 开始;故障或退出时停止控制并断开 PLC,不主动下发关阀命令。当前系统按“执行机构失驱后回到全开”设计,现场必须确认实际硬件确实如此。
|
||||
- **开环 `open_loop.py`**:连接成功后先主动设置 `0%` 开度,实验结束、异常或 `Ctrl+C` 时再次尝试设置 `0%` 开度,然后断开设备。
|
||||
- **手动测试 `test_valve.py`**:连接时仅按已知状态记录 `100%` 开度,不向电机写入初始位置;退出时不主动下发新开度,仅断开设备。该脚本不执行流量/压力越限和连续读取失败保护,只适合在具备独立安全措施的受控测试中使用。
|
||||
- **闭环 `main.py`**:连接成功后先主动设置 `100%` 开度,再开始初始采样、性能报告和控制计时;故障、正常退出或 `Ctrl+C` 时再次尝试设置 `100%` 开度,然后断开 PLC。
|
||||
- **开环 `open_loop.py`**:连接成功后先主动设置 `100%` 开度,再创建记录器并开始实验计时;实验结束、异常或 `Ctrl+C` 时再次尝试设置 `100%` 开度,然后断开设备。
|
||||
- **手动测试 `test_valve.py`**:连接成功后先主动设置 `100%` 开度,再创建记录器并开始采样;退出时再次尝试设置 `100%` 开度,然后断开设备。该脚本不执行流量/压力越限和连续读取失败保护,只适合在具备独立安全措施的受控测试中使用。
|
||||
|
||||
因此,README 中的“关闭”或“全开”均指当前代码定义的逻辑位置,不能代替现场对阀门真实动作方向的确认。
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
- PLC(Easy521):Modbus TCP,默认 `192.168.1.88:502`,站号 `1`;
|
||||
- D 寄存器为直接 Modbus 地址:读用功能码 `03`(保持寄存器),写用功能码 `06`;
|
||||
- 模拟量原始范围:`0~32000`,线性对应各量程满量程;
|
||||
- 模拟量标称原始范围:`0~32000`,线性对应各量程满量程;读取时先把 Modbus 的 `0~65535` 解码为 16 位有符号值,因此传感器负偏差会换算为负物理量,并由上层有效范围检查处理;
|
||||
- 默认流量量程:`300 SLM`;阀后压力量程:`400 kPa`;阀前压力量程:`300 kPa`;
|
||||
- 电机行程范围:`0~1000`,且行程与阀门开度反向作用。
|
||||
|
||||
@@ -96,9 +96,9 @@ python main.py --target 50
|
||||
启动流程为:
|
||||
|
||||
```text
|
||||
校验配置 -> 连接 PLC -> 读取一次初始流量
|
||||
校验配置 -> 连接 PLC -> 主动设置 100% 开度(不计时)-> 读取一次初始流量
|
||||
-> PID 输出初始化为 INITIAL_OPENING_PCT
|
||||
-> 进入周期控制(启动阶段不主动写入关闭位置)
|
||||
-> 进入周期控制
|
||||
```
|
||||
|
||||
单个控制周期为:
|
||||
@@ -128,14 +128,14 @@ opening_to_motor_position()
|
||||
|
||||
| 模式 | 用途 | Kp / Ki / Kd | 最大开度速度 |
|
||||
| --- | --- | --- | ---: |
|
||||
| `FAR` | 大误差时快速接近目标 | `0.5 / 0.5 / 0.0` | `20%/s` |
|
||||
| `FAR` | 大误差时快速接近目标 | `0.5 / 0.5 / 0.0` | `200%/s` |
|
||||
| `NEAR` | 小误差时抑制振荡和稳态误差 | `0.05 / 0.01 / 0.0` | `2%/s` |
|
||||
|
||||
切换阈值同时考虑绝对误差下限和目标流量比例:
|
||||
|
||||
```text
|
||||
near_threshold = max(3 SLM, 5% * target)
|
||||
far_threshold = max(12 SLM, 20% * target)
|
||||
near_threshold = min(3 SLM, max(1 SLM, 5% * target))
|
||||
far_threshold = min(12 SLM, max(4 SLM, 20% * target))
|
||||
|
||||
FAR -> NEAR:|error| <= near_threshold,连续满足 10 个采样周期
|
||||
NEAR -> FAR :|error| >= far_threshold,连续满足 10 个采样周期
|
||||
@@ -147,7 +147,7 @@ NEAR -> FAR :|error| >= far_threshold,连续满足 10 个采样周期
|
||||
|
||||
### 前馈 + 增益调度(MFC 结构)
|
||||
|
||||
闭环默认仍为纯增量式 PID;在确认阀前压力接线、并用 [identify_valve.py](identify_valve.py) 拟合出阀特性表后,可切换到“前馈反解打底 + PI 修残差”的市面 MFC 结构,并可叠加按阀前压力缩放增益的增益调度。
|
||||
闭环当前默认启用“前馈反解打底 + PI 修残差”的 MFC 结构,并加载仓库根目录的 `valve_model.json`;按阀前压力缩放 Kp/Ki 的增益调度仍默认关闭。投用前必须确认阀前/阀后压力接线和阀特性表与当前硬件一致;不满足时应关闭前馈或重新辨识。
|
||||
|
||||
静态阀特性建模为:
|
||||
|
||||
@@ -168,7 +168,11 @@ PI 修正量 correction = PI(目标流量 - 实测流量) # 输出限幅改为
|
||||
开度 = clamp(opening_ff + correction, 0, 100)
|
||||
```
|
||||
|
||||
即前馈把开度送到稳态工作点附近,PI 只负责修正模型残差和动态偏差;PI 输出不再是 `0~100%` 的全行程,而是围绕前馈的小幅修正(限幅由 `FEEDFORWARD_CORRECTION_BAND_PCT` 控制,默认 ±20%)。前馈无法反解时(例如压比下无正向流、压力缺失)会自动退化为纯 PID。
|
||||
即前馈把开度送到稳态工作点附近,PI 只负责修正模型残差和动态偏差;PI 输出不再是 `0~100%` 的全行程,而是围绕前馈的修正量(限幅由 `FEEDFORWARD_CORRECTION_BAND_PCT` 控制,当前默认 ±50%)。
|
||||
|
||||
为避免接近目标后压力噪声持续改写前馈,同时又能响应下游负载变化,控制器维护一个 `FEEDFORWARD_UPDATE_WINDOW_S=3 s` 的流量绝对误差滑动窗口。窗口首次积满后,程序在每个控制周期都重新计算最近 3 秒的平均绝对误差,并与 `FEEDFORWARD_UPDATE_ERROR_THRESHOLD_SLM=5 SLM` 比较:均值不大于阈值时冻结上一次前馈开度,只让 PI correction 逐周期更新;均值超过阈值时重新根据当前目标流量和阀前/阀后压力反解前馈。因此,下游扰动持续影响流量并使 3 秒误差均值越过阈值后,前馈会自动解除冻结。
|
||||
|
||||
窗口未首次积满或尚无缓存前馈时,每个周期都尝试反解前馈。窗口一旦积满,其“已就绪”状态不会因采样抖动和旧样本淘汰而反复失效;但滑动均值仍会持续更新,冻结状态并不会锁死。目标改变、控制器重启或进入零流量分支会清空窗口并重新累计 3 秒。当前周期反解失败时继续复用上次有效前馈;如果从未得到有效前馈,则以 `0%` 为基值并由 correction 调整。
|
||||
|
||||
增益调度把 FAR/NEAR 的 Kp、Ki 按阀前绝对压力缩放,摊平 K_x ∝ P1 的非线性:
|
||||
|
||||
@@ -179,13 +183,13 @@ Kp_eff = scale · Kp_base,Ki_eff = scale · Ki_base # Kd 不调度
|
||||
|
||||
`scale` 相对变化超过 `GAIN_SCHEDULE_SCALE_CHANGE_THRESHOLD`(默认 5%)才重算并写入 PID,避免每个周期都更新增益。
|
||||
|
||||
三项均通过 `config.py` 中的开关启用,默认全部关闭:
|
||||
相关配置的当前默认值为:
|
||||
|
||||
| 开关 | 默认 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `FEEDFORWARD_ENABLED` | `False` | 启用前馈反解打底 + PI 修残差 |
|
||||
| `FEEDFORWARD_ENABLED` | `True` | 启用前馈反解打底 + PI 修残差 |
|
||||
| `GAIN_SCHEDULE_ENABLED` | `False` | 启用按阀前压力缩放 Kp/Ki |
|
||||
| `VALVE_MODEL_PATH` | `""` | 阀特性表 JSON 路径(空串 = 关闭前馈) |
|
||||
| `VALVE_MODEL_PATH` | `"valve_model.json"` | 阀特性表 JSON 路径(空串 = 关闭前馈) |
|
||||
| `PRESSURE_BEFORE_ADDR` | `720` | 阀前压力 P1 的寄存器地址(D720) |
|
||||
|
||||
前馈生效需同时满足:`FEEDFORWARD_ENABLED=True`、`VALVE_MODEL_PATH` 指向有效 JSON、`PRESSURE_BEFORE_ADDR` 与 `PRESSURE_AFTER_ADDR` 均已配置。任一条件缺失时自动退化为纯 PID,并在启动日志中提示。
|
||||
@@ -196,7 +200,7 @@ Kp_eff = scale · Kp_base,Ki_eff = scale · Ki_base # Kd 不调度
|
||||
|
||||
1. **终端与日志**:约每秒输出一次状态;非 `OK` 状态立即输出。日志保存到 `logs/flow_control.log`。
|
||||
2. **逐周期 CSV**:默认保存为 `data/flow_run_YYYYMMDD_HHMMSS.csv`,每行写入后立即刷新到磁盘。现有 `data/日期/实验说明/` 子目录是历史数据的人工归档方式,不是程序自动创建的层级。
|
||||
3. **三联曲线图**:结束时保存同名 PNG,依次显示目标/实际流量、阀门开度和压力;启用前馈时,开度子图会叠加虚线显示前馈开度。
|
||||
3. **四联曲线图**:结束时保存同名 PNG,依次显示目标/实际流量、阀门开度、阀前/阀后压力和绝对压力比;启用前馈时,开度子图会叠加虚线显示前馈开度,压力比子图绘制 `0.528` 临界参考线。
|
||||
4. **性能报告**:首次达到稳态时写入终端和日志;若整个运行过程未达到稳态,只输出未达到稳态的提示。
|
||||
|
||||
闭环 CSV 字段:
|
||||
@@ -208,6 +212,7 @@ Kp_eff = scale · Kp_base,Ki_eff = scale · Ki_base # Kd 不调度
|
||||
| `opening_pct` / `motor_position` | 阀门开度 / 电机行程 |
|
||||
| `pressure_kpa` | 阀后压力;未启用或读取失败时为空 |
|
||||
| `pressure_before_kpa` | 阀前压力 P1;未启用或读取失败时为空 |
|
||||
| `P_abs_ratio` | `(阀后表压 + 101.325) / (阀前表压 + 101.325)`;压力缺失或分母非法时为空 |
|
||||
| `feedforward_pct` | 前馈开度;未启用前馈时为空 |
|
||||
| `correction_pct` | PI 修正量(±带内);未启用前馈时为空 |
|
||||
| `gain_scale` | 增益调度缩放系数;未启用调度时为 `1.0` |
|
||||
@@ -217,22 +222,23 @@ Kp_eff = scale · Kp_base,Ki_eff = scale · Ki_base # Kd 不调度
|
||||
|
||||
### 稳态判定与性能报告
|
||||
|
||||
判稳只使用状态为 `OK` 的有效流量样本。滑窗至少覆盖 `STEADY_STATE_WINDOW_S - CONTROL_PERIOD_S`,以容纳真实采样时间戳抖动,并要求下列条件同时成立:
|
||||
判稳只使用状态为 `OK` 且流量、阀前压力、阀后压力均有效的样本。滑窗至少覆盖 `STEADY_STATE_WINDOW_S - CONTROL_PERIOD_S`,以容纳真实采样时间戳抖动,并要求下列条件同时成立:
|
||||
|
||||
```text
|
||||
|窗口均值 - 目标流量| <= STEADY_STATE_BAND_PCT / 100 * 目标流量
|
||||
窗口总体标准差 <= STEADY_STATE_STD_PCT / 100 * 目标流量
|
||||
阀前压力每个样本均位于阀前压力窗口均值 ± STEADY_STATE_PRESSURE_BAND_KPA
|
||||
阀后压力每个样本均位于阀后压力窗口均值 ± STEADY_STATE_PRESSURE_BAND_KPA
|
||||
```
|
||||
|
||||
当前默认使用 10 秒窗口、±1% 均值误差带和 1% 标准差阈值。报告内容包括判稳时当前模式的 PID 参数、目标与控制范围、调节时间、窗口均值、窗口标准差、稳态误差(目标减窗口均值)、初始流量,以及按初始变化方向计算的峰值/谷值超调量。
|
||||
当前默认使用 5 秒窗口、±1% 流量均值误差带和阀前/阀后各 `±1 kPa` 压力带。流量标准差仍会计算并写入报告,但不再作为闭环判稳条件。报告内容还包括两侧压力的窗口均值/最大偏差、判稳时当前模式的 PID 参数、目标与控制范围、调节时间、稳态误差(目标减窗口均值)、初始流量,以及按初始变化方向计算的峰值/谷值超调量。
|
||||
|
||||
## 开环扫点实验
|
||||
|
||||
[open_loop.py](open_loop.py) 不参与闭环反馈,也不会被 `main.py` 导入。默认将 `0%~100%`、间隔 `5%` 的 21 个开度按固定随机种子 `42` 打乱,然后逐点执行:
|
||||
[open_loop.py](open_loop.py) 不参与闭环反馈,也不会被 `main.py` 导入。默认先将 `0%~100%`、间隔 `5%` 的 21 个开度按固定随机种子 `42` 打乱并换算为行程,再在序列末尾追加 `970~1000`、间隔 `3` 的闭阀端精细行程点(末端不足一个步长时仍包含 `1000`)。精细段直接按行程下发,并反算逻辑开度用于记录。
|
||||
|
||||
```text
|
||||
写入开度 -> 每 0.1 s 采集阀前/阀后压力与阀后流量
|
||||
-> 等待阀后流量稳定,或等待满 60 s
|
||||
写入随机开度/精细行程 -> 每 0.1 s 采集阀前/阀后压力与阀后流量
|
||||
-> 等待阀后流量稳定,或等待满 30 s
|
||||
-> 切换到下一个开度
|
||||
```
|
||||
|
||||
@@ -256,7 +262,7 @@ python open_loop.py --min 0 --max 100 --step 5
|
||||
std <= max(STEADY_STATE_STD_PCT / 100 * |窗口均值|, MIN_ABS_STD_SLM)
|
||||
```
|
||||
|
||||
默认窗口为 10 秒,绝对标准差下限为 `0.05 SLM`。阀后流量连续 5 次读取失败会中止实验;其他通道读取失败会在对应 CSV 字段中留空。
|
||||
默认窗口为 5 秒,绝对标准差下限为 `0.05 SLM`,单点最长等待时间为 30 秒。阀后流量连续 5 次读取失败会中止实验;其他通道读取失败会在对应 CSV 字段中留空。
|
||||
|
||||
输出保存到 `open_loop_data/open_loop_YYYYMMDD_HHMMSS.csv/.png`,日志保存到 `logs/open_loop.log`。PNG 包含三张子图:阀前/阀后压力、阀前/阀后流量、阀后绝对压力与阀前绝对压力之比。由于阀前流量传感器已删除,“阀前流量”曲线与 `flow_before_slm` 列保持为空。
|
||||
|
||||
@@ -276,14 +282,14 @@ CSV 同时记录 `is_ratio_smaller_than_0.528`:压力比小于临界值 `0.528
|
||||
python test_valve.py
|
||||
```
|
||||
|
||||
连接成功后,脚本把当前已知状态记为 `100%` 开度、行程 `800`,但不会立即向电机写入该位置。运行期间:
|
||||
连接成功后,脚本主动写入 `100%` 开度、行程 `800`,完成后才创建记录器并开始采样。运行期间:
|
||||
|
||||
- 每秒读取并显示一次流量、压力、逻辑开度和映射后的电机行程;
|
||||
- 每秒读取并显示一次阀后流量、阀前/阀后压力、各传感器反算模拟量原始值、逻辑开度和映射后的电机行程;
|
||||
- 按 `S` 进入输入模式,输入 `0~100` 的新开度后按回车下发,按 `Esc` 取消;
|
||||
- 输入期间暂停终端状态显示,但传感器采样和 CSV 写入继续;
|
||||
- 按 `Ctrl+C` 保存数据并退出,不主动下发新的阀门开度。
|
||||
- 按 `Ctrl+C` 保存数据并退出;断开前会再次尝试下发 `100%` 开度。
|
||||
|
||||
数据保存为 `test_valve_data/test_valve_YYYYMMDD_HHMMSS.csv`,字段包含相对时间、ISO 时间戳、流量、开度、压力和电机行程;结束时生成同名三联图,依次显示流量、开度和压力。
|
||||
数据保存为 `test_valve_data/test_valve_YYYYMMDD_HHMMSS.csv`,字段包含相对时间、ISO 时间戳、`flow_after_slm`、开度、`pressure_before_kpa`、`pressure_after_kpa` 和电机行程;结束时生成同名三联图,依次显示阀后流量、开度以及叠加的阀前/阀后压力。
|
||||
|
||||
> 此脚本不会调用 `config.validate_config()`,也没有闭环/开环程序中的流量越限、压力越限或连续读取失败保护。运行前应人工完成配置核对,并确保测试人员能够立即切断气源或执行急停。
|
||||
|
||||
@@ -299,10 +305,12 @@ python identify_valve.py --plot # 省略 --csv 时默认合并 open_loop_da
|
||||
|
||||
- 每个 CSV 按 `step_index` 分组,每组取末尾 `--tail` 个采样点平均,得到稳态 `(行程 x, 流量 Q, 阀前压 P1, 阀后压 P2)`,并按开度访问顺序标记逼近方向(上升 / 下降 / 该文件起始步);
|
||||
- 对每个稳态点反解 `A_eff = Q / (P1_abs · F(r))`;同一行程 x 的多个点(来自不同次实验)先取平均再构表;
|
||||
- 按行程升序构表并做单调性检查;若整体非单调,只保留最长单调连续段,其余点丢弃并给出警告;
|
||||
- 按行程升序构表。`IDENTIFY_VALVE_MONOTONIC_CHECK_ENABLED=False`(当前默认)时保留所有按行程平均后的点,并在 JSON 记录 `"enforce_monotonic": false`;设为 `True` 时检查单调性,整体非单调则只保留最长单调连续段并警告其余点被丢弃;
|
||||
- 用 [valve_model.py](valve_model.py) 存成 JSON,并打印合并文件数、稳态点数与阻塞/亚声速点统计等摘要;加 `--plot` 额外生成诊断图,实测点按逼近方向着色:同一行程下上升/下降两团点明显分离说明阀门迟滞显著,前馈表应考虑分方向处理;完全重叠则迟滞可忽略。
|
||||
|
||||
将 `config.VALVE_MODEL_PATH` 指到该 JSON、确认 `PRESSURE_BEFORE_ADDR` 接线无误、并把 `FEEDFORWARD_ENABLED` 设为 `True` 后,闭环即可启用前馈。
|
||||
非单调表可能让同一个有效面积对应多个行程,反解时选择数值更大的行程,即更靠近关闭端的交点。目标有效面积小于表中最小实测值时直接返回机械全关行程 `MOTOR_CLOSED_POSITION`;恰好等于最小值时仍返回对应实测行程。
|
||||
|
||||
将 `config.VALVE_MODEL_PATH` 指到该 JSON、确认 `PRESSURE_BEFORE_ADDR` 接线无误、并把 `FEEDFORWARD_ENABLED` 设为 `True` 后,闭环即可启用前馈。当前配置已指向 `valve_model.json` 并默认启用,重新标定后应覆盖该文件或同步修改配置路径。
|
||||
|
||||
[test_valve_model.py](test_valve_model.py) 是纯计算离线自测,不接触硬件,可在任意环境运行:
|
||||
|
||||
@@ -310,7 +318,11 @@ python identify_valve.py --plot # 省略 --csv 时默认合并 open_loop_da
|
||||
python test_valve_model.py
|
||||
```
|
||||
|
||||
它校验压比函数 `F(r)`、绝对压力换算、`A_eff` 插值与前馈反解互逆,以及 `identify_valve` 端到端辨识。
|
||||
它校验压比函数 `F(r)`、绝对压力换算、`A_eff` 插值与前馈反解互逆、单调/非单调表反解、闭阀端精细扫描点生成,以及 `identify_valve` 端到端辨识。[test_flow_control.py](test_flow_control.py) 校验前馈误差滑窗在采样抖动下保持就绪、同时持续响应新误差;[test_performance_reporter.py](test_performance_reporter.py) 另行校验闭环的流量均值与压力带判稳逻辑。可一次运行全部离线测试:
|
||||
|
||||
```powershell
|
||||
python -m pytest -q
|
||||
```
|
||||
|
||||
## 安全与故障处理
|
||||
|
||||
@@ -322,22 +334,22 @@ python test_valve_model.py
|
||||
- 实际控制周期超过 `MAX_CONTROL_DT_S` 时停止控制;
|
||||
- PID 输出限制在 `0~100%`;FAR/NEAR 两档分别限制每秒最大开度变化;
|
||||
- 电机命令写入异常或返回失败时停止控制;
|
||||
- 所有退出路径都会尝试断开设备,但当前闭环代码不会主动下发关阀命令。
|
||||
- 所有退出路径都会在断开设备前尝试下发 `100%` 开度;下发失败会记录严重错误并返回非零退出码。
|
||||
|
||||
### 开环
|
||||
|
||||
- 启动和收尾均主动下发 `0%` 开度;
|
||||
- 启动和收尾均主动下发 `100%` 开度;
|
||||
- 任一有效流量读数越界、任一有效压力读数超过上限时中止;
|
||||
- 阀后流量连续读取失败达到阈值时中止;
|
||||
- 写入开度失败时中止;
|
||||
- 中止后仍会尽力关阀、断开连接并保留已经写入的 CSV。
|
||||
- 中止后仍会尽力恢复 `100%` 开度、断开连接并保留已经写入的 CSV。
|
||||
|
||||
### 手动测试
|
||||
|
||||
- 只校验输入开度是否为 `0~100` 的有限数值以及电机写入是否成功;
|
||||
- 传感器读取失败时 CSV 对应字段留空,终端显示 `--`,不会自动中止;
|
||||
- 不检查流量和压力安全阈值;
|
||||
- `Ctrl+C`、异常和正常收尾均不会主动关阀,只会断开连接并保存已有数据。
|
||||
- `Ctrl+C`、异常和正常收尾都会在保存已有数据、断开连接前尝试恢复 `100%` 开度。
|
||||
|
||||
## 关键配置默认值
|
||||
|
||||
@@ -354,16 +366,17 @@ python test_valve_model.py
|
||||
| `PID_FAR_KP` / `PID_FAR_KI` / `PID_FAR_KD` | `0.5` / `0.5` / `0.0` | 大误差快速模式 PID 参数 |
|
||||
| `PID_NEAR_KP` / `PID_NEAR_KI` / `PID_NEAR_KD` | `0.05` / `0.01` / `0.0` | 小误差稳定模式 PID 参数 |
|
||||
| `OPENING_MIN_PCT` / `OPENING_MAX_PCT` | `0` / `100` | PID 输出开度范围 |
|
||||
| `MAX_OPENING_RATE_FAR_PCT_S` / `MAX_OPENING_RATE_NEAR_PCT_S` | `20` / `2` | FAR/NEAR 每秒最大开度变化百分比 |
|
||||
| `PID_NEAR_ERROR_MIN_SLM` / `PID_NEAR_ERROR_TARGET_RATIO` | `3` / `0.05` | FAR 进入 NEAR 的绝对/相对误差阈值 |
|
||||
| `PID_FAR_ERROR_MIN_SLM` / `PID_FAR_ERROR_TARGET_RATIO` | `12` / `0.20` | NEAR 返回 FAR 的绝对/相对误差阈值 |
|
||||
| `MAX_OPENING_RATE_FAR_PCT_S` / `MAX_OPENING_RATE_NEAR_PCT_S` | `200` / `2` | FAR/NEAR 每秒最大开度变化百分比 |
|
||||
| `PID_NEAR_ERROR_MIN_SLM` / `PID_NEAR_ERROR_MAX_SLM` / `PID_NEAR_ERROR_TARGET_RATIO` | `1` / `3` / `0.05` | FAR 进入 NEAR 的误差阈值下限、上限和目标比例 |
|
||||
| `PID_FAR_ERROR_MIN_SLM` / `PID_FAR_ERROR_MAX_SLM` / `PID_FAR_ERROR_TARGET_RATIO` | `4` / `12` / `0.20` | NEAR 返回 FAR 的误差阈值下限、上限和目标比例 |
|
||||
| `PID_MODE_SWITCH_CONFIRM_CYCLES` | `10` | 模式切换条件需连续满足的采样周期数(当前约 1 秒) |
|
||||
| `MOTOR_CLOSED_POSITION` / `MOTOR_OPEN_POSITION` | `1000` / `800` | 当前反向控制区间;打开端为机械死区边界 |
|
||||
| `INITIAL_OPENING_PCT` | `100` | 闭环 PID 内部初始输出 |
|
||||
| `PRESSURE_BEFORE_ADDR` | `720` | 阀前压力 P1 的寄存器地址(前馈/增益调度/开环共用) |
|
||||
| `VALVE_MODEL_PATH` | `""` | 阀特性表 JSON 路径;空串关闭前馈 |
|
||||
| `FEEDFORWARD_ENABLED` | `False` | 是否启用前馈反解打底 + PI 修残差 |
|
||||
| `FEEDFORWARD_CORRECTION_BAND_PCT` | `20` | 前馈开启时 PI 修正量的对称限幅(±%) |
|
||||
| `VALVE_MODEL_PATH` | `"valve_model.json"` | 阀特性表 JSON 路径;空串关闭前馈 |
|
||||
| `FEEDFORWARD_ENABLED` | `True` | 是否启用前馈反解打底 + PI 修残差 |
|
||||
| `FEEDFORWARD_CORRECTION_BAND_PCT` | `50` | 前馈开启时 PI 修正量的对称限幅(±%) |
|
||||
| `FEEDFORWARD_UPDATE_ERROR_THRESHOLD_SLM` / `FEEDFORWARD_UPDATE_WINDOW_S` | `5` / `3` | 前馈冻结/更新的流量绝对误差均值阈值与窗口长度 |
|
||||
| `GAIN_SCHEDULE_ENABLED` | `False` | 是否启用按阀前压力缩放 Kp/Ki |
|
||||
| `GAIN_SCHEDULE_REF_ABS_KPA` | `501.325` | 满压调好基准增益对应的绝对压力(400 + 101.325) |
|
||||
| `GAIN_SCHEDULE_FLOOR_ABS_KPA` | `60` | 绝对压力下限,防止 P1 很低时增益爆炸 |
|
||||
@@ -371,7 +384,10 @@ python test_valve_model.py
|
||||
| `FLOW_VALID_MIN_SLM` / `FLOW_VALID_MAX_SLM` | `0` / `300` | 流量安全范围 |
|
||||
| `MAX_PRESSURE_KPA` | `500` | 压力安全上限,须按实际管路额定压力确认 |
|
||||
| `MAX_CONSECUTIVE_FLOW_FAILURES` / `MAX_CONSECUTIVE_PRESSURE_FAILURES` | `3` / `3` | 闭环连续读取失败阈值 |
|
||||
| `STEADY_STATE_WINDOW_S` / `STEADY_STATE_BAND_PCT` / `STEADY_STATE_STD_PCT` | `10` / `1` / `1` | 闭环稳态判定参数 |
|
||||
| `STEADY_STATE_WINDOW_S` / `STEADY_STATE_BAND_PCT` / `STEADY_STATE_PRESSURE_BAND_KPA` | `5` / `1` / `1` | 闭环窗口、流量均值误差带和压力稳定带 |
|
||||
| `STEADY_STATE_MAX_WAIT_S` / `STEADY_STATE_STD_PCT` | `30` / `1` | 开环单点最长等待时间 / 流量稳定标准差比例 |
|
||||
| `OPEN_LOOP_FINE_STROKE_START` / `OPEN_LOOP_FINE_STROKE_STEP` | `970` / `3` | 开环闭阀端精细行程扫描起点 / 步长 |
|
||||
| `IDENTIFY_VALVE_MONOTONIC_CHECK_ENABLED` | `False` | 辨识时是否只保留最长单调连续段 |
|
||||
| `AUTO_STOP_ON_STEADY` | `False` | 达到稳态后是否自动结束闭环 |
|
||||
|
||||
## 模块职责
|
||||
@@ -382,13 +398,15 @@ python test_valve_model.py
|
||||
| [flow_control.py](flow_control.py) | 闭环控制层、传感器读取、开度/行程映射、前馈与增益调度、故障处理 |
|
||||
| [controllers.py](controllers.py) | 通用增量式 PID,含输出限幅和输出变化率限幅 |
|
||||
| [config.py](config.py) | 闭环集中配置和启动前校验 |
|
||||
| [data_logger.py](data_logger.py) | 闭环逐周期 CSV 与三联曲线图(含前馈/修正/增益调度列) |
|
||||
| [performance_reporter.py](performance_reporter.py) | 闭环滑窗判稳和一次性性能报告 |
|
||||
| [data_logger.py](data_logger.py) | 闭环逐周期 CSV 与四联曲线图(含前馈/修正/增益调度/压力比列) |
|
||||
| [performance_reporter.py](performance_reporter.py) | 闭环流量均值与双压力带判稳、一次性性能报告 |
|
||||
| [open_loop.py](open_loop.py) | 独立开环扫点、传感器记录和压力比分析 |
|
||||
| [test_valve.py](test_valve.py) | Windows 终端手动开度测试、每秒采样、CSV 与三联图 |
|
||||
| [valve_model.py](valve_model.py) | 静态阀特性模型 `Q_ss = A_eff(x)·P1_abs·F(r)` 与前馈反解(纯计算) |
|
||||
| [identify_valve.py](identify_valve.py) | 从一份或多份开环扫点 CSV(支持 glob 合并)拟合 `A_eff(x)` 表,输出 `valve_model.json` |
|
||||
| [test_valve_model.py](test_valve_model.py) | 阀特性模型与前馈反解的离线自测 |
|
||||
| [test_flow_control.py](test_flow_control.py) | 前馈误差滑窗、采样抖动与复位逻辑的离线测试 |
|
||||
| [test_performance_reporter.py](test_performance_reporter.py) | 闭环性能报告器与压力带判稳的离线测试 |
|
||||
| [PcControl.py](PcControl.py) | Modbus 硬件客户端;本项目三个入口实际使用 `Easy521ModbusClient` |
|
||||
|
||||
## 项目结构
|
||||
@@ -406,6 +424,8 @@ flow_control/
|
||||
├── valve_model.py # 静态阀特性模型与前馈反解
|
||||
├── identify_valve.py # 从开环 CSV 拟合阀特性表
|
||||
├── test_valve_model.py # 阀特性模型离线自测
|
||||
├── test_flow_control.py # 前馈误差滑窗离线测试
|
||||
├── test_performance_reporter.py # 闭环判稳逻辑离线测试
|
||||
├── PcControl.py
|
||||
├── README.md
|
||||
├── data/ # 闭环 CSV / PNG;历史数据可能已人工分组
|
||||
|
||||
Reference in New Issue
Block a user