Bladeren bron

docs: 更新梯形图与注释功能说明

main
suyu 1 maand geleden
bovenliggende
commit
e03a687406
4 gewijzigde bestanden met toevoegingen van 105 en 20 verwijderingen
  1. +23
    -4
      docs/ai/handoff.md
  2. +15
    -10
      docs/architecture.md
  3. +62
    -3
      docs/工程格式说明.md
  4. +5
    -3
      docs/开发顺序.md

+ 23
- 4
docs/ai/handoff.md Bestand weergeven

@@ -13,7 +13,7 @@
- HMI 和梯形图直接配置 M/D 地址,不依赖预先创建的数据点
- `ActiveRegisterRepository` 在离线虚拟仓库与 PLC 缓存仓库之间切换
- `PlcCommunicationService` 使用 Qt SerialBus 异步连接、轮询和单点写入,UI 不阻塞
- 真机连接收集 HMI 和梯形图实际引用地址,按 M/D 分区并合并相邻地址读取
- 真机连接收集 HMI、报警定义和梯形图实际引用地址,按 M/D 分区并合并相邻地址读取
- 真机模式要求首次读取完成,不复制离线值,不运行 PC 软件逻辑执行器
- 通信错误停止轮询并保留最后一次有效缓存,状态栏和日志显示错误
- 通信故障立即撤销当前连接的首读资格;真机运行中发生故障会自动返回编辑态,重新进入真机前必须重新连接并完成新一轮首读
@@ -28,14 +28,20 @@
- 主窗口使用会话态当前页面 ID、当前逻辑 ID,所有编辑入口不再固定操作第一项
- 工程持久化初始 HMI 页面;运行态由 `HmiNavigationService` 从初始页启动并处理本地 PageJump 导航
- HMI 已开放不绑定寄存器的 `Label` 和独立 `PageJump` 创建入口,属性区按控件类型显示绑定、按钮操作或目标页面
- HMI 已增加 AlarmList 和报警配置入口,支持 M ON、D 高限、D 低限,统一显示当前报警和确认状态;运行态无报警时隐藏,报警恢复后立即移除
- 离线执行器按工程顺序扫描所有启用逻辑,禁用草稿不阻止运行;轨迹按逻辑 ID 隔离,运行工作台可切换当前投影
- 梯形图已支持上升沿、下降沿、T 常开/常闭触点和非保持 TON;边沿只输出一个扫描周期,TON 按 `steady_clock` 计算实际 ET
- T 是 `T0~T4000` 的离线仿真内部资源,不读写 M/D,也不进入 Modbus 轮询;同一 T 只允许一个已启用 TON 驱动
- 工程已支持 M/D 地址注释和 `LadderRung` 网络注释;地址注释只保存地址与文本,不混入当前值和引用状态
- HMI 运行按钮已区分悬停、按下、释放和禁止写入外观,运行态不再显示编辑选中框,可写按钮使用手型光标
- PLC 轮询集合已扩展为 HMI、梯形图和自由监控地址的并集,连接后可动态增删监控地址
- PLC 轮询集合已扩展为 HMI、报警定义、梯形图和自由监控地址的并集,连接后可动态增删监控地址
- 已在真实 `COM3 / 9600 / 8E1 / 站号 1` 上完成只读联机验证,项目通信服务可完成 M/D 首次读取并进入真机运行前置状态

## 关键决策

