联动调度
1. 项目概述
本系统是一个家电产线测试自动化平台,由三个组件协同工作:
| 组件 | 功能 | 启动方式 |
|---|---|---|
| 电压采集上位机 (1.py) | 18通道 Modbus RTU 电压采集、波形显示、数据存储 | 独立启动 python 1.py |
| NTC 模拟器 (NTC.py / NTCSimTab) | 6通道 NTC 热敏电阻温度-电压模拟、曲线加载 | 可独立或集成启动 |
| 联动调度引擎 (auto_coordinator) | 自动联调:偏差补偿、斜率保护、通道联动、自动升降斜坡 | run_coordinator.bat 或 python -m auto_coordinator.app |
系统工作流程:电压采集上位机实时采集 18 路电压 → NTC 模拟器生成对应温度 → 联动引擎根据偏差自动调整温度和斜率,使电压稳定在目标值。
2. 环境要求
-
Python 3.7+
-
依赖包:
PyQt5 pyqtgraph pymodbus (>=3.0) pandas openpyxl numpy minimalmodbus pyserial安装命令:
pip install PyQt5 pyqtgraph pymodbus pandas openpyxl numpy minimalmodbus pyserial -
硬件:支持 Modbus RTU 协议的电压采集模块、HK 系列串口输出模块
-
数据库:使用 SQLite3(Python 内置),无需额外安装
3. 快速启动
3.1 一键环境配置
在新电脑上首次使用时,运行环境配置脚本:
cd jiaohu
python setup.py
该脚本自动完成:Python 版本检查 → 依赖包安装 → 配置文件创建 → 数据库初始化 → 运行测试验证。
3.2 启动联动调度引擎(推荐入口)
双击 run_coordinator.bat,或在命令行执行:
cd jiaohu
python -m auto_coordinator.app
这会打开统一界面,包含以下 5 个标签页:
| 序号 | 标签页 | 功能 |
|---|---|---|
| 1 | NTC模拟 | NTC 温度模拟器控制面板 |
| 2 | 电压采集 | 18通道电压采集与监控 |
| 3 | 通道绑定 | 配置 NTC 通道与电压通道的对应关系 |
| 4 | 状态看板 | 实时显示各通道运行状态 |
| 5 | 事件日志 | 查询和导出历史事件记录 |
3.3 界面工具栏
| 按钮 | 功能 |
|---|---|
| 📌 置顶 | 窗口始终保持在最前 |
| 启动 | 启动联动调度引擎 |
| 暂停 / 恢复 | 暂停或恢复引擎运行 |
| 停止 | 停止引擎运行 |
3.4 状态栏
底部状态栏实时显示:
- NTC: NTC 模拟器在线/离线状态
- 1.py: 电压采集上位机在线/离线状态
- 引擎: 引擎运行状态(已停止 / 运行中 / 已暂停)
4. 详细功能说明
4.1 电压采集(第二个标签页)
功能概述
通过 Modbus RTU 协议采集 18 路电压数据,提供实时波形显示、数据存储和事件监控。
操作步骤
- 连接设备:选择串口号和波特率,点击"连接"按钮
- 开始采样:点击"开始采样"开始数据采集
- 查看波形:左下区域显示 18 通道实时波形图
- 查看数据:右下区域表格显示各通道电压值
工具栏按钮
- 阈值设置:为每个通道设置超阈值报警电压
- 通道名称配置:自定义 18 个通道的显示名称
- 事件显示方式:切换事件列表的显示模式
- 图表显示模式:切换波形图显示模式
- 切换时间格式:切换时间戳显示格式
- 导出数据:导出采集数据到文件
- 关于:软件版本信息
数据存储
采集的电压数据自动存入 voltage_data.db 数据库,包含 18 个通道的电压值和时间戳。
4.2 NTC 模拟器(第一个标签页)
功能概述
模拟 6 路 NTC 热敏电阻的温度-电压转换,通过 HK 串口模块输出对应电压。
操作步骤
- 选择串口:下拉框选择目标 COM 口,填写 Modbus 地址(默认 1)
- 打开串口:点击"打开串口",成功后按钮变为"已连接"
- 设置通道参数:为每个通道配置:
- 通道名:双击名称框编辑
- NTC 曲线:下拉选择(对应 NTC.xlsx 中的工作表名)
- 上拉电阻:单位 kΩ,影响电压输出曲线
- 温度设定:直接在输入框输入或拖动下方滑块
- 上限/下限:温度变化的上限和下限值(°C)
- 斜率:温度变化速度(°C/min),正值升温,负值降温
- 自动模式:勾选后通道自动按斜率和限温上升/下降
- 暂停/恢复:暂停所有通道的温度更新(与引擎暂停独立)
- 复位:将所有通道恢复到 25°C
- 加载配置:重新加载 NTC.json 配置文件
通道颜色标识
6 个通道使用不同背景色标识:蓝色、橙色、绿色、黄色、紫色、粉色。
NTC 曲线说明
NTC 热敏电阻的阻值-温度曲线存储在 NTC.xlsx 文件中。每个工作表代表一条曲线,工作表名即为曲线名称。
文件格式要求:
- 第一列:温度(°C),整数
- 第二列:对应阻值(kΩ),浮点数
- 温度范围建议覆盖 -50°C 到 150°C
默认使用 B=3950 标准 NTC 曲线(R25=10kΩ),电压输出范围约 0.1V ~ 4.9V。
配置文件
通道参数自动保存到 NTC.json,下次启动时自动恢复。
4.3 通道绑定(第三个标签页)
功能概述
配置 6 个 NTC 通道与 18 个电压采集通道之间的对应关系,使引擎知道哪个 NTC 通道对应哪个硬件通道。
操作步骤
- 在下拉框中为每个 NTC CH1~CH6 选择对应的电压通道(1~18)
- 设置容差:允许的电压偏差范围(单位 V,默认 0.05V)
- 设置自动补偿:勾选后引擎自动调整温度补偿电压偏差
- 点击"保存配置"存入数据库
导出/导入
- 导出模板:将当前绑定配置导出为 JSON 文件
- 导入模板:从之前导出的 JSON 文件恢复配置
4.4 状态看板(第四个标签页)
实时显示 6 个通道的运行状态,包括:
| 列名 | 说明 |
|---|---|
| 通道名 | 自定义通道名称 |
| 设温(°C) | 目标设定温度 |
| 期望V | 期望电压值(根据温度计算) |
| 实际V | 实际采集电压值 |
| 偏差V | 期望与实际电压之差 |
| 补偿V | 本次循环的补偿电压量 |
| 斜率 | 当前温度变化斜率 |
| 限幅 | 是否达到温度上下限 |
| 自动 | 是否启用自动模式 |
颜色指示
- 白色:偏差在容差范围内(正常)
- 黄色:偏差中等(0.3V 以内)
- 橙色:偏差较大(0.5V 以内)
- 红色:偏差超过 0.5V(硬件故障)
4.5 事件日志(第五个标签页)
功能概述
记录和查询联动引擎运行期间的所有事件。
操作步骤
- 选择事件类型过滤:全部 / COMPENSATION / SLOPE_ADJ / SLOPE_ADJ_ESCALATE / HW_FAULT / AUTO_STOP
- 选择通道过滤:全部通道 / CH1 ~ CH6
- 设置时间范围:起止日期时间
- 点击"查询"刷新列表
- 点击"导出Excel"导出查询结果为 Excel 文件
- 点击"清除日志"清空所有历史记录
事件类型说明
| 类型 | 含义 |
|---|---|
| COMPENSATION | 常规偏差补偿 |
| SLOPE_ADJ | 超阈值降斜率 |
| SLOPE_ADJ_ESCALATE | 降斜率后仍上升,再次降斜率 |
| HW_FAULT | 大偏差硬件故障(>0.5V) |
| AUTO_STOP | 上位机离线自动停止 |
5. 引擎工作原理
5.1 控制循环
引擎以 100ms 间隔运行控制循环,每周期执行:
1. 存活检测 → 检查 NTC 模拟器和电压采集上位机是否在线
↓(掉线则自动停止)
2. 读取数据 → 从数据库和 JSON 文件读取当前电压和 NTC 状态
↓
3. 偏差分级 → 对每个通道计算实际电压与期望电压的偏差
↓
4. 分级处理:
├─ 偏差 ≤ 容差 → 正常,计数器归零
├─ 偏差 > 0.5V → HW_FAULT 硬件故障报警
└─ 容差 < 偏差 ≤ 0.5V → 触发补偿
↓
5. 阈值检测 → 电压超过阈值则降斜率
↓
6. 自动斜坡 → 自动模式下按斜率更新温度
↓
7. 写日志 → 批量写入数据库
5.2 自动补偿机制
当实际电压偏离期望值时(超出容差但未超 0.5V),引擎自动调整 NTC 温度来修正偏差:
补偿电压 = -偏差 × 阻尼系数(0.5)
补偿上限 = ±0.2V/周期
最大重试 = 10 次
补偿后偏差归零则重试计数器清零,超限则停止补偿并触发限幅标记。
5.3 斜率保护机制
当某通道实际电压超过配置阈值时:
- 一级降斜率:当前斜率 × 0.5(最低降至 0.1)
- 监控上升:降斜率后若电压仍在上升超过 3 个周期
- 二级降斜率:再次乘以 0.5
- 恢复条件:电压回到阈值以下并持续 5 个周期
5.4 自动斜坡
勾选"自动"模式的通道,引擎每周期自动按斜率更新温度:
新温度 = 当前温度 + 斜率/60 × 0.1(控制周期)
温度达到上限/下限时自动限幅,所有通道同时到达限幅且无补偿时引擎休眠。
6. 技术路线与数据流
6.1 技术栈
| 层级 | 技术 | 用途 |
|---|---|---|
| 语言 | Python 3.8+ | 全项目 |
| GUI | PyQt5 | 统一界面框架(QMainWindow + QTabWidget + QScrollArea) |
| 图表 | pyqtgraph | 18 通道实时波形渲染(毫秒级刷新) |
| 数学 | numpy | 电阻-温度曲线插值计算 |
| 通信 | pymodbus / minimalmodbus | Modbus RTU 协议读写 |
| 串口 | pyserial | COM 端口枚举与配置 |
| 数据 | pandas + openpyxl | NTC 曲线 Excel 加载、事件日志导出 |
| 存储 | SQLite3 | 电压数据、通道绑定、事件日志、运行状态 |
| 并发 | threading | 引擎控制循环独立线程 |
| 配置 | JSON | 运行参数、NTC 状态持久化 |
6.2 系统架构
┌──────────────────────────────────────────────────────────────┐
│ PyQt5 统一界面 (app.py) │
│ ┌──────────┬──────────┬──────────┬───────────┬───────────┐ │
│ │ NTC模拟 │ 电压采集 │ 通道绑定 │ 状态看板 │ 事件日志 │ │
│ │(ntc_sim) │(acq_tab) │(bind_tab)│(dashboard)│(log_tab) │ │
│ └────┬─────┴────┬─────┴──────────┴─────┬─────┴───────────┘ │
│ │ │ │ │
│ │ ┌──────┴──────────────────────┴─────┐ │
│ │ │ AutoCoordinator (engine.py) │ │
│ │ │ ┌──────────────────────────────┐ │ │
│ │ │ │ 控制循环线程 │ │ │
│ │ │ │ 100ms 间隔, 每周期 7 步 │ │ │
│ │ │ │ 存活检测→读数据→偏差分级 │ │ │
│ │ │ │ →补偿/故障→斜率守卫→斜坡 │ │ │
│ │ │ │ →写状态快照→推送UI │ │ │
│ │ │ └──────────┬───────────────────┘ │ │
│ │ │ │ │ │
│ │ │ ┌──────────┼───────────────────┐ │ │
│ │ │ │ DataReader │ NTCJsonWriter │ │ │
│ │ │ │ (SQLite读) │ (JSON 原子写) │ │ │
│ │ │ └──────┬─────┴────────┬────────┘ │ │
│ │ └─────────┼──────────────┼───────────┘ │
└───────┼─────────────┼──────────────┼──────────────────────────┘
│ │ │
▼ ▼ ▼
┌──────────┐ ┌────────────┐ ┌───────────┐
│ Modbus │ │ voltage │ │ NTC.json │
│ RTU 硬件 │ │ _data.db │ │ 配置文件 │
│(DAM-3058)│ │ (SQLite) │ │ (JSON) │
└──────────┘ └────────────┘ └─────┬─────┘
│
┌─────────┴─────────┐
│ HK 系列串口模块 │
│ (6通道模拟电压输出) │
└───────────────────┘
6.3 数据流详解
6.3.1 电压采集数据流
DAM-3058 采集模块 (18通道)
│
│ Modbus RTU (9600/8N1)
▼
acquisition_tab.py (AcquisitionTab)
│ 采集线程: 每 100ms 轮询读取 18 路保持寄存器
│ → 电压 = 寄存器值 / 1000
│
├──→ 数据队列 (deque maxlen=1000)
│ │ UI 更新定时器: 每 10ms 追加到波形图
│ │ 存储线程: 每 100ms 批量写入 SQLite
│ ▼
│ voltage_data.db / voltage_data 表
│
└──→ 事件检测线程: 超阈值比较 → 记录事件记录
6.3.2 NTC 温度-电压模拟数据流
NTC.xlsx (电阻-温度曲线)
│ 读入 pandas DataFrame
▼
NTCConverter
│ R(T) = lookup(curve, temp)
│ V_out = 5.0 * R(T) / (R_pullup + R(T))
│ 缓存: voltage_cache[-50..150°C] 预先计算
│
├── 当前温度 → 期望电压查询
│
└── NTC.json
│ 引擎写入 target_temp / target_slope
▼
NTC 模拟器线程
│ 读取 NTC.json → 更新 NTCConverter → 计算输出电压
│ 通过 HK 串口模块 (Modbus) 输出模拟电压
▼
DAM-3058 采集该电压 → 形成闭环
6.3.3 联动控制数据流(核心闭环)
┌──────── 联动控制周期 (100ms) ────────────────────────┐
│ │
│ ① 存活检测 │
│ NTC.json._heartbeat 时间戳 vs 当前时间 │
│ voltage_data.db 最新记录时间戳 vs 当前时间 │
│ → 任一超时(>10s)则 AUTO_STOP │
│ │
│ ② 读取当前状态 │
│ 电压值 ← voltage_data.db 最新一行 (18 通道) │
│ NTC 状态 ← NTC.json (temps, curves, slopes, ...) │
│ 阈值配置 ← config.json │
│ │
│ ③ 逐通道偏差计算 (6个 NTC 通道) │
│ ┌─ 期望电压 = NTCConverter.temp2voltage(设温) │
│ │ 实际电压 = voltages[绑定电压通道] │
│ │ 偏差 = 实际电压 - 期望电压 │
│ └─ 容差 = channel_mapping.tolerance │
│ │
│ ④ 偏差分级 (DeviationChecker) │
│ |偏差| ≤ 容差 → normal (计数器归零) │
│ 容差 < |偏差| ≤ 0.5V → compensate │
│ |偏差| > 0.5V → hw_fault (报警, 不动作) │
│ │
│ ⑤ 补偿执行 (Compensator) — compensate 状态 │
│ 补偿电压 = -偏差 × 0.5 (阻尼) │
│ 钳位: ±0.2V/周期 │
│ 补偿电压 → 换算目标温度 → 写入 NTC.json │
│ 重试 > 10 次 → 停止补偿, 标记 LIMIT │
│ │
│ ⑥ 斜率保护 (SlopeGuard) — 超阈值时 │
│ 实际电压 > 阈值 → 斜率 × 0.5 │
│ 降斜率后仍连续上升 3 周期 → 再次 × 0.5 │
│ 电压回到阈值以下连续 5 周期 → 恢复原始斜率 │
│ │
│ ⑦ 自动斜坡 (RampDriver) — auto_run 通道 │
│ 新温度 = 当前温度 + 斜率/60 × 0.1 │
│ 达到高/低温限值 → 停止升温/降温, 标记 LIMIT │
│ │
│ ⑧ 状态快照写入 link_run_state 表 │
│ 推送 UI (StatusDashboard 实时刷新) │
│ │
└────────────────────────────────────────────────────────┘
6.4 完整工作流(端到端)
用户操作流程:
1. 硬件准备
├── 连接 DAM-3058 电压采集模块 (RS-485/USB)
├── 连接 HK 系列串口输出模块 (RS-232/USB)
└── 准备好 NTC.xlsx 曲线数据
2. 启动系统 (python -m auto_coordinator.app)
├── 自动运行 migration_v1.sql 建表
├── 加载 NTC 曲线
├── 加载 NTC.json 恢复上次状态
└── 加载 config.json 恢复阈值设置
3. 配置通道
├── 进入"电压采集"标签页 → 连接串口 → 开始采样
├── 进入"NTC模拟"标签页 → 打开串口 → 配置参数
└── 进入"通道绑定"标签页 → 绑定 NTC→电压通道 → 保存
4. 启动联动引擎 (点"启动")
├── 存活检测: 确认两个上位机在线
├── 通道检查: 确认已配置绑定
└── 启动控制循环线程
5. 运行中
├── 状态看板实时刷新 6 通道状态
├── 事件日志记录补偿/故障/保护事件
├── 可操作:
│ ├── 暂停/恢复引擎
│ ├── 调整 NTC 参数 (温度/斜率/限幅)
│ ├── 切换通道自动模式
│ └── 手动修改阈值
└── 自动保护:
├── 斜率保护 (电压超限自动降斜率)
├── 硬件故障报警 (>0.5V 大偏差)
└── 离线自动停止
6. 结束运行
├── 点击"停止" → 复位所有输出
├── 关闭窗口 → 自动保存配置
└── 日志/flush 写入数据库
7. 配置文件说明
7.1 NTC.xlsx
NTC 热敏电阻曲线数据。工作表名为曲线名称,每个工作表包含两列:温度(°C) 和 阻值(kΩ)。
7.2 NTC.json
NTC 模拟器配置文件,引擎通过此文件与 NTC 模拟器交互。关键字段:
{
"ntc_temps": [25.0, 25.0, ...], // 6通道当前温度
"ntc_curves": ["10k", "10k", ...], // 6通道曲线名称
"slope": [5.0, 5.0, ...], // 6通道斜率(°C/min)
"auto_run": [false, ...], // 6通道自动模式
"limit_temp_high": [100, ...], // 6通道温度上限
"limit_temp_low": [-50, ...], // 6通道温度下限
"pullup_resistors":[10.0, ...], // 6通道上拉电阻(kΩ)
"_external_command":{}, // 引擎命令区
"_heartbeat": {...}, // 心跳时间戳
"_mode": "standalone" // 运行模式
}
7.3 auto_coordinator/config.json
引擎运行参数(未被 app.py 载入时的默认值):
{
"control_interval_ms": 100, // 控制周期(ms)
"max_deviation_hw_v": 0.5, // 硬件故障判定阈值(V)
"compensation_damping": 0.5, // 补偿阻尼系数
"compensation_max_per_cycle_v": 0.2, // 单周期最大补偿量(V)
"compensation_retry_max": 10, // 最大补偿重试次数
"slope_reduce_default": 0.5, // 默认斜率降幅系数
"slope_restore_cycles": 5, // 斜率恢复所需稳定周期数
"alive_timeout_s": 10.0, // 上位机存活超时(s)
"state_retention_days": 7, // 运行状态数据保留天数
"log_level": "INFO" // 日志级别
}
7.4 voltage_data.db
SQLite 数据库,包含以下关键表:
| 表名 | 用途 |
|---|---|
voltage_data |
18通道电压采集原始数据 |
channel_mapping |
NTC与电压通道的绑定关系 |
link_events |
联动事件日志 |
link_run_state |
运行状态快照记录 |
8. 架构说明
8.1 模块清单
jiaohu/
├── 1.py # 电压采集上位机(独立程序)
├── NTC.py # NTC 后端模块(曲线加载/转换/串口)
├── NTC.xlsx # NTC 热敏电阻曲线数据
├── NTC.json # NTC 模拟器配置文件
├── config.json # 电压采集配置
├── voltage_data.db # SQLite 数据库
├── run_coordinator.bat # 联动引擎启动脚本
│
├── auto_coordinator/
│ ├── app.py # 主窗口(QMainWindow,5标签页)
│ ├── engine.py # 联动调度引擎(核心控制循环)
│ ├── data_reader.py # 统一数据读取层(含 NTCConverter)
│ ├── deviation_checker.py # 偏差分级判定器
│ ├── compensator.py # 自动补偿器
│ ├── slope_guard.py # 斜率卫士(保护/恢复)
│ ├── link_logger.py # 联动日志记录器
│ ├── ntc_json_writer.py # NTC.json 原子写入器
│ ├── migration_v1.sql # 数据库建表迁移脚本
│ ├── config.json # 引擎默认运行参数
│ ├── styles/
│ │ └── theme.qss # 界面 QSS 样式主题
│ └── widgets/
│ ├── acquisition_tab.py # 电压采集标签页 (QWidget)
│ ├── ntc_sim_tab.py # NTC 模拟标签页 (QWidget)
│ ├── bind_tab.py # 通道绑定标签页
│ ├── dashboard_tab.py # 状态看板标签页
│ └── log_tab.py # 事件日志标签页
│
└── tests/
├── test_deviation_checker.py # 偏差判定器测试
├── test_compensator.py # 补偿器测试
├── test_slope_guard.py # 斜率卫士测试
├── test_ramp_driver.py # 斜坡驱动器测试
├── test_ntc_json_writer.py # JSON 写入器测试
├── test_link_logger.py # 日志器测试
└── test_data_reader.py # 数据读取器测试 (33个用例)
8.2 模块间通信
┌─────────────────┐ JSON心跳 ┌─────────────────┐
│ NTC 模拟器 │◄────────────────►│ 联动调度引擎 │
│ (NTCSimTab) │ _external_command│ (AutoCoordinator)│
│ + HKModule串口 │ temp/slope命令 │ 偏差→补偿→保护 │
└────────┬─────────┘ └────────┬─────────┘
│ │
│ 串口输出 │ SQLite读写
▼ ▼
物理电压模块 voltage_data.db
│ ▲
│ Modbus RTU │ 电压数据
▼ │
┌─────────────────┐ │
│ 电压采集上位机 │────────────────────────────┘
│ (AcquisitionTab)│ SQLite 写入
└─────────────────┘
引擎通过文件(JSON + SQLite)与两个上位机通信,无需直接进程间通信,架构简单可靠。
9. 常见问题
Q: 启动引擎时报"NTC.py 或 1.py 离线"
A: 需要先在界面的"电压采集"标签页连接设备并开始采样,在"NTC模拟"标签页打开串口。两个上位机都处于运行状态后,引擎才能启动。
Q: 启动失败显示"未配置通道绑定"
A: 进入"通道绑定"标签页,为每个 NTC 通道选择对应电压通道,设置容差,保存配置后再启动。
Q: 电压输出值偏差过大
A: 检查:
- 通道绑定是否正确
- NTC 曲线数据是否与实际热敏电阻匹配
- 上拉电阻值是否与硬件一致
- 容差设置是否过小
Q: 温度变化不响应
A: 确认 NTC 模拟器串口已打开,且串口号与硬件一致。
Q: 如何更换 NTC 曲线
A: 用 Excel 编辑 NTC.xlsx,添加新的工作表(曲线名自定),然后在 NTC 模拟界面下拉切换曲线。
Q: 数据库过大
A: 可定期使用"事件日志"标签页的"清除日志"按钮清理旧记录,或在 SQLite 中手动执行 DELETE FROM link_events WHERE timestamp < 'xxx'。
10. 版本信息
- 版本:v1.0
- 技术栈:Python 3.7+ / PyQt5 / pyqtgraph / Modbus RTU / SQLite
- 许可证:内部使用

浙公网安备 33010602011771号