虚拟 IO
VirtualDriver 提供纯软件模拟的 IO 驱动,无需任何物理硬件即可运行 PLC 程序。适用于程序开发、逻辑验证和离线调试。
工作原理
VirtualDriver 实现 IHardwareDriver 接口,对 PLC 扫描引擎而言与真实硬件驱动完全等价。切换到虚拟模式只需替换驱动实例,PLC 程序无需修改。
配置
var virtualIO = new VirtualDriver();
virtualIO.Configure(new VirtualIOConfig {
DigitalInputCount = 64, // 64 点 DI
DigitalOutputCount = 64, // 64 点 DO
AnalogInputCount = 16, // 16 通道 AI
AnalogOutputCount = 8 // 8 通道 AO
});
信号操作
手动操作
通过 IO 状态面板直接操作虚拟信号:
| 操作 | 说明 |
|---|---|
| 点击 DI 灯 | 切换 ON/OFF 状态 |
| 拖拽 AI 滑块 | 设置模拟量数值 |
| 右键 → 强制 | 锁定信号值,不被程序覆盖 |
| 右键 → 脉冲 | 产生一个扫描周期的脉冲 |
脚本驱动
通过 SCL 程序或外部程序批量设置虚拟 IO:
(* 模拟工件到位信号序列 *)
%IX0.0 := TRUE; (* 传感器1触发 *)
WAIT(200); (* 等待200ms *)
%IX0.1 := TRUE; (* 传感器2触发 *)
WAIT(100);
%IX0.0 := FALSE; (* 传感器1复位 *)
仿真联动
虚拟 IO 可与仿真系统的物理模型联动:
- 夹爪 DO → GripperSimulator → 夹爪 DI 反馈
- 传送带 AO → ConveyorSimulator → 光电 DI 触发
- 机床门 DO → 定时器 → 加工完成 DI
VirtualDriver (HAL 层) 和 VirtualIOSource (仿真层) 功能相似但层级不同。VirtualDriver 是 HAL 硬件抽象层的一个驱动实现,直接参与 IOMerge/IODistribute。VirtualIOSource 是仿真系统的组件,通过 VariableBus 间接提供 IO 数据。在纯仿真模式下两者协同工作。
输出回读
虚拟模式下,DO/AO 输出值可以直接回读为 DI/AI 输入,用于简单的自环测试:
virtualIO.EnableLoopback = true;
// 设置后:
// %QX0.0 的输出值自动映射到 %IX0.0
// %QW0 的输出值自动映射到 %IW0
信号录制
虚拟 IO 支持录制信号变化历史,用于事后分析:
| 录制内容 | 说明 |
|---|---|
| 时间戳 | 精确到扫描周期 |
| 信号名称 | IO 地址 + 变量名 |
| 变化值 | 变化前后的值 |
| 触发源 | PLC 程序 / 手动 / 脚本 |
典型应用
- 程序开发 — 无硬件环境下编写和调试 PLC 程序
- 逻辑验证 — 验证 IO 联锁逻辑的正确性
- 回归测试 — 使用固定信号序列验证程序修改未引入错误
- 客户演示 — 展示系统功能而无需携带硬件
仿真场景配置
IDE 提供仿真场景编辑器, 用 YAML 描述信号序列:
scenario: 抽板机完整循环
duration: 30s
signals:
# 0s~1s: 初始化
- at: 0.0
set: "%IX0.0"
value: false
- at: 0.5
set: "%IW100"
value: 25.0 # 温度 25°C
# 1s: 启动按钮按下
- at: 1.0
pulse: "%IX1.0"
duration: 100ms
# 2s~10s: 抽板动作序列
- at: 2.0
wait: "%QX2.0" # 等待气缸伸出信号
timeout: 5s
- at: 2.5
set: "%IX0.1"
value: true # 到位传感器
# 每秒增加温度
- from: 0.0
to: 30.0
step: 1.0
set: "%IW100"
value: "{{ 25 + time * 0.5 }}"
加载场景后点"运行", IDE 自动按时间线驱动虚拟 IO。
随机信号
模拟生产中的随机波动:
- at: 0.0
set: "%IW200"
random:
distribution: normal
mean: 50.0
stddev: 2.0
updateInterval: 100ms
支持分布:
- uniform (均匀)
- normal (正态)
- lognormal (对数正态)
- custom (自定义曲线)
物理仿真集成
模拟简单物理系统 (如热传导、贮罐液位):
physics:
- type: integrator
input: "%QW100" # 加热功率
output: "%IW101" # 温度
gain: 0.01
- type: firstOrder
input: "%QW200" # 阀门开度
output: "%IW201" # 液位
timeConstant: 10s
- type: delay
input: "%QW300" # 控制输出
output: "%IW301" # 响应
delay: 500ms
适合闭环控制算法 (PID / 预测控制) 的离线调参。
与 VariableBus 集成
Darra 的 VariableBus 是统一仿真数据总线, 连接:
- VirtualIO (HAL 层)
- 物理模型 (热/流体/机械)
- 机器人运动学
- HMI 显示
三者通过 VariableBus 共享数据, 仿真时自然联动。详见仿真架构文档。
录制与回放
运行真实系统时录制信号, 离线回放用于问题重现:
recorder.Start(signals: new[] { "%IX0.*", "%QW*" });
// ... 让系统运行一段
recorder.Stop();
recorder.SaveAs("bug_repro.sim");
// 在开发机上
virtualIO.LoadRecording("bug_repro.sim");
virtualIO.Replay(speed: 0.5); // 慢放 0.5 倍
支持:
- 全速 / 慢放 / 快进
- 断点 (到某时刻暂停, 手工检查)
- 逐周期步进
混合仿真
真实硬件 + 虚拟 IO 混合:
- 真实 EtherCAT 伺服轴 (真电机真编码器)
- 虚拟的限位传感器和操作面板
- 真实 HMI 触摸屏
场景: 机器人本体是真实的, 周边的产线状态用虚拟代替, 用于独立验证机器人程序。
性能
VirtualDriver 的 Read/Write 是内存操作, 耗时 < 1μs, 不影响 PLC 周期。单机可同时驱动 10,000+ 虚拟点位无压力。
切换策略
项目配置决定用虚拟还是真实 IO:
项目设置 → 部署目标:
[ ] 真实硬件 (生产)
[x] 虚拟 (仿真)
[ ] 混合 (见混合仿真)
切换时 PLC 代码完全不改, 只改部署目标后重新下载。
排错
| 症状 | 处理 |
|---|---|
| 仿真运行但 IO 值不变 | 检查场景脚本的信号地址 |
| 物理模型发散 | 增益或时间常数不合理, 减小步长 |
| 录制回放比原时序慢 | 回放引擎被重型场景拖累, 降速或简化 |
| 强制信号和场景冲突 | 强制值优先, 场景被忽略 |
| 随机信号不重现 | 设随机种子 random.seed: 12345 |