- 工程格式继续使用 `1.0`,当前文件只保存 HMI 和梯形图表达式树,不保留 `dataPoints` 结构及兼容代码
- 工程格式继续使用 `1.0`,当前文件保存 HMI、报警定义和梯形图表达式树,不保留 `dataPoints` 结构及兼容代码
- 工程 `1.0` 直接要求 `alarmDefinitions`,不为缺少该字段的旧草稿增加迁移或默认值
- AlarmList 不直接保存报警逻辑,项目级 `AlarmService` 统一管理运行状态;当前不设置提示、警告、故障等级
- 当前 `1.0` 直接要求 `initialHmiPageId` 和 PageJump 的 `targetPageId`,开发阶段不为同版本旧草稿补默认值或迁移分支
- 页面跳转保存目标页面稳定 ID,不保存名称或数组索引;编辑器当前页面和当前逻辑属于会话状态,不写入工程
- 按钮操作是工程 `1.0` 的必填字段,不兼容或迁移缺少该字段的旧按钮数据
@@ -44,12 +50,14 @@
- 网格仅作为编辑投影,不进入工程格式;服务层把连续范围操作转换为规范化表达式树
- 条件节点继续使用 `std::variant` 的独立配置类型,不向通用节点添加无关字段
- HMI、梯形图和通信共享 `M0~M4000`、`D0~D4000` 地址范围
- 已删除统一数据点表、主窗口数据点 Dock 和属性区数据点下拉框;软元件注释功能待后续按信捷业务单独设计
- 已删除统一数据点表、主窗口数据点 Dock 和属性区数据点下拉框;M/D 注释作为独立的工程级地址元数据实现
- PLC 读写使用从 `0` 开始的原始 Modbus 地址
- HMI 写请求不乐观修改 PLC 缓存,由下一次轮询确认真实值
- 真机运行时 PLC 内部程序是控制源,软件逻辑执行器保持停止
- 真机运行不显示本地梯形图导通轨迹,避免把本地工程误表示为 PLC 内部程序的真实执行状态
- 自由监控表属于当前调试会话,不进入工程 `1.0` JSON,不重新引入数据点表
- 工程 `1.0` 直接要求顶层 `registerComments` 和每个网络的 `comment` 字段,不增加旧工程迁移或缺省兼容
- 50 ms Qt 定时器只调度离线扫描;每个 TON 不创建独立 Qt 定时器,真机模式继续停止整个软件逻辑执行器

## 自动化验证

@@ -64,9 +72,12 @@
- `plc_runtime_tests`
- `main_window_tests`
- `register_monitor_service_tests`
- `alarm_service_tests`

`main_window_tests` 还覆盖 PLC 配置参数往返、独立配置弹窗入口,以及主窗口不再内嵌串口参数控件。

本轮边沿、TON 和注释实现增加了:上下沿一次扫描脉冲、不同逻辑同名边沿状态隔离、TON 到时与断开复位、多个 T 独立计时、网络顺序可见性、运行重启状态清理、T 引用完整性、M/D 与网络注释 JSON 往返、严格新字段缺失失败,以及 T 和纯注释地址不进入 PLC 轮询集合的覆盖。

本轮多页面和多逻辑实现增加了领域、服务、存储和主窗口集成覆盖:初始页约束、页面引用删除保护、页面/逻辑名称唯一性和顺序、禁用草稿逻辑、多逻辑扫描与轨迹隔离、严格 JSON `1.0` 必填字段、工程树选择切换、Label/PageJump 属性可见性、运行态页面跳转和逻辑轨迹选择。

2026-08-13 真机排查发现 `QModbusRtuSerialMaster::connectDevice()` 在当前 Windows
@@ -141,6 +152,14 @@ HMI 图元现已分离编辑选择与运行输入状态。运行按钮悬停时
后出现编辑选中框。主窗口测试使用真实鼠标按下和释放事件验证瞬时按钮写入、视觉状态切换、
手型光标、禁止写入和无运行选中框。

本轮新增最小报警闭环。项目级报警定义支持 M 位为 ON、D 值大于等于阈值、D 值小于等于
阈值;AlarmService 只维护当前报警的发生时间和确认状态,报警恢复后立即移除,多个 AlarmList 共享状态。
报警配置和列表展示分别由独立 Qt Designer 对话框与 HMI 图元完成,主窗口只协调服务。报警
地址已进入 PLC 聚合轮询。工程版本保持 `1.0`,`alarmDefinitions` 为必填字段,不增加兼容分支。

2026-08-17 使用 `COM3 / 9600 / 8E1 / 站号 1` 完成报警功能后的真机只读冒烟,成功读取
`M0~M2 = OFF`、`D0 = 0`,测试结束后正常关闭串口。本次没有执行任何 PLC 写操作。

## 待完成事项

1. 在 PLC STOP 状态确认 COM2 参数和 RS-485 A/B 接线


+ 15
- 10
docs/architecture.md Bestand weergeven

@@ -46,16 +46,17 @@ main.cpp -> UI + Services + Infrastructure
| `register_repository.*` | 定义 M/D 统一读写接口和离线内存实现 |
| `active_register_repository.*` | 在虚拟仓库与 PLC 缓存仓库之间切换当前数据源 |
| `register_monitor_model.*` | 保存当前调试会话的自由监控 M/D 地址集合 |
| `alarm_model.*` | 定义项目级 M ON、D 高限和 D 低限报警条件 |
| `hmi_model.*` | 定义页面、控件、布局和寄存器绑定 |
| `control_logic_model.*` | 定义梯形图表达式树、条件节点和输出线圈 |
| `project_model.*` | 聚合 HMI 页面和控制逻辑并执行工程校验 |
| `control_logic_model.*` | 定义梯形图表达式树、边沿/触点/比较/TON 节点和输出线圈 |
| `project_model.*` | 聚合 HMI 页面、报警定义和控制逻辑并执行工程校验 |
| `runtime_state.*` | 定义编辑、离线运行和真机运行状态机 |

