Files
flow_control/README.md
T

121 lines
5.8 KiB
Markdown
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.
# 气体流量闭环控制系统
基于 **MT2-AM8 模拟量采集/输出模块** 的单回路气体流量 PID 闭环控制程序。
程序以 10 Hz 周期读取流量(可选读取压力),经增量式 PID 计算阀门开度,
映射为电机行程后通过 Modbus TCP 下发给执行机构,并在每次运行结束后自动
保存逐周期数据、生成三联曲线图与一次性的控制性能报告。
## 硬件与通讯
- 采集/输出模块:艾莫迅 **MT2-AM8**Modbus TCP,默认 `192.168.1.12:502`,站号 1
- 模拟量输入(AI):地址 `0x00~0x03`0~4095 对应 0~10V / 0~20mA
- 模拟量输出(AO):保持寄存器 `0x00~0x03`
- 流量计量程默认 300 SLM,压力表量程默认 400 kPa
- 电机行程与开度**反向作用**:行程越大开度越小,
`opening=0% → MOTOR_CLOSED_POSITION``opening=100% → MOTOR_OPEN_POSITION`
> 所有地址、通道、量程、行程端值均在 [config.py](config.py) 中集中配置,
> 首次连接真实设备前必须核对。
## 架构与模块职责
| 文件 | 职责 |
| --- | --- |
| [main.py](main.py) | 程序入口:解析参数、装配日志/控制器/记录器/报告器、主循环与安全退出 |
| [flow_control.py](flow_control.py) | 闭环控制层:`读取传感器 → PID → 开度/行程映射 → 下发电机位置`,含全部安全处理 |
| [controllers.py](controllers.py) | 通用增量式 PID 控制器 `IncrementalPID`(输出限幅 + 输出变化率限幅) |
| [config.py](config.py) | 集中配置与 `validate_config()` 启动前校验 |
| [data_logger.py](data_logger.py) | `FlowRunRecorder`:逐周期写 CSV,运行结束生成三联曲线图 |
| [performance_reporter.py](performance_reporter.py) | `PerformanceReporter`:滑窗稳态判定,输出一次性性能报告 |
| [PcControl.py](PcControl.py) | 硬件层:`MT2AM8Client` 等 Modbus 客户端(本项目实际使用 `MT2AM8Client` |
### 控制回路流程
```
读取流量/压力 (MT2-AM8)
IncrementalPID.update() ──► 开度百分比 0~100%
opening_to_motor_position() ──► 反向行程 0~1000
hardware.set_motor_position() ──► Modbus TCP 写 AO
```
`error = setpoint - measurement`;PID 输出累加后统一映射为阀门开度百分比,
再做行程换算,因此 PID 与执行机构解耦。
## 快速开始
```bash
python main.py --target 50
```
- `--target`:目标流量(SLM),必须在 `[TARGET_FLOW_MIN_SLM, TARGET_FLOW_MAX_SLM]` 内。
- 启动流程:连接 MT2-AM8 → 确认阀门关闭 → 读取初始流量 → 启动闭环。
- 停止:`Ctrl+C`;控制故障、未处理异常同样会触发安全关阀并断开设备。
## 运行输出
1. **终端/日志**:周期状态行(状态、目标/实际流量、压力、开度、行程、实际 dt),
日志同时写入 [logs/flow_control.log](logs/flow_control.log)。
2. **逐周期数据**:每次运行生成 `data/flow_run_<时间戳>.csv`
3. **曲线图**:与 CSV 同名的 PNG 三联图(流量响应 / 阀门开度 / 压力)。
4. **性能报告**:首次达到稳态时打印一次,包含:
- 本次 PID 参数(Kp / Ki / Kd
- 调节时间(至稳态,秒)
- 超调量(绝对 SLM + 相对目标百分比)
- 本次控制范围
稳态判定为两个条件**同时**满足:滑窗均值落在目标 ±`STEADY_STATE_BAND_PCT`% 误差带内,
且滑窗标准差低于 `STEADY_STATE_STD_PCT`% 目标流量阈值。考虑采样时间戳抖动,
滑窗覆盖时长允许一个控制周期的余量。
## 安全机制
- **启动前安全关阀**:控制开始前先确认阀门已关闭。
- **流量/压力越限关阀**:读数超出 `FLOW_VALID_*` 或超过 `MAX_PRESSURE_KPA` 立即关阀。
- **连续读取失败关阀**:短暂读取失败保持上一输出;连续达到阈值后关阀。
- **控制循环超时保护**:实际周期超过 `MAX_CONTROL_DT_S` 判定超时。
- **输出变化率限幅**`MAX_OPENING_RATE_PCT_S` 限制开度变化速度,防止阀门阶跃冲击。
- **退出安全关阀**:任何退出路径(含异常)都会再次尝试关阀并断开设备。
## 关键配置项
见 [config.py](config.py),常用项:
| 配置 | 默认值 | 说明 |
| --- | --- | --- |
| `MT2AM8_HOST` / `MT2AM8_PORT` / `MT2AM8_SLAVE_ID` | `192.168.1.12` / `502` / `1` | 模块地址 |
| `FLOW_INPUT_CHANNEL` / `PRESSURE_INPUT_CHANNEL` / `MOTOR_OUTPUT_CHANNEL` | `1` / `0` / `0` | AI/AO 通道(0 起始) |
| `FLOW_METER_RANGE_SLM` / `PRESSURE_RANGE_KPA` | `300` / `400` | 量程 |
| `CONTROL_PERIOD_S` | `0.1` | 控制周期(100 ms10 Hz |
| `PID_KP` / `PID_KI` / `PID_KD` | `0.5` / `0.1` / `0.0` | 安全起步 PI 参数,需现场整定 |
| `MOTOR_CLOSED_POSITION` / `MOTOR_OPEN_POSITION` | `1000` / `0` | 行程端值 |
| `MAX_PRESSURE_KPA` | `400` | 压力上限,须按管路额定压力确认 |
| `STEADY_STATE_WINDOW_S` / `STEADY_STATE_BAND_PCT` / `STEADY_STATE_STD_PCT` | `10.0` / `1.0` / `1.0` | 稳态判定参数 |
## 依赖
- Python 3
- [pymodbus](https://pymodbus.readthedocs.io/)`PcControl.py` 的 Modbus TCP 通讯)
- [matplotlib](https://matplotlib.org/)(曲线图生成,使用 `Agg` 后端,无显示器环境也可保存)
## 项目结构
```
flow_control/
├── main.py # 程序入口
├── flow_control.py # 闭环控制层
├── controllers.py # 增量式 PID
├── config.py # 集中配置与校验
├── data_logger.py # CSV 记录 + 曲线图
├── performance_reporter.py # 稳态判定 + 性能报告
├── PcControl.py # Modbus 硬件客户端
├── data/ # 每次运行的 CSV / PNG
└── logs/ # 运行日志
```