修复运动控制问题:ExecuteToggleEnable 在 PLC 写入失败或异常时回滚 IsJoystickEnabled 状态;OnPlcConnectionChanged 中改为 new List<>(dict.Keys) 遍历副本,避免潜在的集合修改问题;SendSourceDetectorZMoveCommand 新增 sourcePropertyName 参数,根据用户编辑的是 SourceZ 还是 DetectorZ 来决定 delta 计算方向;SavePositionsCommand 增加 () => IsPlcConnected 条件,PLC 未连接时禁止保存。
补充射线源和PLC类库所需配置和信号地址定义文件。
This commit is contained in:
@@ -1,449 +0,0 @@
|
|||||||
# AxisControlView PLC 通信机制 | AxisControlView PLC Communication
|
|
||||||
|
|
||||||
## 概述 | Overview
|
|
||||||
|
|
||||||
AxisControlView 是运动控制模块的核心用户控件,通过 AxisControlViewModel 与 PLC 进行双向通信。本文档详细说明摇杆 Jog 操作、轴位置输入框操作以及射线源/探测器Z轴联动状态下的 PLC 信号下发机制。
|
|
||||||
|
|
||||||
## 通信架构 | Communication Architecture
|
|
||||||
|
|
||||||
```
|
|
||||||
AxisControlView (XAML)
|
|
||||||
↓ (数据绑定)
|
|
||||||
AxisControlViewModel (C#)
|
|
||||||
↓ (调用)
|
|
||||||
IMotionControlService
|
|
||||||
↓ (调用)
|
|
||||||
ISignalDataService
|
|
||||||
↓ (写入队列)
|
|
||||||
PLC (DB31, WriteCommon 组)
|
|
||||||
```
|
|
||||||
|
|
||||||
## 1. 摇杆 Jog 操作 | Joystick Jog Operation
|
|
||||||
|
|
||||||
### 1.1 双轴摇杆(圆形)| Dual Axis Joystick (Circular)
|
|
||||||
|
|
||||||
**左键拖拽(默认模式)**:
|
|
||||||
- X 轴输出 → StageX Jog(正向/反向)
|
|
||||||
- Y 轴输出 → StageY Jog(正向/反向)
|
|
||||||
|
|
||||||
**右键拖拽(默认模式)**:
|
|
||||||
- X 轴输出 → DetectorSwing Jog(正向/反向)
|
|
||||||
- Y 轴输出 → StageRotation/FixtureRotation Jog(正向/反向)
|
|
||||||
|
|
||||||
**信号下发流程**:
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
// 1. 摇杆输出变化触发 HandleDualJoystickOutput()
|
|
||||||
private void HandleDualJoystickOutput()
|
|
||||||
{
|
|
||||||
switch (DualJoystickActiveButton)
|
|
||||||
{
|
|
||||||
case MouseButtonType.Left:
|
|
||||||
UpdateLinearJog(AxisId.StageX, DualJoystickOutputX);
|
|
||||||
UpdateLinearJog(AxisId.StageY, DualJoystickOutputY);
|
|
||||||
break;
|
|
||||||
case MouseButtonType.Right:
|
|
||||||
UpdateRotaryJog(RotaryAxisId.DetectorSwing, DualJoystickOutputX);
|
|
||||||
var rotationAxisId = GetEnabledRotationAxisId();
|
|
||||||
if (rotationAxisId.HasValue)
|
|
||||||
UpdateRotaryJog(rotationAxisId.Value, DualJoystickOutputY);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. UpdateLinearJog/UpdateRotaryJog 处理 Jog 启动/速度更新/停止
|
|
||||||
private void UpdateLinearJog(AxisId axisId, double output)
|
|
||||||
{
|
|
||||||
if (output != 0)
|
|
||||||
{
|
|
||||||
var speedPercent = Math.Abs(output) * 100;
|
|
||||||
var positive = output > 0;
|
|
||||||
|
|
||||||
if (!_linearJogActive[axisId])
|
|
||||||
{
|
|
||||||
// 首次非零:设置速度并启动 Jog
|
|
||||||
_motionControlService.SetJogSpeed(axisId, speedPercent);
|
|
||||||
_motionControlService.JogStart(axisId, positive);
|
|
||||||
_linearJogActive[axisId] = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 已在 Jog:仅更新速度
|
|
||||||
_motionControlService.SetJogSpeed(axisId, speedPercent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 松开鼠标:停止 Jog
|
|
||||||
if (_linearJogActive[axisId])
|
|
||||||
{
|
|
||||||
_motionControlService.JogStop(axisId);
|
|
||||||
_linearJogActive[axisId] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. IMotionControlService 调用 ISignalDataService.EnqueueWrite 写入 PLC
|
|
||||||
public MotionResult JogStart(AxisId axisId, bool positive)
|
|
||||||
{
|
|
||||||
var signalName = positive ? MotionSignalNames.SourceZ_JogPos : MotionSignalNames.SourceZ_JogNeg;
|
|
||||||
var result = _signalService.EnqueueWrite(signalName, true);
|
|
||||||
return result ? MotionResult.Ok() : MotionResult.Fail("Jog 启动写入失败");
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**PLC 信号地址**:
|
|
||||||
|
|
||||||
| 轴 | 信号名 | 地址 | 说明 |
|
|
||||||
|----|--------|------|------|
|
|
||||||
| StageX | `MC_StageX_JogPos` | 42 | 正向 Jog(0:缺省, 1:点动) |
|
|
||||||
| StageX | `MC_StageX_JogNeg` | 43 | 反向 Jog(0:缺省, 1:点动) |
|
|
||||||
| StageY | `MC_StageY_JogPos` | 54 | 正向 Jog(0:缺省, 1:点动) |
|
|
||||||
| StageY | `MC_StageY_JogNeg` | 55 | 反向 Jog(0:缺省, 1:点动) |
|
|
||||||
| DetectorSwing | `MC_DetSwing_JogPos` | 66 | 正向 Jog(0:缺省, 1:点动) |
|
|
||||||
| DetectorSwing | `MC_DetSwing_JogNeg` | 67 | 反向 Jog(0:缺省, 1:点动) |
|
|
||||||
| StageRotation | `MC_StageRot_JogPos` | 78 | 正向 Jog(0:缺省, 1:点动) |
|
|
||||||
| StageRotation | `MC_StageRot_JogNeg` | 79 | 反向 Jog(0:缺省, 1:点动) |
|
|
||||||
| FixtureRotation | `MC_FixRot_JogPos` | 90 | 正向 Jog(0:缺省, 1:点动) |
|
|
||||||
| FixtureRotation | `MC_FixRot_JogNeg` | 91 | 反向 Jog(0:缺省, 1:点动) |
|
|
||||||
|
|
||||||
### 1.2 单轴摇杆(腰圆)| Single Axis Joystick (Oval)
|
|
||||||
|
|
||||||
**左键拖拽(默认模式)**:
|
|
||||||
- Y 轴输出 → SourceZ Jog(正向/反向)
|
|
||||||
- 若 SZDZLock=true,同时 → DetectorZ Jog(正向/反向)
|
|
||||||
|
|
||||||
**右键拖拽(默认模式)**:
|
|
||||||
- Y 轴输出 → DetectorZ Jog(正向/反向)
|
|
||||||
- 若 SZDZLock=true,同时 → SourceZ Jog(正向/反向)
|
|
||||||
|
|
||||||
**信号下发流程**:
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
private void HandleSingleJoystickOutput()
|
|
||||||
{
|
|
||||||
switch (SingleJoystickActiveButton)
|
|
||||||
{
|
|
||||||
case MouseButtonType.Left:
|
|
||||||
UpdateLinearJog(AxisId.SourceZ, SingleJoystickOutputY);
|
|
||||||
if (_szdzLock)
|
|
||||||
UpdateLinearJog(AxisId.DetectorZ, SingleJoystickOutputY);
|
|
||||||
break;
|
|
||||||
case MouseButtonType.Right:
|
|
||||||
UpdateLinearJog(AxisId.DetectorZ, SingleJoystickOutputY);
|
|
||||||
if (_szdzLock)
|
|
||||||
UpdateLinearJog(AxisId.SourceZ, SingleJoystickOutputY);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**PLC 信号地址**:
|
|
||||||
|
|
||||||
| 轴 | 信号名 | 地址 | 说明 |
|
|
||||||
|----|--------|------|------|
|
|
||||||
| SourceZ | `MC_SourceZ_JogPos` | 18 | 正向 Jog(0:缺省, 1:点动) |
|
|
||||||
| SourceZ | `MC_SourceZ_JogNeg` | 19 | 反向 Jog(0:缺省, 1:点动) |
|
|
||||||
| DetectorZ | `MC_DetZ_JogPos` | 30 | 正向 Jog(0:缺省, 1:点动) |
|
|
||||||
| DetectorZ | `MC_DetZ_JogNeg` | 31 | 反向 Jog(0:缺省, 1:点动) |
|
|
||||||
|
|
||||||
### 1.3 Jog 速度控制 | Jog Speed Control
|
|
||||||
|
|
||||||
摇杆输出值(-1.0 ~ 1.0)映射为速度百分比(0% ~ 100%):
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
var speedPercent = Math.Abs(output) * 100; // 0% ~ 100%
|
|
||||||
```
|
|
||||||
|
|
||||||
**速度计算流程**:
|
|
||||||
|
|
||||||
1. **MotionControlService.SetJogSpeed** 计算实际速度:
|
|
||||||
```csharp
|
|
||||||
var actualSpeed = _config.DefaultVelocity * speedPercent / 100.0;
|
|
||||||
// 例如:DefaultVelocity=100, speedPercent=50 → actualSpeed=50 mm/s
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **PlcLinearAxis.SetJogSpeed** 将实际速度写入 PLC:
|
|
||||||
```csharp
|
|
||||||
_signalService.EnqueueWrite(_speedSignal, (float)speedPercent);
|
|
||||||
// 注意:参数名 speedPercent 实际接收的是 actualSpeed(已计算的实际速度值)
|
|
||||||
```
|
|
||||||
|
|
||||||
**PLC 信号地址**:
|
|
||||||
|
|
||||||
| 轴 | 信号名 | 地址 | 说明 |
|
|
||||||
|----|--------|------|------|
|
|
||||||
| SourceZ | `MC_SourceZ_Speed` | 14 | 速度值(mm/s,由 DefaultVelocity * speedPercent / 100 计算) |
|
|
||||||
| DetectorZ | `MC_DetZ_Speed` | 26 | 速度值(mm/s,由 DefaultVelocity * speedPercent / 100 计算) |
|
|
||||||
| StageX | `MC_StageX_Speed` | 38 | 速度值(mm/s,由 DefaultVelocity * speedPercent / 100 计算) |
|
|
||||||
| StageY | `MC_StageY_Speed` | 50 | 速度值(mm/s,由 DefaultVelocity * speedPercent / 100 计算) |
|
|
||||||
| DetectorSwing | `MC_DetSwing_Speed` | 62 | 速度值(度/s,由 DefaultVelocity * speedPercent / 100 计算) |
|
|
||||||
| StageRotation | `MC_StageRot_Speed` | 74 | 速度值(度/s,由 DefaultVelocity * speedPercent / 100 计算) |
|
|
||||||
| FixtureRotation | `MC_FixRot_Speed` | 86 | 速度值(度/s,由 DefaultVelocity * speedPercent / 100 计算) |
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
- `DefaultVelocity = 100` mm/s
|
|
||||||
- 摇杆输出 30% → PLC 接收速度 = 100 * 30% = 30 mm/s
|
|
||||||
- 摇杆输出 100% → PLC 接收速度 = 100 * 100% = 100 mm/s
|
|
||||||
|
|
||||||
## 2. 轴位置输入框操作 | Axis Position Input Box Operation
|
|
||||||
|
|
||||||
### 2.1 编辑状态管理 | Editing State Management
|
|
||||||
|
|
||||||
- **GotFocus**:`SetEditing(propertyName, true)` → 冻结实时更新
|
|
||||||
- **LostFocus/Escape**:`CancelEditing(propertyName)` → 恢复实时更新,显示实际值
|
|
||||||
- **Enter**:`ConfirmPosition(propertyName)` → 发送目标位置移动命令
|
|
||||||
|
|
||||||
### 2.2 移动命令下发流程 | Move Command Flow
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public void ConfirmPosition(string propertyName)
|
|
||||||
{
|
|
||||||
var value = GetPropertyValue(propertyName);
|
|
||||||
SafeRun(() =>
|
|
||||||
{
|
|
||||||
MotionResult result;
|
|
||||||
// 如果射线源与探测器Z轴联动,且操作的是SourceZ或DetectorZ,则同时发送两个轴
|
|
||||||
if (SZDZLock && (propertyName == nameof(SourceZPosition) || propertyName == nameof(DetectorZPosition)))
|
|
||||||
{
|
|
||||||
result = SendSourceDetectorZMoveCommand(value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = SendMoveCommand(propertyName, value);
|
|
||||||
}
|
|
||||||
if (result.Success)
|
|
||||||
_logger.Info("目标位置已发送:{Property}={Value}", propertyName, value);
|
|
||||||
else
|
|
||||||
_logger.Warn("目标位置发送失败:{Property}={Value},原因={Reason}", propertyName, value, result.ErrorMessage);
|
|
||||||
});
|
|
||||||
_editingFlags[propertyName] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private MotionResult SendMoveCommand(string propertyName, double value)
|
|
||||||
{
|
|
||||||
switch (propertyName)
|
|
||||||
{
|
|
||||||
case nameof(StageXPosition):
|
|
||||||
return _motionControlService.MoveToTarget(AxisId.StageX, value);
|
|
||||||
case nameof(SourceZPosition):
|
|
||||||
return _motionControlService.MoveToTarget(AxisId.SourceZ, value);
|
|
||||||
// ... 其他轴
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.3 单轴移动 | Single Axis Move
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public MotionResult MoveToTarget(AxisId axisId, double targetPosition, int? speed = null)
|
|
||||||
{
|
|
||||||
var axis = _motionSystem.GetLinearAxis(axisId);
|
|
||||||
var actualSpeed = speed ?? _config.DefaultVelocity;
|
|
||||||
|
|
||||||
// 边界检查(使用配置中的 Min/Max)
|
|
||||||
if (targetPosition < config.Min || targetPosition > config.Max)
|
|
||||||
return MotionResult.Fail("目标位置超出范围");
|
|
||||||
|
|
||||||
// 写入目标位置和速度
|
|
||||||
var targetResult = _signalService.EnqueueWrite(signalName, targetPosition);
|
|
||||||
var speedResult = _signalService.EnqueueWrite(speedSignalName, actualSpeed);
|
|
||||||
|
|
||||||
// 启动移动(写入目标位置会自动触发移动)
|
|
||||||
return targetResult && speedResult ? MotionResult.Ok() : MotionResult.Fail("移动命令写入失败");
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**PLC 信号地址**:
|
|
||||||
|
|
||||||
| 轴 | 目标位置信号 | 地址 | 速度信号 | 地址 |
|
|
||||||
|----|-------------|------|---------|------|
|
|
||||||
| SourceZ | `MC_SourceZ_Target` | 10 | `MC_SourceZ_Speed` | 14 |
|
|
||||||
| DetectorZ | `MC_DetZ_Target` | 22 | `MC_DetZ_Speed` | 26 |
|
|
||||||
| StageX | `MC_StageX_Target` | 34 | `MC_StageX_Speed` | 38 |
|
|
||||||
| StageY | `MC_StageY_Target` | 46 | `MC_StageY_Speed` | 50 |
|
|
||||||
| DetectorSwing | `MC_DetSwing_Target` | 58 | `MC_DetSwing_Speed` | 62 |
|
|
||||||
| StageRotation | `MC_StageRot_Target` | 70 | `MC_StageRot_Speed` | 74 |
|
|
||||||
| FixtureRotation | `MC_FixRot_Target` | 82 | `MC_FixRot_Speed` | 86 |
|
|
||||||
|
|
||||||
### 2.4 步进移动 | Step Move
|
|
||||||
|
|
||||||
上下箭头键触发 `StepPosition(propertyName, delta)`:
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public void StepPosition(string propertyName, double delta)
|
|
||||||
{
|
|
||||||
var currentValue = GetPropertyValue(propertyName);
|
|
||||||
var newValue = currentValue + delta;
|
|
||||||
SetPropertyValue(propertyName, newValue);
|
|
||||||
|
|
||||||
// 直接发送移动命令,不进入编辑冻结
|
|
||||||
if (SZDZLock && (propertyName == nameof(SourceZPosition) || propertyName == nameof(DetectorZPosition)))
|
|
||||||
{
|
|
||||||
result = SendSourceDetectorZMoveCommand(newValue);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = SendMoveCommand(propertyName, newValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 3. 射线源/探测器Z轴联动 | Source-Detector Z-axis Linkage
|
|
||||||
|
|
||||||
### 3.1 联动使能 | Linkage Enable
|
|
||||||
|
|
||||||
点击"SZDZLock"按钮切换联动状态:
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
private void ExecuteSZDZLock()
|
|
||||||
{
|
|
||||||
SZDZLock = !SZDZLock;
|
|
||||||
var result = _motionControlService.SetSourceDetectorZLinkage(SZDZLock);
|
|
||||||
|
|
||||||
if (!result.Success)
|
|
||||||
{
|
|
||||||
// 设置失败,恢复状态
|
|
||||||
SZDZLock = !SZDZLock;
|
|
||||||
MessageBox.Show(result.ErrorMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**PLC 信号**:
|
|
||||||
|
|
||||||
| 信号名 | 地址 | 类型 | 说明 |
|
|
||||||
|--------|------|------|------|
|
|
||||||
| `MC_SourceDetZ_Linkage_Enable` | 101 | bool | 联动使能(true=启用, false=禁用) |
|
|
||||||
|
|
||||||
### 3.2 联动移动 | Linkage Move
|
|
||||||
|
|
||||||
当 SZDZLock=true 时,移动 SourceZ 或 DetectorZ 会同时移动两个轴,保持位移量相同:
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
private MotionResult SendSourceDetectorZMoveCommand(double targetValue)
|
|
||||||
{
|
|
||||||
// 1. 检查联动是否在配置中启用
|
|
||||||
if (!_config.SourceDetectorZLinkage.Enabled)
|
|
||||||
return MotionResult.Fail("射线源与探测器Z轴联动未启用");
|
|
||||||
|
|
||||||
// 2. 检查两个轴是否都在空闲状态
|
|
||||||
var sourceZAxis = _motionSystem.GetLinearAxis(AxisId.SourceZ);
|
|
||||||
var detectorZAxis = _motionSystem.GetLinearAxis(AxisId.DetectorZ);
|
|
||||||
|
|
||||||
if (sourceZAxis.Status == AxisStatus.Moving)
|
|
||||||
return MotionResult.Fail("射线源Z轴正在运动中,无法联动移动");
|
|
||||||
|
|
||||||
if (detectorZAxis.Status == AxisStatus.Moving)
|
|
||||||
return MotionResult.Fail("探测器Z轴正在运动中,无法联动移动");
|
|
||||||
|
|
||||||
// 3. 计算位移量和目标位置
|
|
||||||
var currentSourceZ = sourceZAxis.ActualPosition;
|
|
||||||
var currentDetectorZ = detectorZAxis.ActualPosition;
|
|
||||||
var sourceDelta = targetValue - currentSourceZ;
|
|
||||||
var targetDetectorZ = currentDetectorZ + sourceDelta;
|
|
||||||
|
|
||||||
// 4. 边界检查(使用配置中的 Min/Max)
|
|
||||||
if (targetValue < sourceConfig.Min || targetValue > sourceConfig.Max)
|
|
||||||
return MotionResult.Fail("射线源Z轴目标位置超出范围");
|
|
||||||
|
|
||||||
if (targetDetectorZ < detectorConfig.Min || targetDetectorZ > detectorConfig.Max)
|
|
||||||
return MotionResult.Fail("探测器Z轴目标位置超出范围");
|
|
||||||
|
|
||||||
// 5. 同时发送两个轴的移动命令
|
|
||||||
var sourceResult = sourceZAxis.MoveToTarget(targetValue, _config.DefaultVelocity);
|
|
||||||
var detectorResult = detectorZAxis.MoveToTarget(targetDetectorZ, _config.DefaultVelocity);
|
|
||||||
|
|
||||||
return sourceResult.Success && detectorResult.Success
|
|
||||||
? MotionResult.Ok()
|
|
||||||
: (sourceResult.Success ? detectorResult : sourceResult);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**PLC 信号下发**:
|
|
||||||
|
|
||||||
1. **SourceZ 移动**:
|
|
||||||
- `MC_SourceZ_Target` = targetValue(地址 10)
|
|
||||||
- `MC_SourceZ_Speed` = DefaultVelocity(地址 14)
|
|
||||||
|
|
||||||
2. **DetectorZ 移动**:
|
|
||||||
- `MC_DetZ_Target` = currentDetectorZ + (targetValue - currentSourceZ)(地址 22)
|
|
||||||
- `MC_DetZ_Speed` = DefaultVelocity(地址 26)
|
|
||||||
|
|
||||||
### 3.3 联动 Jog | Linkage Jog
|
|
||||||
|
|
||||||
当 SZDZLock=true 时,单轴摇杆的左右键会同时控制两个轴:
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
private void HandleSingleJoystickOutput()
|
|
||||||
{
|
|
||||||
switch (SingleJoystickActiveButton)
|
|
||||||
{
|
|
||||||
case MouseButtonType.Left:
|
|
||||||
UpdateLinearJog(AxisId.SourceZ, SingleJoystickOutputY);
|
|
||||||
if (_szdzLock)
|
|
||||||
UpdateLinearJog(AxisId.DetectorZ, SingleJoystickOutputY);
|
|
||||||
break;
|
|
||||||
case MouseButtonType.Right:
|
|
||||||
UpdateLinearJog(AxisId.DetectorZ, SingleJoystickOutputY);
|
|
||||||
if (_szdzLock)
|
|
||||||
UpdateLinearJog(AxisId.SourceZ, SingleJoystickOutputY);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**PLC 信号下发**:
|
|
||||||
|
|
||||||
- **SourceZ Jog**:
|
|
||||||
- `MC_SourceZ_JogPos`/`MC_SourceZ_JogNeg` = true(地址 18/19)
|
|
||||||
- `MC_SourceZ_Speed` = speedPercent(地址 14)
|
|
||||||
|
|
||||||
- **DetectorZ Jog**:
|
|
||||||
- `MC_DetZ_JogPos`/`MC_DetZ_JogNeg` = true(地址 30/31)
|
|
||||||
- `MC_DetZ_Speed` = speedPercent(地址 26)
|
|
||||||
|
|
||||||
## 4. 虚拟摇杆使能 | Virtual Joystick Enable
|
|
||||||
|
|
||||||
点击"使能开关"按钮切换虚拟摇杆使能状态:
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
private void ExecuteToggleEnable()
|
|
||||||
{
|
|
||||||
IsJoystickEnabled = !IsJoystickEnabled;
|
|
||||||
_motionControlService.SetVirtualJoystickEnable(IsJoystickEnabled);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**PLC 信号**:
|
|
||||||
|
|
||||||
| 信号名 | 地址 | 类型 | 说明 |
|
|
||||||
|--------|------|------|------|
|
|
||||||
| `MC_VirtualJoystick_Enable` | 111 | bool | 虚拟摇杆使能(true=启用, false=禁用) |
|
|
||||||
|
|
||||||
## 5. 信号写入队列机制 | Signal Write Queue Mechanism
|
|
||||||
|
|
||||||
所有 PLC 写入操作通过 `ISignalDataService.EnqueueWrite()` 进入写入队列:
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public interface ISignalDataService
|
|
||||||
{
|
|
||||||
bool EnqueueWrite(string signalName, object value);
|
|
||||||
bool EnqueueWriteBatch(Dictionary<string, object> writes);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**队列处理流程**:
|
|
||||||
|
|
||||||
1. ViewModel 调用 `EnqueueWrite(signalName, value)`
|
|
||||||
2. 信号数据服务将写入请求加入队列
|
|
||||||
3. PLC 服务在轮询周期(默认 100ms)中批量写入
|
|
||||||
4. 写入成功后从队列移除
|
|
||||||
|
|
||||||
**优势**:
|
|
||||||
|
|
||||||
- 批量写入减少 PLC 通讯次数
|
|
||||||
- 避免频繁写入导致的通讯拥塞
|
|
||||||
- 统一的错误处理和重试机制
|
|
||||||
|
|
||||||
---
|
|
||||||
@@ -0,0 +1,803 @@
|
|||||||
|
# AxisControlView PLC 通信机制 | AxisControlView PLC Communication
|
||||||
|
|
||||||
|
## 概述 | Overview
|
||||||
|
|
||||||
|
AxisControlView 是运动控制模块的核心用户控件,通过 AxisControlViewModel 与 PLC 进行双向通信。本文档详细说明摇杆 Jog 操作、轴位置输入框操作、射线源/探测器Z轴联动、安全机制以及辅助功能的 PLC 信号下发机制。
|
||||||
|
|
||||||
|
## 通信架构 | Communication Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
AxisControlView (XAML)
|
||||||
|
↓ (数据绑定)
|
||||||
|
AxisControlViewModel (C#)
|
||||||
|
↓ (调用)
|
||||||
|
IMotionControlService
|
||||||
|
↓ (调用)
|
||||||
|
IMotionSystem → PlcLinearAxis / PlcRotaryAxis
|
||||||
|
↓ (调用)
|
||||||
|
ISignalDataService.EnqueueWrite()
|
||||||
|
↓ (写入队列)
|
||||||
|
PLC (DB31, WriteCommon 组)
|
||||||
|
```
|
||||||
|
|
||||||
|
**关键分层说明**:
|
||||||
|
- `AxisControlViewModel` 调用 `IMotionControlService` 的业务方法
|
||||||
|
- `IMotionControlService` 委托给 `IMotionSystem` 获取轴实例(`PlcLinearAxis` / `PlcRotaryAxis`)
|
||||||
|
- 轴实例内部通过 `ISignalDataService.EnqueueWrite()` 写入 PLC 信号
|
||||||
|
- ViewModel 不直接操作信号,所有信号写入由轴实现层完成
|
||||||
|
|
||||||
|
## 1. 摇杆 Jog 操作 | Joystick Jog Operation
|
||||||
|
|
||||||
|
### 1.1 双轴摇杆(圆形)| Dual Axis Joystick (Circular)
|
||||||
|
|
||||||
|
**左键拖拽(默认模式)**:
|
||||||
|
- X 轴输出 → StageX Jog(正向/反向)
|
||||||
|
- Y 轴输出 → StageY Jog(正向/反向)
|
||||||
|
|
||||||
|
**右键拖拽(默认模式)**:
|
||||||
|
- X 轴输出 → DetectorSwing Jog(正向/反向)
|
||||||
|
- Y 轴输出 → StageRotation/FixtureRotation Jog(正向/反向)
|
||||||
|
|
||||||
|
> 注:当 `SwapMouseButtons=true` 时,左右键功能互换。
|
||||||
|
|
||||||
|
**信号下发流程**:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 1. 摇杆输出变化触发 HandleDualJoystickOutput()
|
||||||
|
private void HandleDualJoystickOutput()
|
||||||
|
{
|
||||||
|
switch (DualJoystickActiveButton)
|
||||||
|
{
|
||||||
|
case MouseButtonType.Left:
|
||||||
|
UpdateLinearJog(AxisId.StageX, DualJoystickOutputX);
|
||||||
|
UpdateLinearJog(AxisId.StageY, DualJoystickOutputY);
|
||||||
|
break;
|
||||||
|
case MouseButtonType.Right:
|
||||||
|
UpdateRotaryJog(RotaryAxisId.DetectorSwing, DualJoystickOutputX);
|
||||||
|
var rotationAxisId = GetEnabledRotationAxisId();
|
||||||
|
if (rotationAxisId.HasValue)
|
||||||
|
UpdateRotaryJog(rotationAxisId.Value, DualJoystickOutputY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. UpdateLinearJog 处理 Jog 启动/速度更新/停止
|
||||||
|
private void UpdateLinearJog(AxisId axisId, double output)
|
||||||
|
{
|
||||||
|
if (output != 0)
|
||||||
|
{
|
||||||
|
var speedPercent = Math.Abs(output) * 100;
|
||||||
|
var positive = output > 0;
|
||||||
|
|
||||||
|
if (!_linearJogActive[axisId])
|
||||||
|
{
|
||||||
|
// 从零变为非零:先设速度再启动 Jog
|
||||||
|
_motionControlService.SetJogSpeed(axisId, speedPercent);
|
||||||
|
_motionControlService.JogStart(axisId, positive);
|
||||||
|
_linearJogActive[axisId] = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 已在 Jog 中:仅更新速度
|
||||||
|
_motionControlService.SetJogSpeed(axisId, speedPercent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 从非零变为零:停止 Jog
|
||||||
|
if (_linearJogActive[axisId])
|
||||||
|
{
|
||||||
|
_motionControlService.JogStop(axisId);
|
||||||
|
_linearJogActive[axisId] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. MotionControlService.JogStart 委托给轴实现
|
||||||
|
public MotionResult JogStart(AxisId axisId, bool positive)
|
||||||
|
{
|
||||||
|
var axis = _motionSystem.GetLinearAxis(axisId);
|
||||||
|
// Homing 状态检查
|
||||||
|
if (axis.Status == AxisStatus.Homing)
|
||||||
|
return MotionResult.Fail("轴正在回零,拒绝 Jog 命令");
|
||||||
|
return axis.JogStart(positive);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. PlcLinearAxis.JogStart 写入 PLC 信号
|
||||||
|
public override MotionResult JogStart(bool positive)
|
||||||
|
{
|
||||||
|
if (Status == AxisStatus.Homing)
|
||||||
|
return MotionResult.Fail("轴正在回零,拒绝 Jog 命令");
|
||||||
|
var signal = positive ? _jogPosSignal : _jogNegSignal;
|
||||||
|
_signalService.EnqueueWrite(signal, true);
|
||||||
|
return MotionResult.Ok();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**旋转轴 Jog 流程类似**(`UpdateRotaryJog` → `SetJogRotarySpeed` → `JogRotaryStart`),额外包含禁用轴检查。
|
||||||
|
|
||||||
|
|
||||||
|
**PLC 信号地址(直线轴 Jog)**:
|
||||||
|
|
||||||
|
| 轴 | 信号名 | 地址 | 说明 |
|
||||||
|
|----|--------|------|------|
|
||||||
|
| SourceZ | `MC_SourceZ_JogPos` | 18 | 正向 Jog(0:缺省, 1:点动) |
|
||||||
|
| SourceZ | `MC_SourceZ_JogNeg` | 19 | 反向 Jog(0:缺省, 1:点动) |
|
||||||
|
| DetectorZ | `MC_DetZ_JogPos` | 30 | 正向 Jog(0:缺省, 1:点动) |
|
||||||
|
| DetectorZ | `MC_DetZ_JogNeg` | 31 | 反向 Jog(0:缺省, 1:点动) |
|
||||||
|
| StageX | `MC_StageX_JogPos` | 42 | 正向 Jog(0:缺省, 1:点动) |
|
||||||
|
| StageX | `MC_StageX_JogNeg` | 43 | 反向 Jog(0:缺省, 1:点动) |
|
||||||
|
| StageY | `MC_StageY_JogPos` | 54 | 正向 Jog(0:缺省, 1:点动) |
|
||||||
|
| StageY | `MC_StageY_JogNeg` | 55 | 反向 Jog(0:缺省, 1:点动) |
|
||||||
|
|
||||||
|
**PLC 信号地址(旋转轴 Jog)**:
|
||||||
|
|
||||||
|
| 轴 | 信号名 | 地址 | 说明 |
|
||||||
|
|----|--------|------|------|
|
||||||
|
| DetectorSwing | `MC_DetSwing_JogPos` | 66 | 正向 Jog(0:缺省, 1:点动) |
|
||||||
|
| DetectorSwing | `MC_DetSwing_JogNeg` | 67 | 反向 Jog(0:缺省, 1:点动) |
|
||||||
|
| StageRotation | `MC_StageRot_JogPos` | 78 | 正向 Jog(0:缺省, 1:点动) |
|
||||||
|
| StageRotation | `MC_StageRot_JogNeg` | 79 | 反向 Jog(0:缺省, 1:点动) |
|
||||||
|
| FixtureRotation | `MC_FixRot_JogPos` | 90 | 正向 Jog(0:缺省, 1:点动) |
|
||||||
|
| FixtureRotation | `MC_FixRot_JogNeg` | 91 | 反向 Jog(0:缺省, 1:点动) |
|
||||||
|
|
||||||
|
### 1.2 单轴摇杆(腰圆)| Single Axis Joystick (Oval)
|
||||||
|
|
||||||
|
**左键拖拽(默认模式)**:
|
||||||
|
- Y 轴输出 → SourceZ Jog(正向/反向)
|
||||||
|
- 若 SZDZLock=true,同时 → DetectorZ Jog(正向/反向)
|
||||||
|
|
||||||
|
**右键拖拽(默认模式)**:
|
||||||
|
- Y 轴输出 → DetectorZ Jog(正向/反向)
|
||||||
|
- 若 SZDZLock=true,同时 → SourceZ Jog(正向/反向)
|
||||||
|
|
||||||
|
**信号下发流程**:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
private void HandleSingleJoystickOutput()
|
||||||
|
{
|
||||||
|
switch (SingleJoystickActiveButton)
|
||||||
|
{
|
||||||
|
case MouseButtonType.Left:
|
||||||
|
UpdateLinearJog(AxisId.SourceZ, SingleJoystickOutputY);
|
||||||
|
if (_szdzLock)
|
||||||
|
UpdateLinearJog(AxisId.DetectorZ, SingleJoystickOutputY);
|
||||||
|
break;
|
||||||
|
case MouseButtonType.Right:
|
||||||
|
UpdateLinearJog(AxisId.DetectorZ, SingleJoystickOutputY);
|
||||||
|
if (_szdzLock)
|
||||||
|
UpdateLinearJog(AxisId.SourceZ, SingleJoystickOutputY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.3 按键释放自动停止 | Button Release Auto-Stop
|
||||||
|
|
||||||
|
当摇杆按键从非 None 变为 None 时,自动停止所有关联轴的 Jog:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// DualJoystickActiveButton setter 中
|
||||||
|
if (value == MouseButtonType.None && oldValue != MouseButtonType.None)
|
||||||
|
StopDualJoystickAxes();
|
||||||
|
|
||||||
|
// StopDualJoystickAxes 停止所有双轴摇杆关联轴
|
||||||
|
private void StopDualJoystickAxes()
|
||||||
|
{
|
||||||
|
UpdateLinearJog(AxisId.StageX, 0);
|
||||||
|
UpdateLinearJog(AxisId.StageY, 0);
|
||||||
|
UpdateRotaryJog(RotaryAxisId.DetectorSwing, 0);
|
||||||
|
var rotationAxisId = GetEnabledRotationAxisId();
|
||||||
|
if (rotationAxisId.HasValue)
|
||||||
|
UpdateRotaryJog(rotationAxisId.Value, 0);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
单轴摇杆同理(`StopSingleJoystickAxes` 停止 SourceZ 和 DetectorZ)。
|
||||||
|
|
||||||
|
### 1.4 Jog 速度控制 | Jog Speed Control
|
||||||
|
|
||||||
|
摇杆输出值(-1.0 ~ 1.0)映射为速度百分比(0% ~ 100%):
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var speedPercent = Math.Abs(output) * 100; // 0% ~ 100%
|
||||||
|
```
|
||||||
|
|
||||||
|
**速度计算流程**:
|
||||||
|
|
||||||
|
1. **MotionControlService.SetJogSpeed** 计算实际速度:
|
||||||
|
```csharp
|
||||||
|
public MotionResult SetJogSpeed(AxisId axisId, double speedPercent)
|
||||||
|
{
|
||||||
|
var axis = _motionSystem.GetLinearAxis(axisId);
|
||||||
|
var actualSpeed = _config.DefaultVelocity * speedPercent / 100.0;
|
||||||
|
return axis.SetJogSpeed(actualSpeed);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **PlcLinearAxis.SetJogSpeed** 将实际速度写入 PLC:
|
||||||
|
```csharp
|
||||||
|
public override MotionResult SetJogSpeed(double speedPercent)
|
||||||
|
{
|
||||||
|
// 注意:参数名为 speedPercent,但实际接收的是已计算的速度值(mm/s 或 度/s)
|
||||||
|
_signalService.EnqueueWrite(_speedSignal, (float)speedPercent);
|
||||||
|
return MotionResult.Ok();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**PLC 速度信号地址**:
|
||||||
|
|
||||||
|
| 轴 | 信号名 | 地址 | 说明 |
|
||||||
|
|----|--------|------|------|
|
||||||
|
| SourceZ | `MC_SourceZ_Speed` | 14 | 速度值(mm/s,由 DefaultVelocity × speedPercent / 100 计算) |
|
||||||
|
| DetectorZ | `MC_DetZ_Speed` | 26 | 速度值(mm/s,由 DefaultVelocity × speedPercent / 100 计算) |
|
||||||
|
| StageX | `MC_StageX_Speed` | 38 | 速度值(mm/s,由 DefaultVelocity × speedPercent / 100 计算) |
|
||||||
|
| StageY | `MC_StageY_Speed` | 50 | 速度值(mm/s,由 DefaultVelocity × speedPercent / 100 计算) |
|
||||||
|
| DetectorSwing | `MC_DetSwing_Speed` | 62 | 速度值(度/s,由 DefaultVelocity × speedPercent / 100 计算) |
|
||||||
|
| StageRotation | `MC_StageRot_Speed` | 74 | 速度值(度/s,由 DefaultVelocity × speedPercent / 100 计算) |
|
||||||
|
| FixtureRotation | `MC_FixRot_Speed` | 86 | 速度值(度/s,由 DefaultVelocity × speedPercent / 100 计算) |
|
||||||
|
|
||||||
|
**示例**:
|
||||||
|
- `DefaultVelocity = 100` mm/s
|
||||||
|
- 摇杆输出 30% → PLC 接收速度 = 100 × 30 / 100 = 30 mm/s
|
||||||
|
- 摇杆输出 100% → PLC 接收速度 = 100 × 100 / 100 = 100 mm/s
|
||||||
|
|
||||||
|
## 2. 轴位置输入框操作 | Axis Position Input Box Operation
|
||||||
|
|
||||||
|
### 2.1 编辑状态管理 | Editing State Management
|
||||||
|
|
||||||
|
- **GotFocus**:`SetEditing(propertyName, true)` → 冻结实时更新
|
||||||
|
- **LostFocus/Escape**:`CancelEditing(propertyName)` → 恢复实时更新,显示实际值
|
||||||
|
- **Enter**:`ConfirmPosition(propertyName)` → 发送目标位置移动命令
|
||||||
|
|
||||||
|
### 2.2 移动命令下发流程 | Move Command Flow
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public void ConfirmPosition(string propertyName)
|
||||||
|
{
|
||||||
|
var value = GetPropertyValue(propertyName);
|
||||||
|
SafeRun(() =>
|
||||||
|
{
|
||||||
|
MotionResult result;
|
||||||
|
// 如果射线源与探测器Z轴联动,且操作的是SourceZ或DetectorZ,则同时发送两个轴
|
||||||
|
if (SZDZLock && (propertyName == nameof(SourceZPosition) || propertyName == nameof(DetectorZPosition)))
|
||||||
|
{
|
||||||
|
result = SendSourceDetectorZMoveCommand(value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = SendMoveCommand(propertyName, value);
|
||||||
|
}
|
||||||
|
if (result.Success)
|
||||||
|
_logger.Info("目标位置已发送:{Property}={Value}", propertyName, value);
|
||||||
|
else
|
||||||
|
_logger.Warn("目标位置发送失败:{Property}={Value},原因={Reason}", propertyName, value, result.ErrorMessage);
|
||||||
|
});
|
||||||
|
_editingFlags[propertyName] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MotionResult SendMoveCommand(string propertyName, double value)
|
||||||
|
{
|
||||||
|
switch (propertyName)
|
||||||
|
{
|
||||||
|
case nameof(StageXPosition):
|
||||||
|
return _motionControlService.MoveToTarget(AxisId.StageX, value);
|
||||||
|
case nameof(StageYPosition):
|
||||||
|
return _motionControlService.MoveToTarget(AxisId.StageY, value);
|
||||||
|
case nameof(SourceZPosition):
|
||||||
|
return _motionControlService.MoveToTarget(AxisId.SourceZ, value);
|
||||||
|
case nameof(DetectorZPosition):
|
||||||
|
return _motionControlService.MoveToTarget(AxisId.DetectorZ, value);
|
||||||
|
case nameof(DetectorSwingAngle):
|
||||||
|
return _motionControlService.MoveRotaryToTarget(RotaryAxisId.DetectorSwing, value);
|
||||||
|
case nameof(StageRotationAngle):
|
||||||
|
return _motionControlService.MoveRotaryToTarget(RotaryAxisId.StageRotation, value);
|
||||||
|
case nameof(FixtureRotationAngle):
|
||||||
|
return _motionControlService.MoveRotaryToTarget(RotaryAxisId.FixtureRotation, value);
|
||||||
|
default:
|
||||||
|
return MotionResult.Fail($"未知的属性名称:{propertyName}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.3 单轴移动 | Single Axis Move
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// MotionControlService.MoveToTarget — 业务层
|
||||||
|
public MotionResult MoveToTarget(AxisId axisId, double target, double? speed = null)
|
||||||
|
{
|
||||||
|
var axis = _motionSystem.GetLinearAxis(axisId);
|
||||||
|
|
||||||
|
// 运动中防重入检查
|
||||||
|
if (axis.Status == AxisStatus.Moving)
|
||||||
|
return MotionResult.Fail("轴正在运动中,拒绝重复命令");
|
||||||
|
|
||||||
|
// 委托给轴实现(轴内部包含边界检查)
|
||||||
|
return axis.MoveToTarget(target, speed ?? _config.DefaultVelocity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// PlcLinearAxis.MoveToTarget — 轴实现层
|
||||||
|
public override MotionResult MoveToTarget(double target, double? speed = null)
|
||||||
|
{
|
||||||
|
if (!ValidateTarget(target))
|
||||||
|
return MotionResult.Fail($"目标位置 {target} 超出范围 [{_min}, {_max}]");
|
||||||
|
if (Status == AxisStatus.Moving)
|
||||||
|
return MotionResult.Fail("轴正在运动中,拒绝重复命令");
|
||||||
|
|
||||||
|
if (speed.HasValue)
|
||||||
|
_signalService.EnqueueWrite(_speedSignal, (float)speed.Value);
|
||||||
|
_signalService.EnqueueWrite(_writeSignal, (float)target);
|
||||||
|
Status = AxisStatus.Moving;
|
||||||
|
return MotionResult.Ok();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**PLC 信号地址**:
|
||||||
|
|
||||||
|
| 轴 | 目标位置信号 | 地址 | 速度信号 | 地址 |
|
||||||
|
|----|-------------|------|---------|------|
|
||||||
|
| SourceZ | `MC_SourceZ_Target` | 10 | `MC_SourceZ_Speed` | 14 |
|
||||||
|
| DetectorZ | `MC_DetZ_Target` | 22 | `MC_DetZ_Speed` | 26 |
|
||||||
|
| StageX | `MC_StageX_Target` | 34 | `MC_StageX_Speed` | 38 |
|
||||||
|
| StageY | `MC_StageY_Target` | 46 | `MC_StageY_Speed` | 50 |
|
||||||
|
| DetectorSwing | `MC_DetSwing_Target` | 58 | `MC_DetSwing_Speed` | 62 |
|
||||||
|
| StageRotation | `MC_StageRot_Target` | 70 | `MC_StageRot_Speed` | 74 |
|
||||||
|
| FixtureRotation | `MC_FixRot_Target` | 82 | `MC_FixRot_Speed` | 86 |
|
||||||
|
|
||||||
|
### 2.4 步进移动 | Step Move
|
||||||
|
|
||||||
|
上下箭头键触发 `StepPosition(propertyName, delta)`:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public void StepPosition(string propertyName, double delta)
|
||||||
|
{
|
||||||
|
var currentValue = GetPropertyValue(propertyName);
|
||||||
|
var newValue = currentValue + delta;
|
||||||
|
SetPropertyValue(propertyName, newValue);
|
||||||
|
SafeRun(() =>
|
||||||
|
{
|
||||||
|
MotionResult result;
|
||||||
|
if (SZDZLock && (propertyName == nameof(SourceZPosition) || propertyName == nameof(DetectorZPosition)))
|
||||||
|
{
|
||||||
|
result = SendSourceDetectorZMoveCommand(newValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = SendMoveCommand(propertyName, newValue);
|
||||||
|
}
|
||||||
|
if (!result.Success)
|
||||||
|
_logger.Warn("步进移动失败:{Property},原因={Reason}", propertyName, result.ErrorMessage);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. 射线源/探测器Z轴联动 | Source-Detector Z-axis Linkage
|
||||||
|
|
||||||
|
### 3.1 联动使能 | Linkage Enable
|
||||||
|
|
||||||
|
点击"SZDZLock"按钮切换联动状态:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
private void ExecuteSZDZLock()
|
||||||
|
{
|
||||||
|
// 切换联动状态
|
||||||
|
SZDZLock = !SZDZLock;
|
||||||
|
|
||||||
|
// 调用服务设置联动
|
||||||
|
var result = _motionControlService.SetSourceDetectorZLinkage(SZDZLock);
|
||||||
|
|
||||||
|
if (!result.Success)
|
||||||
|
{
|
||||||
|
// 如果设置失败,恢复状态
|
||||||
|
SZDZLock = !SZDZLock;
|
||||||
|
MessageBox.Show(result.ErrorMessage, ...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MotionControlService.SetSourceDetectorZLinkage
|
||||||
|
public MotionResult SetSourceDetectorZLinkage(bool enabled)
|
||||||
|
{
|
||||||
|
var config = _config.SourceDetectorZLinkage;
|
||||||
|
if (!config.Enabled)
|
||||||
|
return MotionResult.Fail("射线源与探测器Z轴联动未启用");
|
||||||
|
|
||||||
|
var result = _signalService.EnqueueWrite(MotionSignalNames.SourceDetZ_Linkage_Enable, (bool)enabled);
|
||||||
|
return result ? MotionResult.Ok() : MotionResult.Fail("联动使能写入失败");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
另外提供公开方法 `SetSZDZLinkageToPlc()` 供外部直接同步当前联动状态到 PLC:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public MotionResult SetSZDZLinkageToPlc()
|
||||||
|
{
|
||||||
|
return _motionControlService.SetSourceDetectorZLinkage(SZDZLock);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**PLC 信号**:
|
||||||
|
|
||||||
|
| 信号名 | 地址 | 类型 | 说明 |
|
||||||
|
|--------|------|------|------|
|
||||||
|
| `MC_SourceDetZ_Linkage_Enable` | 101 | bool | 联动使能(true=启用, false=禁用) |
|
||||||
|
|
||||||
|
### 3.2 联动移动 | Linkage Move
|
||||||
|
|
||||||
|
当 SZDZLock=true 时,移动 SourceZ 或 DetectorZ 会同时移动两个轴,保持位移量相同:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
private MotionResult SendSourceDetectorZMoveCommand(double targetValue)
|
||||||
|
{
|
||||||
|
// 1. 检查联动是否在配置中启用
|
||||||
|
if (!_config.SourceDetectorZLinkage.Enabled)
|
||||||
|
return MotionResult.Fail("射线源与探测器Z轴联动未启用");
|
||||||
|
|
||||||
|
// 2. 获取两个轴并检查是否都在空闲状态
|
||||||
|
var sourceZAxis = _motionSystem.GetLinearAxis(AxisId.SourceZ);
|
||||||
|
var detectorZAxis = _motionSystem.GetLinearAxis(AxisId.DetectorZ);
|
||||||
|
|
||||||
|
if (sourceZAxis.Status == AxisStatus.Moving)
|
||||||
|
return MotionResult.Fail("射线源Z轴正在运动中,无法联动移动");
|
||||||
|
if (detectorZAxis.Status == AxisStatus.Moving)
|
||||||
|
return MotionResult.Fail("探测器Z轴正在运动中,无法联动移动");
|
||||||
|
|
||||||
|
// 3. 计算位移量和目标位置
|
||||||
|
var currentSourceZ = sourceZAxis.ActualPosition;
|
||||||
|
var currentDetectorZ = detectorZAxis.ActualPosition;
|
||||||
|
var sourceDelta = targetValue - currentSourceZ;
|
||||||
|
var targetDetectorZ = currentDetectorZ + sourceDelta;
|
||||||
|
|
||||||
|
// 4. 边界检查(使用配置中的 Min/Max,收集所有错误后统一返回)
|
||||||
|
if (_config.LinearAxes.TryGetValue(AxisId.SourceZ, out var sourceConfig) &&
|
||||||
|
_config.LinearAxes.TryGetValue(AxisId.DetectorZ, out var detectorConfig))
|
||||||
|
{
|
||||||
|
var errors = new List<string>();
|
||||||
|
if (targetValue < sourceConfig.Min || targetValue > sourceConfig.Max)
|
||||||
|
errors.Add("射线源Z轴目标位置超出范围");
|
||||||
|
if (targetDetectorZ < detectorConfig.Min || targetDetectorZ > detectorConfig.Max)
|
||||||
|
errors.Add("探测器Z轴目标位置超出范围");
|
||||||
|
if (errors.Count > 0)
|
||||||
|
return MotionResult.Fail(string.Join("; ", errors));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 同时发送两个轴的移动命令(通过轴实现层写入 PLC)
|
||||||
|
var sourceResult = sourceZAxis.MoveToTarget(targetValue, _config.DefaultVelocity);
|
||||||
|
var detectorResult = detectorZAxis.MoveToTarget(targetDetectorZ, _config.DefaultVelocity);
|
||||||
|
|
||||||
|
if (!sourceResult.Success) return sourceResult;
|
||||||
|
if (!detectorResult.Success) return detectorResult;
|
||||||
|
return MotionResult.Ok();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**PLC 信号下发**:
|
||||||
|
|
||||||
|
1. **SourceZ 移动**:
|
||||||
|
- `MC_SourceZ_Speed` = DefaultVelocity(地址 14)
|
||||||
|
- `MC_SourceZ_Target` = targetValue(地址 10)
|
||||||
|
|
||||||
|
2. **DetectorZ 移动**:
|
||||||
|
- `MC_DetZ_Speed` = DefaultVelocity(地址 26)
|
||||||
|
- `MC_DetZ_Target` = currentDetectorZ + (targetValue - currentSourceZ)(地址 22)
|
||||||
|
|
||||||
|
### 3.3 联动 Jog | Linkage Jog
|
||||||
|
|
||||||
|
当 SZDZLock=true 时,单轴摇杆的左右键会同时控制两个轴:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
private void HandleSingleJoystickOutput()
|
||||||
|
{
|
||||||
|
switch (SingleJoystickActiveButton)
|
||||||
|
{
|
||||||
|
case MouseButtonType.Left:
|
||||||
|
UpdateLinearJog(AxisId.SourceZ, SingleJoystickOutputY);
|
||||||
|
if (_szdzLock)
|
||||||
|
UpdateLinearJog(AxisId.DetectorZ, SingleJoystickOutputY);
|
||||||
|
break;
|
||||||
|
case MouseButtonType.Right:
|
||||||
|
UpdateLinearJog(AxisId.DetectorZ, SingleJoystickOutputY);
|
||||||
|
if (_szdzLock)
|
||||||
|
UpdateLinearJog(AxisId.SourceZ, SingleJoystickOutputY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**PLC 信号下发**:
|
||||||
|
|
||||||
|
- **SourceZ Jog**:
|
||||||
|
- `MC_SourceZ_Speed` = actualSpeed(地址 14)
|
||||||
|
- `MC_SourceZ_JogPos`/`MC_SourceZ_JogNeg` = true(地址 18/19)
|
||||||
|
|
||||||
|
- **DetectorZ Jog**:
|
||||||
|
- `MC_DetZ_Speed` = actualSpeed(地址 26)
|
||||||
|
- `MC_DetZ_JogPos`/`MC_DetZ_JogNeg` = true(地址 30/31)
|
||||||
|
|
||||||
|
|
||||||
|
## 4. 虚拟摇杆使能 | Virtual Joystick Enable
|
||||||
|
|
||||||
|
点击"使能开关"按钮切换虚拟摇杆使能状态:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
private void ExecuteToggleEnable()
|
||||||
|
{
|
||||||
|
IsJoystickEnabled = !IsJoystickEnabled;
|
||||||
|
|
||||||
|
var result = _motionControlService.SetVirtualJoystickEnable(IsJoystickEnabled);
|
||||||
|
if (!result.Success)
|
||||||
|
{
|
||||||
|
MessageBox.Show(result.ErrorMessage, ...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MotionControlService.SetVirtualJoystickEnable
|
||||||
|
public MotionResult SetVirtualJoystickEnable(bool enabled)
|
||||||
|
{
|
||||||
|
var result = _signalService.EnqueueWrite(MotionSignalNames.VirtualJoystick_Enable, (bool)enabled);
|
||||||
|
return result ? MotionResult.Ok() : MotionResult.Fail("虚拟摇杆使能写入失败");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**PLC 信号**:
|
||||||
|
|
||||||
|
| 信号名 | 地址 | 类型 | 说明 |
|
||||||
|
|--------|------|------|------|
|
||||||
|
| `MC_VirtualJoystick_Enable` | 111 | bool | 虚拟摇杆使能(true=启用, false=禁用) |
|
||||||
|
|
||||||
|
## 5. 鼠标按键交换 | Mouse Button Swap
|
||||||
|
|
||||||
|
点击"交换按键"按钮切换摇杆左右键功能映射:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
private void ExecuteToggleSwapMouseButtons()
|
||||||
|
{
|
||||||
|
SwapMouseButtons = !SwapMouseButtons;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
此功能为纯 UI 层逻辑,不涉及 PLC 信号写入。当 `SwapMouseButtons=true` 时,摇杆控件内部交换左右键的功能映射。
|
||||||
|
|
||||||
|
## 6. 保存/恢复轴位置 | Save/Restore Axis Positions
|
||||||
|
|
||||||
|
### 6.1 保存当前位置 | Save Current Positions
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
private void ExecuteSavePositions()
|
||||||
|
{
|
||||||
|
_savedPositions = new SavedPositions
|
||||||
|
{
|
||||||
|
StageX = StageXPosition,
|
||||||
|
StageY = StageYPosition,
|
||||||
|
SourceZ = SourceZPosition,
|
||||||
|
DetectorZ = DetectorZPosition,
|
||||||
|
DetectorSwing = DetectorSwingAngle,
|
||||||
|
StageRotation = StageRotationAngle,
|
||||||
|
FixtureRotation = FixtureRotationAngle
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.2 恢复保存的位置 | Restore Saved Positions
|
||||||
|
|
||||||
|
恢复时会同时向所有轴发送移动命令:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
private void ExecuteRestorePositions()
|
||||||
|
{
|
||||||
|
if (_savedPositions == null) return;
|
||||||
|
|
||||||
|
// 恢复到输入框
|
||||||
|
StageXPosition = _savedPositions.StageX;
|
||||||
|
StageYPosition = _savedPositions.StageY;
|
||||||
|
SourceZPosition = _savedPositions.SourceZ;
|
||||||
|
DetectorZPosition = _savedPositions.DetectorZ;
|
||||||
|
DetectorSwingAngle = _savedPositions.DetectorSwing;
|
||||||
|
StageRotationAngle = _savedPositions.StageRotation;
|
||||||
|
FixtureRotationAngle = _savedPositions.FixtureRotation;
|
||||||
|
|
||||||
|
// 发送移动命令(通过 MotionControlService → PlcLinearAxis/PlcRotaryAxis → PLC)
|
||||||
|
_motionControlService.MoveToTarget(AxisId.StageX, _savedPositions.StageX);
|
||||||
|
_motionControlService.MoveToTarget(AxisId.StageY, _savedPositions.StageY);
|
||||||
|
_motionControlService.MoveToTarget(AxisId.SourceZ, _savedPositions.SourceZ);
|
||||||
|
_motionControlService.MoveToTarget(AxisId.DetectorZ, _savedPositions.DetectorZ);
|
||||||
|
_motionControlService.MoveRotaryToTarget(RotaryAxisId.DetectorSwing, _savedPositions.DetectorSwing);
|
||||||
|
_motionControlService.MoveRotaryToTarget(RotaryAxisId.StageRotation, _savedPositions.StageRotation);
|
||||||
|
_motionControlService.MoveRotaryToTarget(RotaryAxisId.FixtureRotation, _savedPositions.FixtureRotation);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**PLC 信号下发**:恢复时向所有 7 个轴写入目标位置和速度信号(参见第 2.3 节信号地址表)。
|
||||||
|
|
||||||
|
## 7. 安全参数 | Safety Parameters
|
||||||
|
|
||||||
|
ViewModel 提供以下安全参数属性:
|
||||||
|
|
||||||
|
| 属性 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `SafetyHeight` | 探测器安全高度限定值 |
|
||||||
|
| `CalibrationValue` | 校准自动计算值 |
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public void ConfirmSafetyHeight()
|
||||||
|
{
|
||||||
|
_logger.Info("探测器安全高度限定值已保存:{Value}", SafetyHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ConfirmCalibrationValue()
|
||||||
|
{
|
||||||
|
_logger.Info("校准自动计算值已保存:{Value}", CalibrationValue);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> 注:当前实现仅记录日志,未写入 PLC 信号。后续可能扩展为写入 PLC 安全参数区域。
|
||||||
|
|
||||||
|
## 8. PLC 断连安全处理 | PLC Disconnection Safety
|
||||||
|
|
||||||
|
当 PLC 连接断开时,ViewModel 自动执行以下安全操作:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
private void OnPlcConnectionChanged()
|
||||||
|
{
|
||||||
|
IsPlcConnected = _plcService.IsConnected;
|
||||||
|
|
||||||
|
if (!_plcService.IsConnected)
|
||||||
|
{
|
||||||
|
// 1. 停止所有活跃的 Jog 操作(标记为停止)
|
||||||
|
foreach (var axisId in _linearJogActive.Keys)
|
||||||
|
if (_linearJogActive[axisId])
|
||||||
|
_linearJogActive[axisId] = false;
|
||||||
|
foreach (var axisId in _rotaryJogActive.Keys)
|
||||||
|
if (_rotaryJogActive[axisId])
|
||||||
|
_rotaryJogActive[axisId] = false;
|
||||||
|
|
||||||
|
// 2. 禁用摇杆
|
||||||
|
IsJoystickEnabled = false;
|
||||||
|
|
||||||
|
// 3. 显示连接断开提示
|
||||||
|
ErrorMessage = LocalizationHelper.Get("MC_PlcNotConnected");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// PLC 重连:清除错误信息(不自动启用摇杆,需用户手动开启)
|
||||||
|
ErrorMessage = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**安全策略**:
|
||||||
|
- PLC 断连时立即标记所有 Jog 为停止状态
|
||||||
|
- 禁用虚拟摇杆,防止用户误操作
|
||||||
|
- PLC 重连后不自动恢复使能,需用户手动确认后开启
|
||||||
|
|
||||||
|
## 9. 实体摇杆状态 | Physical Joystick Status
|
||||||
|
|
||||||
|
通过 `JoystickActiveEvent` 事件订阅实体摇杆的激活状态:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
_eventAggregator.GetEvent<JoystickActiveEvent>().Subscribe(OnJoystickActiveChanged, ThreadOption.UIThread);
|
||||||
|
|
||||||
|
private void OnJoystickActiveChanged(bool isActive)
|
||||||
|
{
|
||||||
|
IsJoystickActive = isActive;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**PLC 信号(读取)**:
|
||||||
|
|
||||||
|
| 信号名 | 说明 |
|
||||||
|
|--------|------|
|
||||||
|
| `MC_Joystick_Active` | 实体摇杆输入激活状态(由 PLC 轮询读取) |
|
||||||
|
|
||||||
|
## 10. 旋转轴可见性控制 | Rotary Axis Visibility Control
|
||||||
|
|
||||||
|
根据配置动态控制旋转轴输入框的可见性:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
DetectorSwingVisibility = _config.RotaryAxes.ContainsKey(RotaryAxisId.DetectorSwing)
|
||||||
|
&& _config.RotaryAxes[RotaryAxisId.DetectorSwing].Enabled
|
||||||
|
? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
|
||||||
|
StageRotationVisibility = _config.RotaryAxes.ContainsKey(RotaryAxisId.StageRotation)
|
||||||
|
&& _config.RotaryAxes[RotaryAxisId.StageRotation].Enabled
|
||||||
|
? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
|
||||||
|
FixtureRotationVisibility = _config.RotaryAxes.ContainsKey(RotaryAxisId.FixtureRotation)
|
||||||
|
&& _config.RotaryAxes[RotaryAxisId.FixtureRotation].Enabled
|
||||||
|
? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
```
|
||||||
|
|
||||||
|
此功能为纯 UI 层逻辑,不涉及 PLC 信号。
|
||||||
|
|
||||||
|
## 11. 信号写入队列机制 | Signal Write Queue Mechanism
|
||||||
|
|
||||||
|
所有 PLC 写入操作通过 `ISignalDataService.EnqueueWrite()` 进入写入队列:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public interface ISignalDataService
|
||||||
|
{
|
||||||
|
bool EnqueueWrite(string signalName, object value);
|
||||||
|
bool EnqueueWriteBatch(Dictionary<string, object> writes);
|
||||||
|
T GetValueByName<T>(string signalName);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**队列处理流程**:
|
||||||
|
|
||||||
|
1. 轴实现层(`PlcLinearAxis`/`PlcRotaryAxis`)调用 `EnqueueWrite(signalName, value)`
|
||||||
|
2. 信号数据服务将写入请求加入队列
|
||||||
|
3. PLC 服务在轮询周期(默认 100ms)中批量写入
|
||||||
|
4. 写入成功后从队列移除
|
||||||
|
|
||||||
|
**优势**:
|
||||||
|
|
||||||
|
- 批量写入减少 PLC 通讯次数
|
||||||
|
- 避免频繁写入导致的通讯拥塞
|
||||||
|
- 统一的错误处理和重试机制
|
||||||
|
|
||||||
|
## 12. 完整 PLC 信号名称常量 | Complete PLC Signal Name Constants
|
||||||
|
|
||||||
|
定义在 `MotionSignalNames.cs` 中:
|
||||||
|
|
||||||
|
| 分类 | 常量名 | 信号名 | 方向 |
|
||||||
|
|------|--------|--------|------|
|
||||||
|
| 联动 | `SourceDetZ_Linkage_Enable` | `MC_SourceDetZ_Linkage_Enable` | 写入 |
|
||||||
|
| 使能 | `VirtualJoystick_Enable` | `MC_VirtualJoystick_Enable` | 写入 |
|
||||||
|
| 状态 | `Joystick_Active` | `MC_Joystick_Active` | 读取 |
|
||||||
|
| SourceZ | `SourceZ_Pos` | `MC_SourceZ_Pos` | 读取 |
|
||||||
|
| SourceZ | `SourceZ_Target` | `MC_SourceZ_Target` | 写入 |
|
||||||
|
| SourceZ | `SourceZ_Speed` | `MC_SourceZ_Speed` | 写入 |
|
||||||
|
| SourceZ | `SourceZ_JogPos` | `MC_SourceZ_JogPos` | 写入 |
|
||||||
|
| SourceZ | `SourceZ_JogNeg` | `MC_SourceZ_JogNeg` | 写入 |
|
||||||
|
| SourceZ | `SourceZ_Home` | `MC_SourceZ_Home` | 写入 |
|
||||||
|
| SourceZ | `SourceZ_Stop` | `MC_SourceZ_Stop` | 写入 |
|
||||||
|
| DetectorZ | `DetZ_Pos` | `MC_DetZ_Pos` | 读取 |
|
||||||
|
| DetectorZ | `DetZ_Target` | `MC_DetZ_Target` | 写入 |
|
||||||
|
| DetectorZ | `DetZ_Speed` | `MC_DetZ_Speed` | 写入 |
|
||||||
|
| DetectorZ | `DetZ_JogPos` | `MC_DetZ_JogPos` | 写入 |
|
||||||
|
| DetectorZ | `DetZ_JogNeg` | `MC_DetZ_JogNeg` | 写入 |
|
||||||
|
| DetectorZ | `DetZ_Home` | `MC_DetZ_Home` | 写入 |
|
||||||
|
| DetectorZ | `DetZ_Stop` | `MC_DetZ_Stop` | 写入 |
|
||||||
|
| StageX | `StageX_Pos` | `MC_StageX_Pos` | 读取 |
|
||||||
|
| StageX | `StageX_Target` | `MC_StageX_Target` | 写入 |
|
||||||
|
| StageX | `StageX_Speed` | `MC_StageX_Speed` | 写入 |
|
||||||
|
| StageX | `StageX_JogPos` | `MC_StageX_JogPos` | 写入 |
|
||||||
|
| StageX | `StageX_JogNeg` | `MC_StageX_JogNeg` | 写入 |
|
||||||
|
| StageX | `StageX_Home` | `MC_StageX_Home` | 写入 |
|
||||||
|
| StageX | `StageX_Stop` | `MC_StageX_Stop` | 写入 |
|
||||||
|
| StageY | `StageY_Pos` | `MC_StageY_Pos` | 读取 |
|
||||||
|
| StageY | `StageY_Target` | `MC_StageY_Target` | 写入 |
|
||||||
|
| StageY | `StageY_Speed` | `MC_StageY_Speed` | 写入 |
|
||||||
|
| StageY | `StageY_JogPos` | `MC_StageY_JogPos` | 写入 |
|
||||||
|
| StageY | `StageY_JogNeg` | `MC_StageY_JogNeg` | 写入 |
|
||||||
|
| StageY | `StageY_Home` | `MC_StageY_Home` | 写入 |
|
||||||
|
| StageY | `StageY_Stop` | `MC_StageY_Stop` | 写入 |
|
||||||
|
| DetSwing | `DetSwing_Angle` | `MC_DetSwing_Angle` | 读取 |
|
||||||
|
| DetSwing | `DetSwing_Target` | `MC_DetSwing_Target` | 写入 |
|
||||||
|
| DetSwing | `DetSwing_Speed` | `MC_DetSwing_Speed` | 写入 |
|
||||||
|
| DetSwing | `DetSwing_JogPos` | `MC_DetSwing_JogPos` | 写入 |
|
||||||
|
| DetSwing | `DetSwing_JogNeg` | `MC_DetSwing_JogNeg` | 写入 |
|
||||||
|
| DetSwing | `DetSwing_Home` | `MC_DetSwing_Home` | 写入 |
|
||||||
|
| DetSwing | `DetSwing_Stop` | `MC_DetSwing_Stop` | 写入 |
|
||||||
|
| StageRot | `StageRot_Angle` | `MC_StageRot_Angle` | 读取 |
|
||||||
|
| StageRot | `StageRot_Target` | `MC_StageRot_Target` | 写入 |
|
||||||
|
| StageRot | `StageRot_Speed` | `MC_StageRot_Speed` | 写入 |
|
||||||
|
| StageRot | `StageRot_JogPos` | `MC_StageRot_JogPos` | 写入 |
|
||||||
|
| StageRot | `StageRot_JogNeg` | `MC_StageRot_JogNeg` | 写入 |
|
||||||
|
| StageRot | `StageRot_Home` | `MC_StageRot_Home` | 写入 |
|
||||||
|
| StageRot | `StageRot_Stop` | `MC_StageRot_Stop` | 写入 |
|
||||||
|
| FixRot | `FixRot_Angle` | `MC_FixRot_Angle` | 读取 |
|
||||||
|
| FixRot | `FixRot_Target` | `MC_FixRot_Target` | 写入 |
|
||||||
|
| FixRot | `FixRot_Speed` | `MC_FixRot_Speed` | 写入 |
|
||||||
|
| FixRot | `FixRot_JogPos` | `MC_FixRot_JogPos` | 写入 |
|
||||||
|
| FixRot | `FixRot_JogNeg` | `MC_FixRot_JogNeg` | 写入 |
|
||||||
|
| FixRot | `FixRot_Home` | `MC_FixRot_Home` | 写入 |
|
||||||
|
| FixRot | `FixRot_Stop` | `MC_FixRot_Stop` | 写入 |
|
||||||
|
| 安全门 | `Door_Open` | `MC_Door_Open` | 写入 |
|
||||||
|
| 安全门 | `Door_Close` | `MC_Door_Close` | 写入 |
|
||||||
|
| 安全门 | `Door_Stop` | `MC_Door_Stop` | 写入 |
|
||||||
|
| 安全门 | `Door_Status` | `MC_Door_Status` | 读取 |
|
||||||
|
| 安全门 | `Door_Interlock` | `MC_Door_Interlock` | 读取 |
|
||||||
|
| 轴复位 | `Axis_Reset` | `MC_Axis_Reset` | 写入 |
|
||||||
|
| 轴复位 | `Axis_ResetDone` | `MC_Axis_ResetDone` | 读取 |
|
||||||
|
|
||||||
|
---
|
||||||
@@ -83,7 +83,7 @@ namespace XP.Hardware.MotionControl.ViewModels
|
|||||||
// 初始化命令 | Initialize commands
|
// 初始化命令 | Initialize commands
|
||||||
ToggleEnableCommand = new DelegateCommand(ExecuteToggleEnable, () => IsPlcConnected);
|
ToggleEnableCommand = new DelegateCommand(ExecuteToggleEnable, () => IsPlcConnected);
|
||||||
ToggleSwapMouseButtonsCommand = new DelegateCommand(ExecuteToggleSwapMouseButtons);
|
ToggleSwapMouseButtonsCommand = new DelegateCommand(ExecuteToggleSwapMouseButtons);
|
||||||
SavePositionsCommand = new DelegateCommand(ExecuteSavePositions);
|
SavePositionsCommand = new DelegateCommand(ExecuteSavePositions, () => IsPlcConnected);
|
||||||
RestorePositionsCommand = new DelegateCommand(ExecuteRestorePositions, () => _savedPositions != null && IsPlcConnected);
|
RestorePositionsCommand = new DelegateCommand(ExecuteRestorePositions, () => _savedPositions != null && IsPlcConnected);
|
||||||
// 射线源与探测器Z轴联动命令 | Source-Detector Z-axis linkage command
|
// 射线源与探测器Z轴联动命令 | Source-Detector Z-axis linkage command
|
||||||
SZDZLockCommand = new DelegateCommand(() => SafeRun(ExecuteSZDZLock), () => IsPlcConnected);
|
SZDZLockCommand = new DelegateCommand(() => SafeRun(ExecuteSZDZLock), () => IsPlcConnected);
|
||||||
@@ -125,11 +125,7 @@ namespace XP.Hardware.MotionControl.ViewModels
|
|||||||
public double DualJoystickOutputX
|
public double DualJoystickOutputX
|
||||||
{
|
{
|
||||||
get => _dualJoystickOutputX;
|
get => _dualJoystickOutputX;
|
||||||
set
|
set => SetProperty(ref _dualJoystickOutputX, value);
|
||||||
{
|
|
||||||
if (SetProperty(ref _dualJoystickOutputX, value))
|
|
||||||
HandleDualJoystickOutput();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private double _dualJoystickOutputY;
|
private double _dualJoystickOutputY;
|
||||||
@@ -430,7 +426,7 @@ namespace XP.Hardware.MotionControl.ViewModels
|
|||||||
if (!_plcService.IsConnected)
|
if (!_plcService.IsConnected)
|
||||||
{
|
{
|
||||||
// PLC 断开:停止所有活跃的 Jog 操作 | PLC disconnected: stop all active jog operations
|
// PLC 断开:停止所有活跃的 Jog 操作 | PLC disconnected: stop all active jog operations
|
||||||
foreach (var axisId in _linearJogActive.Keys)
|
foreach (var axisId in new List<AxisId>(_linearJogActive.Keys))
|
||||||
{
|
{
|
||||||
if (_linearJogActive[axisId])
|
if (_linearJogActive[axisId])
|
||||||
{
|
{
|
||||||
@@ -438,7 +434,7 @@ namespace XP.Hardware.MotionControl.ViewModels
|
|||||||
_logger.Debug("PLC 断开,直线轴 Jog 已标记停止:{AxisId} | PLC disconnected, linear axis jog marked stopped: {AxisId}", axisId);
|
_logger.Debug("PLC 断开,直线轴 Jog 已标记停止:{AxisId} | PLC disconnected, linear axis jog marked stopped: {AxisId}", axisId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (var axisId in _rotaryJogActive.Keys)
|
foreach (var axisId in new List<RotaryAxisId>(_rotaryJogActive.Keys))
|
||||||
{
|
{
|
||||||
if (_rotaryJogActive[axisId])
|
if (_rotaryJogActive[axisId])
|
||||||
{
|
{
|
||||||
@@ -484,12 +480,16 @@ namespace XP.Hardware.MotionControl.ViewModels
|
|||||||
|
|
||||||
if (!result.Success)
|
if (!result.Success)
|
||||||
{
|
{
|
||||||
|
// 写入失败,回滚状态 | Write failed, rollback state
|
||||||
|
IsJoystickEnabled = !IsJoystickEnabled;
|
||||||
MessageBox.Show(result.ErrorMessage, XP.Common.Localization.LocalizationHelper.Get("MC_Error"),
|
MessageBox.Show(result.ErrorMessage, XP.Common.Localization.LocalizationHelper.Get("MC_Error"),
|
||||||
MessageBoxButton.OK, MessageBoxImage.Warning);
|
MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
// 异常时回滚状态 | Rollback state on exception
|
||||||
|
IsJoystickEnabled = !IsJoystickEnabled;
|
||||||
MessageBox.Show(ex.Message, XP.Common.Localization.LocalizationHelper.Get("MC_Error"),
|
MessageBox.Show(ex.Message, XP.Common.Localization.LocalizationHelper.Get("MC_Error"),
|
||||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
}
|
}
|
||||||
@@ -831,7 +831,7 @@ namespace XP.Hardware.MotionControl.ViewModels
|
|||||||
// 如果射线源与探测器Z轴联动,且操作的是SourceZ或DetectorZ,则同时发送两个轴
|
// 如果射线源与探测器Z轴联动,且操作的是SourceZ或DetectorZ,则同时发送两个轴
|
||||||
if (SZDZLock && (propertyName == nameof(SourceZPosition) || propertyName == nameof(DetectorZPosition)))
|
if (SZDZLock && (propertyName == nameof(SourceZPosition) || propertyName == nameof(DetectorZPosition)))
|
||||||
{
|
{
|
||||||
result = SendSourceDetectorZMoveCommand(value);
|
result = SendSourceDetectorZMoveCommand(value, propertyName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -873,7 +873,7 @@ namespace XP.Hardware.MotionControl.ViewModels
|
|||||||
// 如果射线源与探测器Z轴联动,且操作的是SourceZ或DetectorZ,则同时步进两个轴
|
// 如果射线源与探测器Z轴联动,且操作的是SourceZ或DetectorZ,则同时步进两个轴
|
||||||
if (SZDZLock && (propertyName == nameof(SourceZPosition) || propertyName == nameof(DetectorZPosition)))
|
if (SZDZLock && (propertyName == nameof(SourceZPosition) || propertyName == nameof(DetectorZPosition)))
|
||||||
{
|
{
|
||||||
result = SendSourceDetectorZMoveCommand(newValue);
|
result = SendSourceDetectorZMoveCommand(newValue, propertyName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -920,7 +920,7 @@ namespace XP.Hardware.MotionControl.ViewModels
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="targetValue">目标位置 | Target position</param>
|
/// <param name="targetValue">目标位置 | Target position</param>
|
||||||
/// <returns>操作结果 | Operation result</returns>
|
/// <returns>操作结果 | Operation result</returns>
|
||||||
private MotionResult SendSourceDetectorZMoveCommand(double targetValue)
|
private MotionResult SendSourceDetectorZMoveCommand(double targetValue, string sourcePropertyName = null)
|
||||||
{
|
{
|
||||||
// 1. 检查联动是否在配置中启用 | Check if linkage is enabled in config
|
// 1. 检查联动是否在配置中启用 | Check if linkage is enabled in config
|
||||||
if (!_config.SourceDetectorZLinkage.Enabled)
|
if (!_config.SourceDetectorZLinkage.Enabled)
|
||||||
@@ -945,11 +945,27 @@ namespace XP.Hardware.MotionControl.ViewModels
|
|||||||
return MotionResult.Fail("探测器Z轴正在运动中,无法联动移动 | Detector Z-axis is moving, linkage move rejected");
|
return MotionResult.Fail("探测器Z轴正在运动中,无法联动移动 | Detector Z-axis is moving, linkage move rejected");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 计算位移量和目标位置 | Calculate displacement and target positions
|
// 3. 根据编辑来源计算位移量和目标位置 | Calculate displacement and targets based on edit source
|
||||||
var currentSourceZ = sourceZAxis.ActualPosition;
|
var currentSourceZ = sourceZAxis.ActualPosition;
|
||||||
var currentDetectorZ = detectorZAxis.ActualPosition;
|
var currentDetectorZ = detectorZAxis.ActualPosition;
|
||||||
var sourceDelta = targetValue - currentSourceZ;
|
|
||||||
var targetDetectorZ = currentDetectorZ + sourceDelta;
|
double targetSourceZ;
|
||||||
|
double targetDetectorZ;
|
||||||
|
|
||||||
|
if (sourcePropertyName == nameof(DetectorZPosition))
|
||||||
|
{
|
||||||
|
// 用户编辑的是探测器Z:以探测器Z为基准计算位移 | User edited DetectorZ: calculate delta from DetectorZ
|
||||||
|
var delta = targetValue - currentDetectorZ;
|
||||||
|
targetDetectorZ = targetValue;
|
||||||
|
targetSourceZ = currentSourceZ + delta;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 用户编辑的是射线源Z(默认):以射线源Z为基准计算位移 | User edited SourceZ (default): calculate delta from SourceZ
|
||||||
|
var delta = targetValue - currentSourceZ;
|
||||||
|
targetSourceZ = targetValue;
|
||||||
|
targetDetectorZ = currentDetectorZ + delta;
|
||||||
|
}
|
||||||
|
|
||||||
// 4. 边界检查(使用配置中的 Min/Max)| Boundary check (use Min/Max from config)
|
// 4. 边界检查(使用配置中的 Min/Max)| Boundary check (use Min/Max from config)
|
||||||
if (_config.LinearAxes.TryGetValue(AxisId.SourceZ, out var sourceConfig) &&
|
if (_config.LinearAxes.TryGetValue(AxisId.SourceZ, out var sourceConfig) &&
|
||||||
@@ -957,10 +973,10 @@ namespace XP.Hardware.MotionControl.ViewModels
|
|||||||
{
|
{
|
||||||
var errors = new List<string>();
|
var errors = new List<string>();
|
||||||
|
|
||||||
if (targetValue < sourceConfig.Min || targetValue > sourceConfig.Max)
|
if (targetSourceZ < sourceConfig.Min || targetSourceZ > sourceConfig.Max)
|
||||||
{
|
{
|
||||||
errors.Add($"射线源Z轴目标位置 {targetValue} 超出范围 [{sourceConfig.Min}, {sourceConfig.Max}] | " +
|
errors.Add($"射线源Z轴目标位置 {targetSourceZ} 超出范围 [{sourceConfig.Min}, {sourceConfig.Max}] | " +
|
||||||
$"Source Z-axis target {targetValue} out of range [{sourceConfig.Min}, {sourceConfig.Max}]");
|
$"Source Z-axis target {targetSourceZ} out of range [{sourceConfig.Min}, {sourceConfig.Max}]");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetDetectorZ < detectorConfig.Min || targetDetectorZ > detectorConfig.Max)
|
if (targetDetectorZ < detectorConfig.Min || targetDetectorZ > detectorConfig.Max)
|
||||||
@@ -983,7 +999,7 @@ namespace XP.Hardware.MotionControl.ViewModels
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 5. 所有检查通过,同时发送两个轴的移动命令 | All checks passed, send move commands to both axes simultaneously
|
// 5. 所有检查通过,同时发送两个轴的移动命令 | All checks passed, send move commands to both axes simultaneously
|
||||||
var sourceResult = sourceZAxis.MoveToTarget(targetValue, _config.DefaultVelocity);
|
var sourceResult = sourceZAxis.MoveToTarget(targetSourceZ, _config.DefaultVelocity);
|
||||||
var detectorResult = detectorZAxis.MoveToTarget(targetDetectorZ, _config.DefaultVelocity);
|
var detectorResult = detectorZAxis.MoveToTarget(targetDetectorZ, _config.DefaultVelocity);
|
||||||
|
|
||||||
// 6. 返回结果(任一失败都记录日志)| Return result (log if any fails)
|
// 6. 返回结果(任一失败都记录日志)| Return result (log if any fails)
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||||
|
<Config>
|
||||||
|
<Group ID="WriteCommon" DBNumber="31">
|
||||||
|
<Signal Name="SoftLive" Type="byte" StartAddr="0" IndexOrLength="" Remark="软件心跳,01周期变化表示PLC存活" />
|
||||||
|
<Signal Name="MC_SourceZ_Target" Type="single" StartAddr="10" IndexOrLength="" Remark="射线源Z目标位置" />
|
||||||
|
<Signal Name="MC_SourceZ_Speed" Type="single" StartAddr="14" IndexOrLength="" Remark="射线源Z运动速度" />
|
||||||
|
<Signal Name="MC_SourceZ_JogPos" Type="byte" StartAddr="18" IndexOrLength="" Remark="射线源Z正向Jog,0:缺省,1:正向点动" />
|
||||||
|
<Signal Name="MC_SourceZ_JogNeg" Type="byte" StartAddr="19" IndexOrLength="" Remark="射线源Z反向Jog,0:缺省,1:反向点动" />
|
||||||
|
<Signal Name="MC_SourceZ_Home" Type="byte" StartAddr="20" IndexOrLength="" Remark="射线源Z回零,0:缺省,1:触发回零" />
|
||||||
|
<Signal Name="MC_SourceZ_Stop" Type="byte" StartAddr="21" IndexOrLength="" Remark="射线源Z停止,0:缺省,1:触发停止" />
|
||||||
|
<Signal Name="MC_DetZ_Target" Type="single" StartAddr="22" IndexOrLength="" Remark="探测器Z目标位置" />
|
||||||
|
<Signal Name="MC_DetZ_Speed" Type="single" StartAddr="26" IndexOrLength="" Remark="探测器Z运动速度" />
|
||||||
|
<Signal Name="MC_DetZ_JogPos" Type="byte" StartAddr="30" IndexOrLength="" Remark="探测器Z正向Jog,0:缺省,1:正向点动" />
|
||||||
|
<Signal Name="MC_DetZ_JogNeg" Type="byte" StartAddr="31" IndexOrLength="" Remark="探测器Z反向Jog,0:缺省,1:反向点动" />
|
||||||
|
<Signal Name="MC_DetZ_Home" Type="byte" StartAddr="32" IndexOrLength="" Remark="探测器Z回零,0:缺省,1:触发回零" />
|
||||||
|
<Signal Name="MC_DetZ_Stop" Type="byte" StartAddr="33" IndexOrLength="" Remark="探测器Z停止,0:缺省,1:触发停止" />
|
||||||
|
<Signal Name="MC_StageX_Target" Type="single" StartAddr="34" IndexOrLength="" Remark="载物台X目标位置" />
|
||||||
|
<Signal Name="MC_StageX_Speed" Type="single" StartAddr="38" IndexOrLength="" Remark="载物台X运动速度" />
|
||||||
|
<Signal Name="MC_StageX_JogPos" Type="byte" StartAddr="42" IndexOrLength="" Remark="载物台X正向Jog,0:缺省,1:正向点动" />
|
||||||
|
<Signal Name="MC_StageX_JogNeg" Type="byte" StartAddr="43" IndexOrLength="" Remark="载物台X反向Jog,0:缺省,1:反向点动" />
|
||||||
|
<Signal Name="MC_StageX_Home" Type="byte" StartAddr="44" IndexOrLength="" Remark="载物台X回零,0:缺省,1:触发回零" />
|
||||||
|
<Signal Name="MC_StageX_Stop" Type="byte" StartAddr="45" IndexOrLength="" Remark="载物台X停止,0:缺省,1:触发停止" />
|
||||||
|
<Signal Name="MC_StageY_Target" Type="single" StartAddr="46" IndexOrLength="" Remark="载物台Y目标位置" />
|
||||||
|
<Signal Name="MC_StageY_Speed" Type="single" StartAddr="50" IndexOrLength="" Remark="载物台Y运动速度" />
|
||||||
|
<Signal Name="MC_StageY_JogPos" Type="byte" StartAddr="54" IndexOrLength="" Remark="载物台Y正向Jog,0:缺省,1:正向点动" />
|
||||||
|
<Signal Name="MC_StageY_JogNeg" Type="byte" StartAddr="55" IndexOrLength="" Remark="载物台Y反向Jog,0:缺省,1:反向点动" />
|
||||||
|
<Signal Name="MC_StageY_Home" Type="byte" StartAddr="56" IndexOrLength="" Remark="载物台Y回零,0:缺省,1:触发回零" />
|
||||||
|
<Signal Name="MC_StageY_Stop" Type="byte" StartAddr="57" IndexOrLength="" Remark="载物台Y停止,0:缺省,1:触发停止" />
|
||||||
|
<Signal Name="MC_DetSwing_Target" Type="single" StartAddr="58" IndexOrLength="" Remark="探测器摆动目标角度" />
|
||||||
|
<Signal Name="MC_DetSwing_Speed" Type="single" StartAddr="62" IndexOrLength="" Remark="探测器摆动运动速度" />
|
||||||
|
<Signal Name="MC_DetSwing_JogPos" Type="byte" StartAddr="66" IndexOrLength="" Remark="探测器摆动正向Jog,0:缺省,1:正向点动" />
|
||||||
|
<Signal Name="MC_DetSwing_JogNeg" Type="byte" StartAddr="67" IndexOrLength="" Remark="探测器摆动反向Jog,0:缺省,1:反向点动" />
|
||||||
|
<Signal Name="MC_DetSwing_Home" Type="byte" StartAddr="68" IndexOrLength="" Remark="探测器摆动回零,0:缺省,1:触发回零" />
|
||||||
|
<Signal Name="MC_DetSwing_Stop" Type="byte" StartAddr="69" IndexOrLength="" Remark="探测器摆动停止,0:缺省,1:触发停止" />
|
||||||
|
<Signal Name="MC_StageRot_Target" Type="single" StartAddr="70" IndexOrLength="" Remark="载物台旋转目标角度" />
|
||||||
|
<Signal Name="MC_StageRot_Speed" Type="single" StartAddr="74" IndexOrLength="" Remark="载物台旋转运动速度" />
|
||||||
|
<Signal Name="MC_StageRot_JogPos" Type="byte" StartAddr="78" IndexOrLength="" Remark="载物台旋转正向Jog,0:缺省,1:正向点动" />
|
||||||
|
<Signal Name="MC_StageRot_JogNeg" Type="byte" StartAddr="79" IndexOrLength="" Remark="载物台旋转反向Jog,0:缺省,1:反向点动" />
|
||||||
|
<Signal Name="MC_StageRot_Home" Type="byte" StartAddr="80" IndexOrLength="" Remark="载物台旋转回零,0:缺省,1:触发回零" />
|
||||||
|
<Signal Name="MC_StageRot_Stop" Type="byte" StartAddr="81" IndexOrLength="" Remark="载物台旋转停止,0:缺省,1:触发停止" />
|
||||||
|
<Signal Name="MC_FixRot_Target" Type="single" StartAddr="82" IndexOrLength="" Remark="夹具旋转目标角度" />
|
||||||
|
<Signal Name="MC_FixRot_Speed" Type="single" StartAddr="86" IndexOrLength="" Remark="夹具旋转运动速度" />
|
||||||
|
<Signal Name="MC_FixRot_JogPos" Type="byte" StartAddr="90" IndexOrLength="" Remark="夹具旋转正向Jog,0:缺省,1:正向点动" />
|
||||||
|
<Signal Name="MC_FixRot_JogNeg" Type="byte" StartAddr="91" IndexOrLength="" Remark="夹具旋转反向Jog,0:缺省,1:反向点动" />
|
||||||
|
<Signal Name="MC_FixRot_Home" Type="byte" StartAddr="92" IndexOrLength="" Remark="夹具旋转回零,0:缺省,1:触发回零" />
|
||||||
|
<Signal Name="MC_FixRot_Stop" Type="byte" StartAddr="93" IndexOrLength="" Remark="夹具旋转停止,0:缺省,1:触发停止" />
|
||||||
|
<Signal Name="MC_Door_Open" Type="byte" StartAddr="94" IndexOrLength="" Remark="安全门开门,0:缺省,1:触发开门" />
|
||||||
|
<Signal Name="MC_Door_Close" Type="byte" StartAddr="95" IndexOrLength="" Remark="安全门关门,0:缺省,1:触发关门" />
|
||||||
|
<Signal Name="MC_Door_Stop" Type="byte" StartAddr="96" IndexOrLength="" Remark="安全门停止,0:缺省,1:触发停止" />
|
||||||
|
<Signal Name="MC_VirtualJoystick_Enable" Type="bool" StartAddr="111" IndexOrLength="" Remark="虚拟摇杆使能"/>
|
||||||
|
<Signal Name="MC_SourceDetZ_Linkage_Enable" Type="bool" StartAddr="101" IndexOrLength="" Remark="联动使能"/>
|
||||||
|
</Group>
|
||||||
|
<Group ID="ReadCommon" DBNumber="31">
|
||||||
|
<Signal Name="PlcLive" Type="byte" StartAddr="200" IndexOrLength="" Remark="PLC心跳,01周期变化表示PLC存活" />
|
||||||
|
<Signal Name="PlcAlarm" Type="byte" StartAddr="201" IndexOrLength="" Remark="系统报警,0:缺省,10:有报警" />
|
||||||
|
<Signal Name="MC_SourceZ_Pos" Type="single" StartAddr="100" IndexOrLength="" Remark="射线源Z实际位置" />
|
||||||
|
<Signal Name="MC_DetZ_Pos" Type="single" StartAddr="104" IndexOrLength="" Remark="探测器Z实际位置" />
|
||||||
|
<Signal Name="MC_StageX_Pos" Type="single" StartAddr="108" IndexOrLength="" Remark="载物台X实际位置" />
|
||||||
|
<Signal Name="MC_StageY_Pos" Type="single" StartAddr="112" IndexOrLength="" Remark="载物台Y实际位置" />
|
||||||
|
<Signal Name="MC_DetSwing_Angle" Type="single" StartAddr="116" IndexOrLength="" Remark="探测器摆动实际角度" />
|
||||||
|
<Signal Name="MC_StageRot_Angle" Type="single" StartAddr="120" IndexOrLength="" Remark="载物台旋转实际角度" />
|
||||||
|
<Signal Name="MC_FixRot_Angle" Type="single" StartAddr="124" IndexOrLength="" Remark="夹具旋转实际角度" />
|
||||||
|
<Signal Name="MC_Door_Status" Type="byte" StartAddr="128" IndexOrLength="" Remark="安全门状态,0:未知,1:正在开门,2:已开,3:正在关门,4:已关,5:已锁定,6:故障" />
|
||||||
|
<Signal Name="MC_Door_Interlock" Type="byte" StartAddr="130" IndexOrLength="" Remark="安全门联锁信号,0:缺省(无联锁),10:联锁有效(禁止开门)" />
|
||||||
|
<Signal Name="MC_Joystick_Active" Type="bool" StartAddr="110" IndexOrLength="" Remark="实体摇杆输入"/>
|
||||||
|
</Group>
|
||||||
|
<Group ID="Status" DBNumber="4100">
|
||||||
|
<Signal Name="ScanMode" Type="byte" StartAddr="201" IndexOrLength="" Remark="扫描模式,0:缺省(空闲),具体值由PLC定义" />
|
||||||
|
</Group>
|
||||||
|
</Config>
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
[sys1____]
|
||||||
|
"SerialNumber"
|
||||||
|
[geo_dm__#Cougar]
|
||||||
|
"Name9"
|
||||||
|
"Value9"
|
||||||
|
"Name10"
|
||||||
|
"Value10"
|
||||||
|
"Name19"
|
||||||
|
"Value19"
|
||||||
|
"Name21"
|
||||||
|
"Value21"
|
||||||
|
"Name24"
|
||||||
|
"Value24"
|
||||||
|
"Name29"
|
||||||
|
"Value29"
|
||||||
|
"Name30"
|
||||||
|
"Value30"
|
||||||
|
"Name48"
|
||||||
|
"Value48"
|
||||||
|
[geo_dm__#Cheetah]
|
||||||
|
"Name9"
|
||||||
|
"Value9"
|
||||||
|
"Name10"
|
||||||
|
"Value10"
|
||||||
|
"Name12"
|
||||||
|
"Value12"
|
||||||
|
"Name13"
|
||||||
|
"Value13"
|
||||||
|
"Name22"
|
||||||
|
"Value22"
|
||||||
|
"Name24"
|
||||||
|
"Value24"
|
||||||
|
"Name27"
|
||||||
|
"Value27"
|
||||||
|
"Name48"
|
||||||
|
"Value48"
|
||||||
|
[joyspeed]
|
||||||
|
"Speed0"
|
||||||
|
"Speed1"
|
||||||
|
"Speed2"
|
||||||
|
"Speed3"
|
||||||
|
"Speed4"
|
||||||
|
"Speed5"
|
||||||
|
"Speed6"
|
||||||
|
"Speed7"
|
||||||
|
"Speed8"
|
||||||
|
"Speed9"
|
||||||
|
[loadpos_]
|
||||||
|
"SafePos[3]"
|
||||||
|
[para_1__]
|
||||||
|
"PosSW_End"
|
||||||
|
"NegSW_End"
|
||||||
|
"RefPosition"
|
||||||
|
[para_2__]
|
||||||
|
"PosSW_End"
|
||||||
|
"NegSW_End"
|
||||||
|
"RefPosition"
|
||||||
|
[para_3__]
|
||||||
|
"PosSW_End"
|
||||||
|
"NegSW_End"
|
||||||
|
"RefPosition"
|
||||||
|
[para_4__]
|
||||||
|
"PosSW_End"
|
||||||
|
"NegSW_End"
|
||||||
|
"RefPosition"
|
||||||
|
"RefPositionEnd"
|
||||||
|
[para_5__]
|
||||||
|
"PosSW_End"
|
||||||
|
"NegSW_End"
|
||||||
|
"RefPosition"
|
||||||
|
[para_6__]
|
||||||
|
"PosSW_End"
|
||||||
|
"NegSW_End"
|
||||||
|
"RefPosition"
|
||||||
|
"DistPerTurn"
|
||||||
|
[para_7__]
|
||||||
|
"PosSW_End"
|
||||||
|
"NegSW_End"
|
||||||
|
"RefPosition"
|
||||||
|
[para_8__]
|
||||||
|
"PosSW_End"
|
||||||
|
"NegSW_End"
|
||||||
|
"RefPosition"
|
||||||
|
[para_9__]
|
||||||
|
"PosSW_End"
|
||||||
|
"NegSW_End"
|
||||||
|
"RefPosition"
|
||||||
|
[dm_door_]
|
||||||
|
"DoorOpenSwitchAvail#410"
|
||||||
|
EOF
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
[MODEDM#all]
|
||||||
|
"everything"
|
||||||
|
"beginExceptions"
|
||||||
|
"Version"
|
||||||
|
"endExceptions"
|
||||||
|
!*************************************************************
|
||||||
|
[TARGETDM#all]
|
||||||
|
"everything"
|
||||||
|
"beginExceptions"
|
||||||
|
"Version"
|
||||||
|
"endExceptions"
|
||||||
|
!*************************************************************
|
||||||
|
[TUBEDM#all]
|
||||||
|
"everything"
|
||||||
|
"beginExceptions"
|
||||||
|
"Version"
|
||||||
|
"endExceptions"
|
||||||
|
!*************************************************************
|
||||||
|
[HSGDM#all]
|
||||||
|
"everything"
|
||||||
|
"beginExceptions"
|
||||||
|
"Version"
|
||||||
|
"endExceptions"
|
||||||
|
!*************************************************************
|
||||||
|
[SYSDM#all]
|
||||||
|
"everything"
|
||||||
|
"beginExceptions"
|
||||||
|
"Version"
|
||||||
|
"SoftwareVersionPLC"
|
||||||
|
"SysConfig"
|
||||||
|
"SoftwareVersion"
|
||||||
|
"endExceptions"
|
||||||
|
!*************************************************************
|
||||||
|
[AMPDM#all]
|
||||||
|
"everything"
|
||||||
|
"beginExceptions"
|
||||||
|
"Version"
|
||||||
|
"endExceptions"
|
||||||
|
!*************************************************************
|
||||||
|
[VACDM#all]
|
||||||
|
"everything"
|
||||||
|
"beginExceptions"
|
||||||
|
"Version_vacuum_system"
|
||||||
|
"endExceptions"
|
||||||
|
!*************************************************************
|
||||||
|
[CENTDM#all]
|
||||||
|
"everything"
|
||||||
|
"beginExceptions"
|
||||||
|
"Version"
|
||||||
|
"endExceptions"
|
||||||
|
!*************************************************************
|
||||||
|
[FOCUSDM#all]
|
||||||
|
"everything"
|
||||||
|
"beginExceptions"
|
||||||
|
"Version"
|
||||||
|
"endExceptions"
|
||||||
|
!*************************************************************
|
||||||
|
[CONSDM#all]
|
||||||
|
"everything"
|
||||||
|
"beginExceptions"
|
||||||
|
"Version"
|
||||||
|
"endExceptions"
|
||||||
|
!*************************************************************
|
||||||
|
[TREGDM#all]
|
||||||
|
"everything"
|
||||||
|
"beginExceptions"
|
||||||
|
"Version"
|
||||||
|
"endExceptions"
|
||||||
|
!*************************************************************
|
||||||
|
[CONDDM#all]
|
||||||
|
"everything"
|
||||||
|
"beginExceptions"
|
||||||
|
"Version"
|
||||||
|
"endExceptions"
|
||||||
|
!*************************************************************
|
||||||
|
[FILDM#all]
|
||||||
|
"everything"
|
||||||
|
"beginExceptions"
|
||||||
|
"Version"
|
||||||
|
"endExceptions"
|
||||||
|
!*************************************************************
|
||||||
|
[TUBEHEADDM#all]
|
||||||
|
"everything"
|
||||||
|
"beginExceptions"
|
||||||
|
"version"
|
||||||
|
"endExceptions"
|
||||||
|
!*************************************************************
|
||||||
|
[INITDM#all]
|
||||||
|
"everything"
|
||||||
|
"beginExceptions"
|
||||||
|
"version"
|
||||||
|
"endExceptions"
|
||||||
|
EOF
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// Flag, ob die Trace-Meldungen asynchron zu protokolliern sind: 1 für asynchron, 0 für synchron.
|
||||||
|
1
|
||||||
|
// Kategorie Konfigurationen: <Kategorie-Name> <Enabled[0/1]>
|
||||||
|
FXDriver 0
|
||||||
|
FXDriverPviXCreateResponse 0
|
||||||
|
FXDriverUpgradeCP1483ToCP1583 0
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,294 @@
|
|||||||
|
[XRaySystemErrors]
|
||||||
|
ErrorNumber0=101
|
||||||
|
ErrorString0="Data module init error"
|
||||||
|
ErrorNumber1=102
|
||||||
|
ErrorString1="Data module sys error"
|
||||||
|
ErrorNumber2=103
|
||||||
|
ErrorString2="Data module amp error"
|
||||||
|
ErrorNumber3=301
|
||||||
|
ErrorString3="Timeout during filament adjusting"
|
||||||
|
ErrorNumber4=302
|
||||||
|
ErrorString4="Timeout during warmup"
|
||||||
|
ErrorNumber5=303
|
||||||
|
ErrorString5="Error door control"
|
||||||
|
ErrorNumber6=401
|
||||||
|
ErrorString6="Defective warn lamp 1"
|
||||||
|
ErrorNumber7=402
|
||||||
|
ErrorString7="Defective warn lamp 2"
|
||||||
|
ErrorNumber8=403
|
||||||
|
ErrorString8="Defective warn lamp 3"
|
||||||
|
ErrorNumber9=404
|
||||||
|
ErrorString9="Cooling defect"
|
||||||
|
ErrorNumber10=405
|
||||||
|
ErrorString10="Error COM2"
|
||||||
|
ErrorNumber11=406
|
||||||
|
ErrorString12="Error COM2"
|
||||||
|
ErrorNumber13=407
|
||||||
|
ErrorString13="Error COM2"
|
||||||
|
ErrorNumber14=408
|
||||||
|
ErrorString14="Error COM2"
|
||||||
|
ErrorNumber15=601
|
||||||
|
ErrorString15="Defective warn lamp 1"
|
||||||
|
ErrorNumber16=602
|
||||||
|
ErrorString16="Defective warn lamp 2"
|
||||||
|
ErrorNumber17=603
|
||||||
|
ErrorString17="Defective warn lamp 3"
|
||||||
|
ErrorNumber18=604
|
||||||
|
ErrorString18="Cooling defect"
|
||||||
|
ErrorNumber19=605
|
||||||
|
ErrorString19="Error COM2"
|
||||||
|
|
||||||
|
[HSGErrors]
|
||||||
|
ErrorNumber0=101
|
||||||
|
ErrorString0="Data module error"
|
||||||
|
ErrorNumber1=201
|
||||||
|
ErrorString1="Underflow of actual accelerating voltage"
|
||||||
|
ErrorNumber2=202
|
||||||
|
ErrorString2="Overflow of actual accelerating voltage"
|
||||||
|
ErrorNumber3=203
|
||||||
|
ErrorString3="Underflow of actual tube current"
|
||||||
|
ErrorNumber4=204
|
||||||
|
ErrorString4="Overflow of actual tube current"
|
||||||
|
ErrorNumber5=205
|
||||||
|
ErrorString5="Underflow of actual filament current"
|
||||||
|
ErrorNumber6=206
|
||||||
|
ErrorString6="Overflow of actual filament current"
|
||||||
|
ErrorNumber7=301
|
||||||
|
ErrorString7="Timeout acceleration voltage"
|
||||||
|
ErrorNumber8=302
|
||||||
|
ErrorString8="Timeout tube current"
|
||||||
|
ErrorNumber9=303
|
||||||
|
ErrorString9="Timeout filament adjust"
|
||||||
|
ErrorNumber10=402
|
||||||
|
ErrorString10="High voltage generator overload"
|
||||||
|
ErrorNumber11=403
|
||||||
|
ErrorString11="No filament current"
|
||||||
|
ErrorNumber12=501
|
||||||
|
ErrorString12="Overvlow of nominal filament current"
|
||||||
|
ErrorNumber13=502
|
||||||
|
ErrorString13="Overflow or underflow of nominal accelerating voltage"
|
||||||
|
ErrorNumber14=503
|
||||||
|
ErrorString14="Overflow of nominal tube current"
|
||||||
|
ErrorNumber15=510
|
||||||
|
ErrorString15="Error during filament adjust step 30"
|
||||||
|
ErrorNumber16=520
|
||||||
|
ErrorString16="Nominal filament current smaller than filament offset"
|
||||||
|
ErrorNumber17=524
|
||||||
|
ErrorString17="Filament working current exceeds limit during filament adjust"
|
||||||
|
ErrorNumber18=525
|
||||||
|
ErrorString18="Filament working current exceeds limit during filament adjust"
|
||||||
|
ErrorNumber19=526
|
||||||
|
ErrorString19="Nominal filament current smaller than filament offset during filament adjust"
|
||||||
|
ErrorNumber19=527
|
||||||
|
ErrorString19="Nominal filament current smaller than filament offset during filament adjust"
|
||||||
|
|
||||||
|
[TubeErrors]
|
||||||
|
ErrorNumber0=101
|
||||||
|
ErrorString0="Data module error"
|
||||||
|
ErrorNumber1=102
|
||||||
|
ErrorString1="Data module focus table created"
|
||||||
|
ErrorNumber2=103
|
||||||
|
ErrorString2="Focus data module write error"
|
||||||
|
ErrorNumber3=104
|
||||||
|
ErrorString3="Focus data module error"
|
||||||
|
ErrorNumber4=105
|
||||||
|
ErrorString4="Focus table data module info error"
|
||||||
|
ErrorNumber5=106
|
||||||
|
ErrorString5="Focus table data module read error"
|
||||||
|
ErrorNumber6=107
|
||||||
|
ErrorString6="Condensor data module error"
|
||||||
|
ErrorNumber7=108
|
||||||
|
ErrorString7="Data module condensor table created"
|
||||||
|
ErrorNumber8=109
|
||||||
|
ErrorString8="Condensor table data module info error"
|
||||||
|
ErrorNumber9=110
|
||||||
|
ErrorString9="Condensor table data module read error"
|
||||||
|
ErrorNumber10=111
|
||||||
|
ErrorString10="Centering 1 / Centering 2 / Centering 3 data module error"
|
||||||
|
ErrorNumber11=114
|
||||||
|
ErrorString11="Centering table 1 data module error"
|
||||||
|
ErrorNumber12=115
|
||||||
|
ErrorString12="Centering table 2 data module error"
|
||||||
|
ErrorNumber13=116
|
||||||
|
ErrorString13="Centering table 3 data module error"
|
||||||
|
ErrorNumber14=117
|
||||||
|
ErrorString14="Conditioning data module error"
|
||||||
|
ErrorNumber15=118
|
||||||
|
ErrorString15="Read focus data module error"
|
||||||
|
ErrorNumber16=119
|
||||||
|
ErrorString16="Write focus data module error"
|
||||||
|
ErrorNumber17=120
|
||||||
|
ErrorString17="Read default focus data module error"
|
||||||
|
ErrorNumber18=121
|
||||||
|
ErrorString18="Write default focus data module error"
|
||||||
|
ErrorNumber19=122
|
||||||
|
ErrorString19="Read condensor data module error"
|
||||||
|
ErrorNumber20=123
|
||||||
|
ErrorString20="Write condensor data module error"
|
||||||
|
ErrorNumber21=124
|
||||||
|
ErrorString21="Read default condensor data module error"
|
||||||
|
ErrorNumber22=125
|
||||||
|
ErrorString22="Write default condensor data module error"
|
||||||
|
ErrorNumber23=126
|
||||||
|
ErrorString23="Read centering 1 data module error"
|
||||||
|
ErrorNumber24=127
|
||||||
|
ErrorString24="Read centering 2 data module error"
|
||||||
|
ErrorNumber25=128
|
||||||
|
ErrorString25="Read centering 3 data module error"
|
||||||
|
ErrorNumber26=129
|
||||||
|
ErrorString26="Write centering 1 data module error"
|
||||||
|
ErrorNumber27=130
|
||||||
|
ErrorString27="Write centering 2 data module error"
|
||||||
|
ErrorNumber28=131
|
||||||
|
ErrorString28="Write centering 3 data module error"
|
||||||
|
ErrorNumber29=132
|
||||||
|
ErrorString29="Read default centering 1 data module error"
|
||||||
|
ErrorNumber30=133
|
||||||
|
ErrorString30="Read default centering 2 data module error"
|
||||||
|
ErrorNumber31=134
|
||||||
|
ErrorString31="Read default centering 3 data module error"
|
||||||
|
ErrorNumber32=135
|
||||||
|
ErrorString32="Write default centering 1 data module error"
|
||||||
|
ErrorNumber33=136
|
||||||
|
ErrorString33="Write default centering 2 data module error"
|
||||||
|
ErrorNumber34=137
|
||||||
|
ErrorString34="Write default centering 3 data module error"
|
||||||
|
ErrorNumber35=140
|
||||||
|
ErrorString35="Shutter data module error"
|
||||||
|
ErrorNumber36=141
|
||||||
|
ErrorString36="Data module shutter created"
|
||||||
|
ErrorNumber37=142
|
||||||
|
ErrorString37="Shutter table data module info error"
|
||||||
|
ErrorNumber38=143
|
||||||
|
ErrorString38="Shutter table data module read error"
|
||||||
|
ErrorNumber39=144
|
||||||
|
ErrorString39="Scan data module error"
|
||||||
|
ErrorNumber40=145
|
||||||
|
ErrorString40="Scan table data module error"
|
||||||
|
ErrorNumber41=146
|
||||||
|
ErrorString41="Ti_Reg data module error"
|
||||||
|
ErrorNumber42=147
|
||||||
|
ErrorString42="dm_ken (focus) data module error"
|
||||||
|
ErrorNumber43=148
|
||||||
|
ErrorString43="dm_ken (condensor) data module error"
|
||||||
|
ErrorNumber44=149
|
||||||
|
ErrorString44="Mode_x data module error"
|
||||||
|
ErrorNumber45=150
|
||||||
|
ErrorString45="burn data module error"
|
||||||
|
ErrorNumber46=151
|
||||||
|
ErrorString46="tube_cur data module error"
|
||||||
|
ErrorNumber47=152
|
||||||
|
ErrorString47="Tubehead data module error"
|
||||||
|
ErrorNumber48=153
|
||||||
|
ErrorString48="Target data module error"
|
||||||
|
ErrorNumber49=154
|
||||||
|
ErrorString49="read_def_tube_cur data module error"
|
||||||
|
ErrorNumber50=155
|
||||||
|
ErrorString50="write_def_tube_cur data module error"
|
||||||
|
ErrorNumber51=156
|
||||||
|
ErrorString51="Filament data module error"
|
||||||
|
ErrorNumber52=201
|
||||||
|
ErrorString52="Underflow of actual target (amp1) current"
|
||||||
|
ErrorNumber53=202
|
||||||
|
ErrorString53="Overflow of actual target (amp1) current"
|
||||||
|
ErrorNumber54=203
|
||||||
|
ErrorString54="Underflow of actual target (amp2) current"
|
||||||
|
ErrorNumber55=204
|
||||||
|
ErrorString55="Overflow of actual target (amp2) current"
|
||||||
|
ErrorNumber56=205
|
||||||
|
ErrorString56="Underflow of actual amp3 current"
|
||||||
|
ErrorNumber57=206
|
||||||
|
ErrorString57="Overflow of actual amp3 current"
|
||||||
|
ErrorNumber58=301
|
||||||
|
ErrorString58="Time limit for centering current overflow exeeded, x-ray switched off"
|
||||||
|
ErrorNumber59=302
|
||||||
|
ErrorString59="Time limit for shutter exceeded, xray switched off"
|
||||||
|
ErrorNumber60=401
|
||||||
|
ErrorString60="Overflow of target power"
|
||||||
|
ErrorNumber61=402
|
||||||
|
ErrorString61="Missing amplifier"
|
||||||
|
ErrorNumber62=403
|
||||||
|
ErrorString62="Scanning coil temperature overflow"
|
||||||
|
ErrorNumber63=501
|
||||||
|
ErrorString63="Overflow of nominal focus current"
|
||||||
|
ErrorNumber64=502
|
||||||
|
ErrorString64="Overflow of nominal centering current x"
|
||||||
|
ErrorNumber65=503
|
||||||
|
ErrorString65="Overflow of nominal centering current y"
|
||||||
|
ErrorNumber66=504
|
||||||
|
ErrorString66="Overflow of nominal centering current"
|
||||||
|
ErrorNumber67=505
|
||||||
|
ErrorString67="Overflow of nominal shutter current"
|
||||||
|
ErrorNumber68=506
|
||||||
|
ErrorString68="Overflow of actual focus current"
|
||||||
|
ErrorNumber69=507
|
||||||
|
ErrorString69="Negative focus current"
|
||||||
|
ErrorNumber70=611
|
||||||
|
ErrorString70="Error during autocentering (plane 1)"
|
||||||
|
ErrorNumber71=612
|
||||||
|
ErrorString71="Error during autocentering (plane 1)"
|
||||||
|
ErrorNumber72=613
|
||||||
|
ErrorString72="Error during autocentering (plane 1)"
|
||||||
|
ErrorNumber73=614
|
||||||
|
ErrorString73="Error during autocentering (plane 1)"
|
||||||
|
ErrorNumber74=615
|
||||||
|
ErrorString74="Error during autocentering (plane 1)"
|
||||||
|
ErrorNumber75=616
|
||||||
|
ErrorString75="Error during autocentering (plane 1)"
|
||||||
|
ErrorNumber76=617
|
||||||
|
ErrorString76="Max. number of runs for autocentering exceeded (plane 1)"
|
||||||
|
ErrorNumber77=618
|
||||||
|
ErrorString77="Centering current exceeded (plane 1)"
|
||||||
|
ErrorNumber78=621
|
||||||
|
ErrorString78="Error during autocentering (plane 2)"
|
||||||
|
ErrorNumber79=622
|
||||||
|
ErrorString79="Error during autocentering (plane 2)"
|
||||||
|
ErrorNumber80=623
|
||||||
|
ErrorString80="Error during autocentering (plane 2)"
|
||||||
|
ErrorNumber81=624
|
||||||
|
ErrorString81="Error during autocentering (plane 2)"
|
||||||
|
ErrorNumber82=625
|
||||||
|
ErrorString82="Error during autocentering (plane 2)"
|
||||||
|
ErrorNumber83=626
|
||||||
|
ErrorString83="Error during autocentering (plane 2)"
|
||||||
|
ErrorNumber84=627
|
||||||
|
ErrorString84="Max. number of runs for autocentering exceeded (plane 2)"
|
||||||
|
ErrorNumber85=628
|
||||||
|
ErrorString85="Centering current exceeded (plane 2)"
|
||||||
|
ErrorNumber86=631
|
||||||
|
ErrorString86="Error during autocentering (plane 3)"
|
||||||
|
ErrorNumber87=632
|
||||||
|
ErrorString87="Error during autocentering (plane 3)"
|
||||||
|
ErrorNumber88=633
|
||||||
|
ErrorString88="Error during autocentering (plane 3)"
|
||||||
|
ErrorNumber89=634
|
||||||
|
ErrorString89="Error during autocentering (plane 3)"
|
||||||
|
ErrorNumber90=635
|
||||||
|
ErrorString90="Error during autocentering (plane 3)"
|
||||||
|
ErrorNumber91=636
|
||||||
|
ErrorString91="Error during autocentering (plane 3)"
|
||||||
|
ErrorNumber92=637
|
||||||
|
ErrorString92="Max. number of runs for autocentering exceeded (plane 3)"
|
||||||
|
ErrorNumber93=638
|
||||||
|
ErrorString93="Centering current exceeded (plane 3)"
|
||||||
|
|
||||||
|
|
||||||
|
[VacuumErrors]
|
||||||
|
ErrorNumber1=101
|
||||||
|
ErrorString1="Data module error"
|
||||||
|
ErrorNumber2=201
|
||||||
|
ErrorString2="Underflow of actual vacuum value"
|
||||||
|
ErrorNumber3=202
|
||||||
|
ErrorString3="Overflow of actual vacuum value"
|
||||||
|
ErrorNumber4=301
|
||||||
|
ErrorString4="Timeout vacuum"
|
||||||
|
ErrorNumber5=301
|
||||||
|
ErrorString5="Timeout vacuum breakdown"
|
||||||
|
ErrorNumber6=401
|
||||||
|
ErrorString6="Bad vacuum during X-ray on"
|
||||||
|
|
||||||
|
[AxisErrors]
|
||||||
|
ErrorNumber0=1002
|
||||||
|
ErrorString0="general EL_Critical"
|
||||||
|
|
||||||
|
[ManiErrors]
|
||||||
Binary file not shown.
Reference in New Issue
Block a user