工程文件格式保持 `1.0`。当前 `1.0` 直接保存有序 `hmiPages`、`initialHmiPageId`、有序 `controlLogics` 和梯形图表达式树,不读取其他结构,也不包含迁移和兼容代码。加载必须先完成 JSON 解析、版本检查和领域校验,成功后才能替换当前工程;保存使用原子提交。完整字段定义见 `docs/工程格式说明.md`。
工程文件格式保持 `1.0`。当前 `1.0` 直接保存有序 `hmiPages`、`initialHmiPageId`、有序 `alarmDefinitions`、工程级 `registerComments`、有序 `controlLogics` 和梯形图表达式树,不读取其他结构,也不包含迁移和兼容代码。加载必须先完成 JSON 解析、版本检查和领域校验,成功后才能替换当前工程;保存使用原子提交。完整字段定义见 `docs/工程格式说明.md`。

`HmiPage.id` 和 `ControlLogic.id` 是稳定内部标识,名称可修改,数组顺序分别决定工程树页面顺序和离线逻辑扫描顺序。`MainWindow` 保存 `current_hmi_page_id_` 与 `current_logic_id_` 作为编辑会话选择,它们不进入 JSON。`Project.initialHmiPageId` 是运行态每次启动 HMI 时使用的持久化初始页,与编辑器当前正在查看的页面相互独立。

`Project::validate()` 允许未绑定控件、待配置节点和未完成网络作为编辑草稿保存。`Project::validateForRunning()` 额外拒绝未绑定 HMI、待配置节点、空条件和缺少输出的网络。
`Project::validate()` 允许未绑定控件、待配置节点和未完成网络作为编辑草稿保存。`Project::validateForRunning()` 额外拒绝未绑定 HMI、待配置节点、空条件和缺少输出的网络,并检查已启用逻辑中的 T 触点必须有唯一的 TON 驱动

HMI 按钮操作作为工程 `1.0` 的强类型字段保存,支持 `置 ON`、`置 OFF`、`取反` 和
`瞬时 ON`。新建按钮默认使用瞬时 ON;按钮按下和释放事件由 UI 转交运行服务解释,UI
@@ -63,6 +64,8 @@ HMI 按钮操作作为工程 `1.0` 的强类型字段保存,支持 `置 ON`、

`Label` 是不绑定 M/D 的固定文本控件。`PageJump` 是独立控件,使用强类型 `targetPageId` 引用目标页面稳定 ID,同样不绑定 M/D。编辑态点击 PageJump 只执行选择和拖动;离线或真机运行态点击后由 `HmiNavigationService` 在本地切换运行页面,不发出 PLC 写请求,因此 PLC 通信写权限不可用时也不影响页面导航。被 PageJump 引用的页面不能删除,初始页必须先切换后才能删除,工程至少保留一个页面。

`AlarmList` 是不绑定单个寄存器的运行状态投影。项目级 `AlarmDefinition` 只支持 M 位为 ON、D 值大于等于阈值和 D 值小于等于阈值三种条件,不设置提示、警告、故障等级。`AlarmEditorService` 负责定义增删改,`AlarmService` 统一读取活动寄存器仓库并维护当前报警的发生时间和确认状态,所有页面上的 AlarmList 共享这份状态。报警条件恢复后立即删除对应运行记录;运行态没有报警时 AlarmList 隐藏,出现报警时显示并置顶。返回编辑态时清空运行记录,工程 JSON 只保存报警定义。

## 结构化梯形图

网络条件采用递归表达式:
@@ -88,23 +91,25 @@ Parallel

`LogicEditorWidget` 将表达式树投影到固定行列网格,串联节点横向占列,并联分支纵向占行,所有连接只使用水平线和竖线。用户只选择画布中可见的节点:单击定位当前节点,橡皮框或多选连续节点后可直接建立并联支路。内部 `Series / Parallel` 容器不作为可选 UI 对象暴露。网格是编辑投影,不持久化自由线段,因此不会产生悬空线、环路和多输出路径。

