修改急停联动
This commit is contained in:
parent
76f9b8641b
commit
b10b321e7d
20
Docs/开发文档.md
20
Docs/开发文档.md
@ -81,9 +81,9 @@
|
|||||||
|
|
||||||
- 硬件连接:`PCI2312` 通过厂商 `PCI2312_64.dll` 以 P/Invoke 方式接入,使用 DI 通道读取急停状态,使用 DO 通道控制报警灯。
|
- 硬件连接:`PCI2312` 通过厂商 `PCI2312_64.dll` 以 P/Invoke 方式接入,使用 DI 通道读取急停状态,使用 DO 通道控制报警灯。
|
||||||
- 后台监控:`SafetyMonitorService.Start()` 在主窗口初始化后启动,按 `Devices:Pci2312:PollIntervalMs` 周期轮询急停输入。
|
- 后台监控:`SafetyMonitorService.Start()` 在主窗口初始化后启动,按 `Devices:Pci2312:PollIntervalMs` 周期轮询急停输入。
|
||||||
- 硬件急停:当配置的 DI 通道达到有效电平时,程序写入报警 DO,并依次执行 SSPC 全通道关断、电源输出关闭、负载输入关闭。
|
- 硬件急停:当配置的 DI 通道达到有效电平时,程序锁存硬件急停状态,写入报警 DO,并依次执行 SSPC 全通道关断、电源输出关闭、负载输入关闭。
|
||||||
- 软件急停:主窗口顶部“报警急停”按钮调用 `TriggerSoftwareEmergencyAsync()`,走同一套报警灯和设备关断链路。
|
- 软件急停:主窗口顶部“报警急停”按钮调用 `TriggerSoftwareEmergencyAsync()`,走同一套报警灯和设备关断链路;纯软件急停需要通过“状态重置”解除。
|
||||||
- 状态重置:报警灯点亮后按钮变为“状态重置”。若硬件急停 DI 仍有效,重置会被拒绝;DI 复位后才关闭报警输出并恢复监控状态。
|
- 状态重置与硬件解除:报警灯点亮后按钮变为“状态重置”。若硬件急停 DI 仍有效,手动重置会被拒绝;硬件急停曾触发后,DI 复位会自动关闭报警输出、清除硬件急停锁存和软件急停状态,并刷新 UI 回到“报警急停”。
|
||||||
|
|
||||||
控制链路如下:
|
控制链路如下:
|
||||||
|
|
||||||
@ -518,10 +518,16 @@ Timer(PollIntervalMs,代码中限制 50~10000ms)
|
|||||||
-> 自动连接 PCI2312(若启用 AutoConnect)
|
-> 自动连接 PCI2312(若启用 AutoConnect)
|
||||||
-> ReadInputAsync(EmergencyInputChannel)
|
-> ReadInputAsync(EmergencyInputChannel)
|
||||||
-> 按 EmergencyInputActiveHigh 解释有效电平
|
-> 按 EmergencyInputActiveHigh 解释有效电平
|
||||||
-> 触发 HandleEmergencyAsync()
|
-> DI 有效时锁存硬件急停并触发 HandleEmergencyAsync()
|
||||||
|
-> 硬件急停锁存后 DI 复位时触发 ClearHardwareEmergencyAsync()
|
||||||
```
|
```
|
||||||
|
|
||||||
急停处理具有防重入保护:`_gate` 和 `_handlingEmergency` 避免重复并发关断。每个设备的关断失败会单独记录日志,不阻断后续设备的关断尝试。
|
急停处理具有防重入保护:`_gate` 和 `_handlingEmergency` 避免重复并发关断;`_hardwareEmergencyLatched` 用于区分“硬件急停曾触发后解除”和“纯软件急停等待手动重置”。每个设备的关断失败会单独记录日志,不阻断后续设备的关断尝试。
|
||||||
|
|
||||||
|
解除行为:
|
||||||
|
|
||||||
|
- 硬件急停触发后,DI 复位会自动关闭报警 DO,清除 `_handlingEmergency`、`_softwareEmergencyActive`、`_hardwareEmergencyLatched`,并刷新 UI 按钮回到“报警急停”。
|
||||||
|
- 纯软件急停不会因为硬件 DI 处于未触发状态而被轮询自动解除,仍需要点击“状态重置”;若此时硬件 DI 仍有效,重置会被拒绝。
|
||||||
|
|
||||||
主窗口顶部状态区会展示:
|
主窗口顶部状态区会展示:
|
||||||
|
|
||||||
@ -669,7 +675,7 @@ PowerShell -ExecutionPolicy Bypass -File .\publish.ps1
|
|||||||
- PDF / Word 报告生成
|
- PDF / Word 报告生成
|
||||||
- 真/假设备可按设备粒度切换
|
- 真/假设备可按设备粒度切换
|
||||||
- 实际 SSPC / 电源 / 负载 / PCIe8586 / PCI2312 驱动接入代码
|
- 实际 SSPC / 电源 / 负载 / PCIe8586 / PCI2312 驱动接入代码
|
||||||
- PCI2312 急停输入轮询、报警输出、软件急停、状态重置和设备关断联动
|
- PCI2312 急停输入轮询、报警输出、软件急停、硬件解除联动、状态重置和设备关断联动
|
||||||
|
|
||||||
### 10.2 待统一 / 待完善
|
### 10.2 待统一 / 待完善
|
||||||
|
|
||||||
@ -687,7 +693,7 @@ PowerShell -ExecutionPolicy Bypass -File .\publish.ps1
|
|||||||
3. **电源与负载真实驱动已接入,但控制命令支持度需按实物验证**。
|
3. **电源与负载真实驱动已接入,但控制命令支持度需按实物验证**。
|
||||||
4. **PCI2312 急停报警链路依赖现场接线和 DLL 部署**:DI/DO 通道号、高/低有效配置、报警灯供电、`PCI2312_64.dll` 位数和搜索路径都必须逐项核实。
|
4. **PCI2312 急停报警链路依赖现场接线和 DLL 部署**:DI/DO 通道号、高/低有效配置、报警灯供电、`PCI2312_64.dll` 位数和搜索路径都必须逐项核实。
|
||||||
5. **软件安全链路不能替代硬件安全回路**:`SafetyMonitorService` 通过轮询和软件命令下发关断,适合作为上位机联动保护;最终急停/互锁仍应由硬件电气回路兜底。
|
5. **软件安全链路不能替代硬件安全回路**:`SafetyMonitorService` 通过轮询和软件命令下发关断,适合作为上位机联动保护;最终急停/互锁仍应由硬件电气回路兜底。
|
||||||
6. **状态重置必须确认急停输入已复位**:当前代码在 DI 仍有效时拒绝关闭报警灯,避免误复位。
|
6. **状态重置与硬件解除都必须确认急停输入已复位**:当前代码在 DI 仍有效时拒绝手动重置;硬件急停锁存后只有检测到 DI 复位才会自动关闭报警灯并清除软件急停状态,避免误复位。
|
||||||
7. **所有长流程应贯穿 `CancellationToken`**,中止后优先保证设备回到安全状态。
|
7. **所有长流程应贯穿 `CancellationToken`**,中止后优先保证设备回到安全状态。
|
||||||
8. **示波器不纳入软件控制**,仅作为线下校准基准。
|
8. **示波器不纳入软件控制**,仅作为线下校准基准。
|
||||||
9. **任何涉及数据模型持久化格式的修改,都要考虑旧项目兼容**。
|
9. **任何涉及数据模型持久化格式的修改,都要考虑旧项目兼容**。
|
||||||
|
|||||||
@ -18,6 +18,7 @@ public sealed class SafetyMonitorService : IDisposable
|
|||||||
private Timer? _timer;
|
private Timer? _timer;
|
||||||
private bool _handlingEmergency;
|
private bool _handlingEmergency;
|
||||||
private bool _softwareEmergencyActive;
|
private bool _softwareEmergencyActive;
|
||||||
|
private bool _hardwareEmergencyLatched;
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
|
||||||
public SafetyMonitorService(
|
public SafetyMonitorService(
|
||||||
@ -55,7 +56,7 @@ public sealed class SafetyMonitorService : IDisposable
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int interval = Math.Clamp(options.PollIntervalMs, 50, 10_000);
|
int interval = Math.Clamp(options.PollIntervalMs, 50, 10000);
|
||||||
_timer = new Timer(OnTimer, null, TimeSpan.Zero, TimeSpan.FromMilliseconds(interval));
|
_timer = new Timer(OnTimer, null, TimeSpan.Zero, TimeSpan.FromMilliseconds(interval));
|
||||||
SetStatus(false, false, "设备正常", "正在监控 PCI2312 急停输入");
|
SetStatus(false, false, "设备正常", "正在监控 PCI2312 急停输入");
|
||||||
}
|
}
|
||||||
@ -118,6 +119,7 @@ public sealed class SafetyMonitorService : IDisposable
|
|||||||
|
|
||||||
await SetAlarmOutputAsync(false, ct).ConfigureAwait(false);
|
await SetAlarmOutputAsync(false, ct).ConfigureAwait(false);
|
||||||
_softwareEmergencyActive = false;
|
_softwareEmergencyActive = false;
|
||||||
|
_hardwareEmergencyLatched = false;
|
||||||
_handlingEmergency = false;
|
_handlingEmergency = false;
|
||||||
SetStatus(false, false, "设备正常", "急停状态已重置,报警灯已关闭,正在监控 PCI2312 输入");
|
SetStatus(false, false, "设备正常", "急停状态已重置,报警灯已关闭,正在监控 PCI2312 输入");
|
||||||
return new SafetyResetResult(true, "急停状态已重置。");
|
return new SafetyResetResult(true, "急停状态已重置。");
|
||||||
@ -143,15 +145,20 @@ public sealed class SafetyMonitorService : IDisposable
|
|||||||
bool active = await IsEmergencyInputActiveAsync(options, CancellationToken.None).ConfigureAwait(false);
|
bool active = await IsEmergencyInputActiveAsync(options, CancellationToken.None).ConfigureAwait(false);
|
||||||
if (active)
|
if (active)
|
||||||
{
|
{
|
||||||
|
_hardwareEmergencyLatched = true;
|
||||||
await HandleEmergencyAsync().ConfigureAwait(false);
|
await HandleEmergencyAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
else if (_hardwareEmergencyLatched)
|
||||||
|
{
|
||||||
|
await ClearHardwareEmergencyAsync(options).ConfigureAwait(false);
|
||||||
|
}
|
||||||
else if (_softwareEmergencyActive)
|
else if (_softwareEmergencyActive)
|
||||||
{
|
{
|
||||||
SetStatus(true, IsAlarmOutputOn, "软件急停已触发", "等待状态重置,电源和负载不会自动恢复");
|
SetStatus(true, IsAlarmOutputOn, "软件急停已触发", "等待状态重置,电源和负载不会自动恢复");
|
||||||
}
|
}
|
||||||
else if (IsEmergencyActive || IsAlarmOutputOn)
|
else if (IsEmergencyActive || IsAlarmOutputOn)
|
||||||
{
|
{
|
||||||
SetStatus(true, IsAlarmOutputOn, "急停已触发", $"DI{options.EmergencyInputChannel} 已复位,请点击状态重置关闭报警灯");
|
await ClearHardwareEmergencyAsync(options).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -193,6 +200,18 @@ public sealed class SafetyMonitorService : IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task ClearHardwareEmergencyAsync(Pci2312Options options)
|
||||||
|
{
|
||||||
|
if (IsAlarmOutputOn)
|
||||||
|
await SetAlarmOutputAsync(false, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
|
_handlingEmergency = false;
|
||||||
|
_softwareEmergencyActive = false;
|
||||||
|
_hardwareEmergencyLatched = false;
|
||||||
|
SetStatus(false, false, "设备正常", $"DI{options.EmergencyInputChannel} 已复位,硬件急停已解除,报警灯已关闭,设备输出不会自动恢复");
|
||||||
|
_log.Add(UiLogLevel.Info, "硬件急停输入已复位,软件急停状态和报警灯已自动解除。");
|
||||||
|
}
|
||||||
|
|
||||||
private async Task TryShutdownSspcAsync()
|
private async Task TryShutdownSspcAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user