工具栏中的常开、常闭和比较条件在没有选择时追加到当前网络末尾,选中一个条件节点时插入到该节点后。并联支路按钮默认建立常开触点,下拉菜单可选择常闭触点或比较条件。新增节点保持待配置状态,并自动选中供属性区继续编辑。
工具栏中的常开、常闭、上升沿、下降沿、T 触点和比较条件在没有选择时追加到当前网络末尾,选中一个条件节点时插入到该节点后。并联支路按钮默认建立常开触点,下拉菜单可选择常闭、边沿、T 触点或比较条件。新增节点保持待配置状态,并自动选中供属性区继续编辑。

条件节点使用 `std::variant` 保存独立配置类型,当前包含 M 常开/常闭触点和 D 值与常量比较。输出支持普通、置位和复位 M 线圈。新增节点类型时应增加独立配置类型及校验、存储和执行分支,不能向通用节点堆叠无关字段。
条件节点使用 `std::variant` 保存独立配置类型,当前包含 M 常开/常闭触点、M 上升沿/下降沿触点、T 常开/常闭触点和 D 值与常量比较。输出支持普通、置位、复位 M 线圈和非保持 TON。边沿节点在每个扫描周期比较当前 M 值与该逻辑节点自己的上一扫描值,只产生一个扫描周期的脉冲。T 地址是 `T0~T4000` 的离线资源,不是 M/D 地址。新增节点类型时应增加独立配置类型及校验、存储和执行分支,不能向通用节点堆叠无关字段。

## 执行与运行反馈

`SoftwareLogicExecutor` 按 `controlLogics` 数组顺序扫描所有已启用逻辑,再按网络顺序递归求值 `Node / Series / Parallel`。禁用逻辑仅保留结构校验,未完成的禁用草稿不会阻止离线运行。普通线圈每周期写入网络结果,置位和复位线圈只在网络成立时写入;前面逻辑或网络的写入对后面逻辑和网络在同一扫描周期立即可见。

上升沿和下降沿是标准的一次扫描脉冲,运行状态按逻辑 ID 和节点 ID 隔离。TON 是正常非保持接通延时:输入接通后记录 `steady_clock` 起点,`ET` 使用实际经过的毫秒数,达到 `PT` 后 `Q` 为真;输入断开立即清零 `ET/Q`。TON 的输出状态保存在离线执行器的 T 资源表中,T 触点只读取对应 TON 的 `Q`。软件不为每个 TON 创建 Qt `QTimer`,现有 50 ms `QTimer` 只负责扫描调度,因此不会与 Qt 事件循环或 PLC 轮询形成额外定时器线程。

每次扫描生成按逻辑 ID 分区的 `LogicTraceSnapshot`,记录节点、表达式、网络和线圈的导通状态,避免不同逻辑中重复的 `rung-1`、`contact-1` 相互覆盖。运行工作台的逻辑下拉框只切换当前轨迹投影,所有已启用逻辑仍持续执行。逻辑画布以绿色显示导通节点和路径;执行错误携带逻辑、网络和节点上下文,画布选择并以红色突出故障位置。

`OfflineSimulationService` 以 50 ms 目标周期驱动扫描,启动时复制逻辑快照并清空虚拟 M/D。故障后停止扫描并保留最终寄存器值,HMI 可继续显示但禁止写入。该周期不提供硬实时保证。
`OfflineSimulationService` 以 50 ms 目标周期驱动扫描,启动时复制逻辑快照、清空虚拟 M/D 并重置边沿和 T 运行状态。故障或停止后清理这些运行状态;重新启动不会继承上次边沿历史或 TON 的 ET/Q。该周期只提供调度精度,不提供硬实时保证。

## M/D 地址使用

HMI 控件和梯形图节点直接绑定 `M0~M4000`、`D0~D4000` 地址,不要求预先创建数据点。地址是程序和通信的真实标识,属性面板只编辑区域与地址。

软元件注释、网络注释和命令语视图不属于当前实现。后续如增加注释,应把地址级软元件注释和网络级说明分开建模,不能重新引入“名称、注释、当前值、引用位置”混合的数据点表。
工程级 `registerComments` 只保存 M/D 地址和注释文本,作为地址元数据供编辑器和注释对话框使用,不保存当前值、引用位置或缓存状态,也不会因为存在注释而加入 PLC 轮询。`LadderRung.comment` 保存单个网络的说明文本。两者在 JSON 中分开建模,不能重新引入混合“名称、注释、当前值、引用位置”的数据点表。

## 自由监控与运行工作台

@@ -134,8 +139,8 @@ HMI 控件和梯形图节点直接绑定 `M0~M4000`、`D0~D4000` 地址,不要
- 真机运行使用 `PlcRegisterRepository` 的最近一次有效缓存

`PlcCommunicationService` 使用 `QModbusRtuSerialMaster` 异步连接、读取和写入。轮询集合由
HMI 引用、梯形图引用和自由监控地址合并而成,去重后按区域合并相邻地址。M 使用线圈,D
使用保持寄存器;所有 Modbus 地址均为从 `0` 开始的原始地址。
HMI 引用、报警定义、梯形图中的 M/D 引用和自由监控地址合并而成,去重后按区域合并相邻地址。
T 触点、TON 和工程级注释不会进入该集合。M 使用线圈,D 使用保持寄存器;所有 Modbus 地址均为从 `0` 开始的原始地址。

PLC 连接后可以动态增删自由监控地址。存在读取请求时,新的轮询集合在当前响应处理完成后
应用,旧响应仍按发出时的读取块解析。连接级首次读取完成后,动态增加地址不会撤销真机


+ 62
- 3
docs/工程格式说明.md Bestand weergeven

@@ -13,11 +13,13 @@
"name": "包装线",
"hmiPages": [],
"initialHmiPageId": "",
"alarmDefinitions": [],
"registerComments": [],
"controlLogics": []
}
```

所有顶层字段必填。空工程允许 `hmiPages` 和 `controlLogics` 为空,此时 `initialHmiPageId` 必须为空。存在页面时,`initialHmiPageId` 必须引用 `hmiPages` 中的页面 ID。
所有顶层字段必填。空工程允许 `hmiPages`、`alarmDefinitions`、`registerComments` 和 `controlLogics` 为空,此时 `initialHmiPageId` 必须为空。存在页面时,`initialHmiPageId` 必须引用 `hmiPages` 中的页面 ID。

`hmiPages` 与 `controlLogics` 都是有序数组。页面顺序用于工程树显示;控制逻辑顺序是离线扫描顺序。对象 ID 稳定且唯一,名称可修改且在同类对象中唯一。

@@ -45,6 +47,7 @@
| `numericInput` | D 地址或 `null` 草稿 | 无 |
| `label` | 必须为 `null` | 无 |
| `pageJump` | 必须为 `null` | `targetPageId` |
| `alarmList` | 必须为 `null` | 无 |

按钮操作字符串为 `setOn`、`setOff`、`toggle` 或 `momentaryOn`。PageJump 使用目标页面稳定 ID,不使用名称或数组位置:

@@ -62,6 +65,53 @@

编辑草稿允许 `targetPageId` 为空字符串,但进入运行态前必须配置为现存页面 ID。任何页面被 PageJump 引用时不得删除。

AlarmList 只负责显示项目级当前报警,不保存独立触发逻辑,也不直接绑定单个寄存器。多个页面放置 AlarmList 时共享同一组当前报警和确认状态。运行态没有报警时控件隐藏;报警恢复后对应记录立即移除,最后一条报警恢复后控件再次隐藏。

## 报警定义

```json
{
"id": "alarm-1",
"address": {"area": "M", "index": 0},
"condition": "mOn",
"threshold": 0,
"message": "急停已按下"
}
```

`alarmDefinitions` 是项目级有序数组,报警 ID 必须唯一。触发条件只包含当前业务需要的三种:

| `condition` | 地址区域 | 触发规则 |
| --- | --- | --- |
| `mOn` | M | 位值为 ON |
| `dHigh` | D | 字值大于等于 `threshold` |
| `dLow` | D | 字值小于等于 `threshold` |

`threshold` 使用有符号 16 位范围;M 报警仍保留该必填字段但不参与判断。报警文本不能为空。发生时间、活动状态、确认状态和清除时间属于运行会话,不进入工程 JSON。

## 地址注释与网络注释

`registerComments` 是工程级 M/D 地址元数据数组。每个元素必须包含有效的 `address` 和非空 `text`,同一地址只能出现一次:

```json
{
"address": {"area": "M", "index": 0},
"text": "启动按钮"
}
```

注释不保存寄存器当前值,也不自动把地址加入 Modbus 轮询。网络注释属于 `LadderRung`,与网络 ID、名称、条件和输出并列保存:

```json
{
"id": "rung-1",
"name": "启动网络",
"comment": "启动按钮接通后延时启动",
"condition": null,
"output": null
}
```

## 控制逻辑

```json
@@ -75,10 +125,19 @@

`enabled` 决定离线执行器是否扫描该逻辑。所有启用逻辑按 `controlLogics` 数组顺序执行;禁用逻辑仍要求 ID、名称、网络和表达式结构合法,但允许保留未完成节点作为草稿。

网络、`Node / Series / Parallel` 条件表达式、触点、比较和线圈字段沿用当前结构化梯形图模型。网格坐标、画布连线和运行轨迹是 UI 或运行会话投影,不进入 JSON。
网络、`Node / Series / Parallel` 条件表达式、触点、边沿、T 触点、比较、线圈和 TON 字段沿用当前结构化梯形图模型。网格坐标、画布连线和运行轨迹是 UI 或运行会话投影,不进入 JSON。节点配置的类型和值域如下:

```json
{"type": "edgeContact", "address": {"area": "M", "index": 0}, "mode": "rising"}
{"type": "edgeContact", "address": {"area": "M", "index": 0}, "mode": "falling"}
{"type": "timerContact", "timer": {"index": 0}, "mode": "normallyOpen"}
{"type": "ton", "timer": {"index": 0}, "presetMs": 1000}
```

T 地址范围为 `0~4000`,TON `presetMs` 范围为 `1~86400000`。上升沿和下降沿是一次扫描脉冲;TON 是非保持接通延时,输入断开时 `ET/Q` 立即清零。T 不参与 Modbus,也不写入 M/D 仓库。

## 校验与读写

保存顺序为领域校验、JSON 序列化、`QSaveFile` 原子提交。加载顺序为 JSON 语法、`formatVersion`、必填字段和类型、领域关系校验,全部成功后才替换当前工程。

工程保存允许未绑定的寄存器控件和未完成梯形图草稿。进入离线运行还必须通过运行校验:所有 HMI 寄存器控件完成绑定、所有 PageJump 目标有效、所有启用逻辑完整;禁用草稿逻辑不阻止运行。
工程保存允许未绑定的寄存器控件和未完成梯形图草稿。进入离线运行还必须通过运行校验:所有 HMI 寄存器控件完成绑定、所有 PageJump 目标有效、所有报警定义合法、所有启用逻辑完整;禁用草稿逻辑不阻止运行。

+ 5
- 3
docs/开发顺序.md Bestand weergeven

@@ -59,8 +59,9 @@

- 使用 `Node / Series / Parallel` 表达式树建立梯形图逻辑模型,支持嵌套串并联关系。
- 支持节点前后串联插入、与节点并联、与整个支路并联、删除和输出线圈配置。
- 初版实现常开、常闭、普通线圈、置位/复位以及 D 值与常量比较。
- 定时器不属于当前原始需求范围,只有在后续需求明确时才新增对应配置和执行逻辑。
- 实现常开、常闭、上升沿、下降沿、T 触点、普通线圈、置位/复位、TON 以及 D 值与常量比较。
- 上升沿和下降沿按一次扫描脉冲执行;TON 使用离线执行器的 `steady_clock` 和 T 资源表,不为每个 TON 创建独立 Qt 定时器。
- M/D 注释作为工程级地址元数据保存,网络注释作为 `LadderRung` 字段保存,两者都不改变寄存器轮询行为。
- 新增节点类型时使用独立配置类型,不向通用节点结构持续堆叠无关字段。
- 编辑器只生成逻辑模型,不直接修改 HMI 或 PLC。
- 工程可包含多个有序控制逻辑,离线执行器按顺序扫描全部启用项,运行工作台只切换当前轨迹投影。
@@ -70,8 +71,9 @@

## 8. 实现离线仿真运行

- 实现虚拟 M/D 寄存器和固定周期的软件逻辑执行器。
- 实现虚拟 M/D 寄存器和固定周期的软件逻辑执行器,T 仅作为离线仿真内部资源
- 将 HMI、虚拟寄存器和控制逻辑形成完整闭环。
- 验证 TON 的接通延时、断开复位、多个 T 独立计时和网络顺序语义。
- 实现启动、停止、异常和当前运行状态反馈。
- 记录节点、支路和网络导通轨迹,在画布突出导通路径和故障节点。



Laden…
Annuleren
Opslaan