添加项目文件。
This commit is contained in:
19
BenchMovementModule/BenchMovementModule.cs
Normal file
19
BenchMovementModule/BenchMovementModule.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Reflection;
|
||||
using BenchMovementModule.Views;
|
||||
|
||||
namespace BenchMovementModule
|
||||
{
|
||||
public class BenchMovementModule : IModule
|
||||
{
|
||||
public void OnInitialized(IContainerProvider containerProvider)
|
||||
{
|
||||
IRegionManager regionManager = containerProvider.Resolve<IRegionManager>();
|
||||
regionManager.RegisterViewWithRegion("ShellViewManager", typeof(BenchMovementView));
|
||||
}
|
||||
|
||||
public void RegisterTypes(IContainerRegistry containerRegistry)
|
||||
{
|
||||
containerRegistry.RegisterForNavigation<BenchMovementView>("BenchMovementView");
|
||||
}
|
||||
}
|
||||
}
|
||||
14
BenchMovementModule/BenchMovementModule.csproj
Normal file
14
BenchMovementModule/BenchMovementModule.csproj
Normal file
@@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<UseWPF>true</UseWPF>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\UIShare\UIShare.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
164
BenchMovementModule/HardwareDrive/GantryControlBase.cs
Normal file
164
BenchMovementModule/HardwareDrive/GantryControlBase.cs
Normal file
@@ -0,0 +1,164 @@
|
||||
using DeviceCommand.Base;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BenchMovementModule.HardwareDrive
|
||||
{
|
||||
public abstract class GantryControlBase
|
||||
{
|
||||
protected readonly IModbusDevice _device;
|
||||
protected readonly byte _slaveAddress;
|
||||
|
||||
// 默认 PLC Modbus 映射地址
|
||||
protected const ushort ADDR_HM_X_ENABLE = 0xC100; // HM0: X轴使能
|
||||
protected const ushort ADDR_HM_Y_ENABLE = 0xC101; // HM1: Y轴使能
|
||||
protected const ushort ADDR_HM_Z_ENABLE = 0xC102; // HM2: Z轴使能
|
||||
|
||||
protected const ushort ADDR_M_X_START = 30; // M30: X轴指定位置启动
|
||||
protected const ushort ADDR_M_Y_START = 31; // M31: Y轴指定位置启动
|
||||
protected const ushort ADDR_M_Z_START = 35; // M35: Z轴指定位置启动
|
||||
|
||||
protected const ushort ADDR_M_ALL_STOP = 40; // M40: 全停
|
||||
protected const ushort ADDR_M_X_STOP = 41; // M41: X轴停止
|
||||
protected const ushort ADDR_M_Y_STOP = 42; // M42: Y轴停止
|
||||
protected const ushort ADDR_M_Z_STOP = 43; // M43: Z轴停止
|
||||
|
||||
protected const ushort ADDR_M_HOME = 100; // M100: 回原点触发
|
||||
|
||||
protected const ushort ADDR_HD_X_SPEED = 0xA166; // HD230: X轴速度 (32位)
|
||||
protected const ushort ADDR_HD_Y_SPEED = 0xA17A; // HD250: Y轴速度 (32位)
|
||||
protected const ushort ADDR_HD_Z_SPEED = 0xA170; // HD240: Z轴速度 (32位)
|
||||
|
||||
protected const ushort ADDR_HD_X_TARGET = 0xA10C; // HD140: X轴指定位置 (32位)
|
||||
protected const ushort ADDR_HD_Y_TARGET = 0xA120; // HD160: Y轴指定位置 (32位)
|
||||
protected const ushort ADDR_HD_Z_TARGET = 0xA116; // HD150: Z轴指定位置 (32位)
|
||||
|
||||
public bool IsConnected => _device?.IsConnected ?? false;
|
||||
|
||||
protected GantryControlBase(IModbusDevice device, byte slaveAddress = 1)
|
||||
{
|
||||
_device = device ?? throw new ArgumentNullException(nameof(device));
|
||||
_slaveAddress = slaveAddress;
|
||||
}
|
||||
|
||||
public async Task<bool> ConnectAsync(CancellationToken ct = default)
|
||||
{
|
||||
return await _device.ConnectAsync(ct);
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
_device.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 轴使能控制
|
||||
/// </summary>
|
||||
public async Task SetAxisEnableAsync(int axis, bool enable, CancellationToken ct = default)
|
||||
{
|
||||
ushort address = axis switch
|
||||
{
|
||||
1 => ADDR_HM_X_ENABLE, // X
|
||||
2 => ADDR_HM_Y_ENABLE, // Y
|
||||
3 => ADDR_HM_Z_ENABLE, // Z
|
||||
_ => throw new ArgumentException("轴通道错误,仅支持 1(X), 2(Y), 3(Z)")
|
||||
};
|
||||
|
||||
await _device.WriteSingleCoilAsync(_slaveAddress, address, enable, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 左右移动(X轴)
|
||||
/// </summary>
|
||||
/// <param name="position">目标绝对位置(脉冲数/单位值)</param>
|
||||
/// <param name="speed">运行速度</param>
|
||||
public async Task MoveLeftRightAsync(int position, int speed, CancellationToken ct = default)
|
||||
{
|
||||
// 1. 写入速度与目标位置(32位数据,写入连续的2个保持寄存器)
|
||||
await _device.WriteMultipleRegistersAsync(_slaveAddress, ADDR_HD_X_SPEED, Int32ToUshorts(speed), ct);
|
||||
await _device.WriteMultipleRegistersAsync(_slaveAddress, ADDR_HD_X_TARGET, Int32ToUshorts(position), ct);
|
||||
|
||||
// 2. 边缘触发启动信号 M30
|
||||
await TriggerCoilAsync(ADDR_M_X_START, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上下移动(Z轴)
|
||||
/// </summary>
|
||||
/// <param name="position">目标绝对位置</param>
|
||||
/// <param name="speed">运行速度</param>
|
||||
public async Task MoveUpDownAsync(int position, int speed, CancellationToken ct = default)
|
||||
{
|
||||
// 1. 写入速度与目标位置(32位数据)
|
||||
await _device.WriteMultipleRegistersAsync(_slaveAddress, ADDR_HD_Z_SPEED, Int32ToUshorts(speed), ct);
|
||||
await _device.WriteMultipleRegistersAsync(_slaveAddress, ADDR_HD_Z_TARGET, Int32ToUshorts(position), ct);
|
||||
|
||||
// 2. 边缘触发启动信号 M35
|
||||
await TriggerCoilAsync(ADDR_M_Z_START, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 前后移动(Y轴 - 预留拓展)
|
||||
/// </summary>
|
||||
public async Task MoveFrontBackAsync(int position, int speed, CancellationToken ct = default)
|
||||
{
|
||||
await _device.WriteMultipleRegistersAsync(_slaveAddress, ADDR_HD_Y_SPEED, Int32ToUshorts(speed), ct);
|
||||
await _device.WriteMultipleRegistersAsync(_slaveAddress, ADDR_HD_Y_TARGET, Int32ToUshorts(position), ct);
|
||||
await TriggerCoilAsync(ADDR_M_Y_START, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 全局回零
|
||||
/// </summary>
|
||||
public async Task HomeAsync(CancellationToken ct = default)
|
||||
{
|
||||
await TriggerCoilAsync(ADDR_M_HOME, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 轴停止
|
||||
/// </summary>
|
||||
/// <param name="axis">1:X轴, 2:Y轴, 3:Z轴, 0:全停</param>
|
||||
public async Task StopAsync(int axis = 0, CancellationToken ct = default)
|
||||
{
|
||||
ushort address = axis switch
|
||||
{
|
||||
0 => ADDR_M_ALL_STOP,
|
||||
1 => ADDR_M_X_STOP,
|
||||
2 => ADDR_M_Y_STOP,
|
||||
3 => ADDR_M_Z_STOP,
|
||||
_ => ADDR_M_ALL_STOP
|
||||
};
|
||||
|
||||
await TriggerCoilAsync(address, ct);
|
||||
}
|
||||
|
||||
#region 内部工具方法
|
||||
|
||||
/// <summary>
|
||||
/// 触发一个点动信号(置 1 后,延时 100ms 自动置 0)
|
||||
/// </summary>
|
||||
protected async Task TriggerCoilAsync(ushort address, CancellationToken ct = default)
|
||||
{
|
||||
await _device.WriteSingleCoilAsync(_slaveAddress, address, true, ct);
|
||||
await Task.Delay(100, ct); // 给予 PLC 扫描周期足够的响应时间
|
||||
await _device.WriteSingleCoilAsync(_slaveAddress, address, false, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将 32 位整型数据转换为 Modbus 的 2 个 16 位无符号整数(高低字转换)
|
||||
/// </summary>
|
||||
protected ushort[] Int32ToUshorts(int value)
|
||||
{
|
||||
// 本处采用低字在前(CDAB),如果PLC高字在前(ABCD),可将返回数组顺序颠倒
|
||||
ushort lowWord = (ushort)(value & 0xFFFF);
|
||||
ushort highWord = (ushort)((value >> 16) & 0xFFFF);
|
||||
return new ushort[] { lowWord, highWord };
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
28
BenchMovementModule/HardwareDrive/GantryControlRtu.cs
Normal file
28
BenchMovementModule/HardwareDrive/GantryControlRtu.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using DeviceCommand.Base;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Ports;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BenchMovementModule.HardwareDrive
|
||||
{
|
||||
public class GantryControlRtu : GantryControlBase
|
||||
{
|
||||
// 暴露出底层的 ModbusRtu 实例以便修改串口配置
|
||||
public ModbusRtu RtuDevice => (ModbusRtu)_device;
|
||||
|
||||
public GantryControlRtu(string portName, int baudRate = 9600, byte slaveAddress = 1)
|
||||
: base(new ModbusRtu(), slaveAddress)
|
||||
{
|
||||
RtuDevice.ConfigureDevice(portName, baudRate);
|
||||
}
|
||||
|
||||
public GantryControlRtu(string portName, int baudRate, int dataBits, StopBits stopBits, Parity parity, byte slaveAddress = 1)
|
||||
: base(new ModbusRtu(), slaveAddress)
|
||||
{
|
||||
RtuDevice.ConfigureDevice(portName, baudRate, dataBits, stopBits, parity);
|
||||
}
|
||||
}
|
||||
}
|
||||
27
BenchMovementModule/HardwareDrive/GantryControlTcp.cs
Normal file
27
BenchMovementModule/HardwareDrive/GantryControlTcp.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using DeviceCommand.Base;
|
||||
using Model.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BenchMovementModule.HardwareDrive
|
||||
{
|
||||
public class GantryControlTcp : GantryControlBase
|
||||
{
|
||||
// 暴露出底层的 ModbusTcp 实例以便修改网络配置
|
||||
public ModbusTcp TcpDevice => (ModbusTcp)_device;
|
||||
|
||||
public GantryControlTcp(TcpConfig config, byte slaveAddress = 1)
|
||||
: base(new ModbusTcp(config), slaveAddress)
|
||||
{
|
||||
}
|
||||
|
||||
public GantryControlTcp(string ipAddress, int port = 502, byte slaveAddress = 1)
|
||||
: base(new ModbusTcp(), slaveAddress)
|
||||
{
|
||||
TcpDevice.ConfigureDevice(ipAddress, port);
|
||||
}
|
||||
}
|
||||
}
|
||||
522
BenchMovementModule/ViewModels/BenchMovementViewModel.cs
Normal file
522
BenchMovementModule/ViewModels/BenchMovementViewModel.cs
Normal file
@@ -0,0 +1,522 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Threading;
|
||||
using DeviceCommand.Devices;
|
||||
using Logger;
|
||||
using Prism.Ioc;
|
||||
using UIShare.GlobalVariable;
|
||||
using UIShare.ViewModelBase;
|
||||
|
||||
namespace BenchMovementModule.ViewModels
|
||||
{
|
||||
public class BenchMovementViewModel : NavigateViewModelBase, IRegionMemberLifetime, IDisposable
|
||||
{
|
||||
#region 属性
|
||||
|
||||
public bool KeepAlive => true;
|
||||
|
||||
// ===== GantryControlTcp 实例(从 DeviceManager 获取)=====
|
||||
private GantryControlTcp? _gantry;
|
||||
private DeviceManager? _deviceManager;
|
||||
private readonly GlobalInfo _globalInfo;
|
||||
|
||||
// ===== 连接状态 =====
|
||||
private bool _isConnected;
|
||||
public bool IsConnected
|
||||
{
|
||||
get => _isConnected;
|
||||
set => SetProperty(ref _isConnected, value);
|
||||
}
|
||||
|
||||
private string _connectionStatus = "未连接";
|
||||
public string ConnectionStatus
|
||||
{
|
||||
get => _connectionStatus;
|
||||
set => SetProperty(ref _connectionStatus, value);
|
||||
}
|
||||
|
||||
// ===== 6轴绝对位置显示(相对原点的实时位置,只读)=====
|
||||
private int _absPos1;
|
||||
public int AbsPos1 { get => _absPos1; set => SetProperty(ref _absPos1, value); }
|
||||
|
||||
private int _absPos2;
|
||||
public int AbsPos2 { get => _absPos2; set => SetProperty(ref _absPos2, value); }
|
||||
|
||||
private int _absPos3;
|
||||
public int AbsPos3 { get => _absPos3; set => SetProperty(ref _absPos3, value); }
|
||||
|
||||
private int _absPos4;
|
||||
public int AbsPos4 { get => _absPos4; set => SetProperty(ref _absPos4, value); }
|
||||
|
||||
private int _absPos5;
|
||||
public int AbsPos5 { get => _absPos5; set => SetProperty(ref _absPos5, value); }
|
||||
|
||||
private int _absPos6;
|
||||
public int AbsPos6 { get => _absPos6; set => SetProperty(ref _absPos6, value); }
|
||||
|
||||
// ===== 寸动目标位置 =====
|
||||
private int _targetX;
|
||||
public int TargetX { get => _targetX; set => SetProperty(ref _targetX, value); }
|
||||
|
||||
private int _targetY;
|
||||
public int TargetY { get => _targetY; set => SetProperty(ref _targetY, value); }
|
||||
|
||||
private int _targetZ;
|
||||
public int TargetZ { get => _targetZ; set => SetProperty(ref _targetZ, value); }
|
||||
|
||||
// ===== 扫描参数 =====
|
||||
private int _scanStepX = 1000;
|
||||
public int ScanStepX { get => _scanStepX; set => SetProperty(ref _scanStepX, value); }
|
||||
|
||||
private int _scanStartX;
|
||||
public int ScanStartX { get => _scanStartX; set => SetProperty(ref _scanStartX, value); }
|
||||
|
||||
private int _scanEndX = 50000;
|
||||
public int ScanEndX { get => _scanEndX; set => SetProperty(ref _scanEndX, value); }
|
||||
|
||||
private int _scanStepY = 1000;
|
||||
public int ScanStepY { get => _scanStepY; set => SetProperty(ref _scanStepY, value); }
|
||||
|
||||
private int _scanStartY;
|
||||
public int ScanStartY { get => _scanStartY; set => SetProperty(ref _scanStartY, value); }
|
||||
|
||||
private int _scanEndY = 50000;
|
||||
public int ScanEndY { get => _scanEndY; set => SetProperty(ref _scanEndY, value); }
|
||||
|
||||
private int _scanStepZ = 100;
|
||||
public int ScanStepZ { get => _scanStepZ; set => SetProperty(ref _scanStepZ, value); }
|
||||
|
||||
private int _scanStartZ;
|
||||
public int ScanStartZ { get => _scanStartZ; set => SetProperty(ref _scanStartZ, value); }
|
||||
|
||||
private int _scanEndZ = 20000;
|
||||
public int ScanEndZ { get => _scanEndZ; set => SetProperty(ref _scanEndZ, value); }
|
||||
|
||||
// ===== 速度设定(脉冲)=====
|
||||
private int _speedX = 5000;
|
||||
public int SpeedX { get => _speedX; set => SetProperty(ref _speedX, value); }
|
||||
|
||||
private int _speedY = 5000;
|
||||
public int SpeedY { get => _speedY; set => SetProperty(ref _speedY, value); }
|
||||
|
||||
private int _speedZ = 2000;
|
||||
public int SpeedZ { get => _speedZ; set => SetProperty(ref _speedZ, value); }
|
||||
|
||||
private int _homeSpeed = 3000;
|
||||
public int HomeSpeed { get => _homeSpeed; set => SetProperty(ref _homeSpeed, value); }
|
||||
|
||||
// ===== 零点设定 =====
|
||||
private int _homeX;
|
||||
public int HomeX { get => _homeX; set => SetProperty(ref _homeX, value); }
|
||||
|
||||
private int _homeY;
|
||||
public int HomeY { get => _homeY; set => SetProperty(ref _homeY, value); }
|
||||
|
||||
private int _homeZ;
|
||||
public int HomeZ { get => _homeZ; set => SetProperty(ref _homeZ, value); }
|
||||
|
||||
#endregion
|
||||
|
||||
#region 命令
|
||||
public ICommand ConnectCommand { get; }
|
||||
public ICommand DisconnectCommand { get; }
|
||||
public ICommand MoveXCommand { get; }
|
||||
public ICommand MoveYCommand { get; }
|
||||
public ICommand MoveZCommand { get; }
|
||||
public ICommand MoveAllCommand { get; }
|
||||
public ICommand GoHomeCommand { get; }
|
||||
public ICommand EmergencyStopCommand { get; }
|
||||
public ICommand StopXCommand { get; }
|
||||
public ICommand StopYCommand { get; }
|
||||
public ICommand StopZCommand { get; }
|
||||
public ICommand SetSpeedCommand { get; }
|
||||
public ICommand SetHomeCommand { get; }
|
||||
public ICommand ReadStatusCommand { get; }
|
||||
#endregion
|
||||
|
||||
#region 私有字段
|
||||
private readonly DispatcherTimer _pollTimer;
|
||||
private bool _isInitiated = false;
|
||||
#endregion
|
||||
|
||||
public BenchMovementViewModel(IContainerProvider containerProvider) : base(containerProvider)
|
||||
{
|
||||
_globalInfo = containerProvider.Resolve<GlobalInfo>();
|
||||
ConnectCommand = new DelegateCommand(OnConnect);
|
||||
DisconnectCommand = new DelegateCommand(OnDisconnect);
|
||||
MoveXCommand = new DelegateCommand(OnMoveX);
|
||||
MoveYCommand = new DelegateCommand(OnMoveY);
|
||||
MoveZCommand = new DelegateCommand(OnMoveZ);
|
||||
MoveAllCommand = new DelegateCommand(OnMoveAll);
|
||||
GoHomeCommand = new DelegateCommand(OnGoHome);
|
||||
EmergencyStopCommand = new DelegateCommand(OnEmergencyStop);
|
||||
StopXCommand = new DelegateCommand(OnStopX);
|
||||
StopYCommand = new DelegateCommand(OnStopY);
|
||||
StopZCommand = new DelegateCommand(OnStopZ);
|
||||
SetSpeedCommand = new DelegateCommand(OnSetSpeed);
|
||||
SetHomeCommand = new DelegateCommand(OnSetHome);
|
||||
ReadStatusCommand = new DelegateCommand(OnReadStatus);
|
||||
|
||||
// 位置轮询定时器(500ms)
|
||||
_pollTimer = new DispatcherTimer(DispatcherPriority.Background)
|
||||
{
|
||||
Interval = TimeSpan.FromMilliseconds(500)
|
||||
};
|
||||
_pollTimer.Tick += OnPollTick;
|
||||
}
|
||||
|
||||
#region 命令处理
|
||||
|
||||
private async void OnConnect()
|
||||
{
|
||||
if (_gantry == null) return;
|
||||
try
|
||||
{
|
||||
ConnectionStatus = "连接中...";
|
||||
bool ok = await _gantry.ConnectAsync();
|
||||
if (ok)
|
||||
{
|
||||
IsConnected = true;
|
||||
ConnectionStatus = "已连接";
|
||||
_pollTimer.Start();
|
||||
await ReadDeviceParametersAsync();
|
||||
LoggerHelper.Info("[BenchMovement] 台架连接成功");
|
||||
}
|
||||
else
|
||||
{
|
||||
ConnectionStatus = "连接失败";
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.Error($"[BenchMovement] 连接失败: {ex.Message}");
|
||||
ConnectionStatus = $"连接失败: {ex.Message}";
|
||||
}
|
||||
UpdateConnectionStatus();
|
||||
}
|
||||
|
||||
private void OnDisconnect()
|
||||
{
|
||||
if (_gantry == null) return;
|
||||
try
|
||||
{
|
||||
_pollTimer.Stop();
|
||||
_gantry.Close();
|
||||
IsConnected = false;
|
||||
ConnectionStatus = "未连接";
|
||||
LoggerHelper.Info("[BenchMovement] 台架已断开");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.Error($"[BenchMovement] 断开失败: {ex.Message}");
|
||||
}
|
||||
UpdateConnectionStatus();
|
||||
}
|
||||
|
||||
private async void OnMoveX()
|
||||
{
|
||||
if (!EnsureConnected()) return;
|
||||
try
|
||||
{
|
||||
await _gantry!.SetAxisTargetPositionAsync(1, TargetX);
|
||||
await _gantry.StartSingleAxisAsync(1);
|
||||
LoggerHelper.Info($"[BenchMovement] X轴移动到 {TargetX}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.Error($"[BenchMovement] X轴移动失败: {ex.Message}");
|
||||
ShowErrorMessageBox($"X轴移动失败: {ex.Message}", () => { });
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnMoveY()
|
||||
{
|
||||
if (!EnsureConnected()) return;
|
||||
try
|
||||
{
|
||||
await _gantry!.SetAxisTargetPositionAsync(2, TargetY);
|
||||
await _gantry.StartSingleAxisAsync(2);
|
||||
LoggerHelper.Info($"[BenchMovement] Y轴移动到 {TargetY}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.Error($"[BenchMovement] Y轴移动失败: {ex.Message}");
|
||||
ShowErrorMessageBox($"Y轴移动失败: {ex.Message}", () => { });
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnMoveZ()
|
||||
{
|
||||
if (!EnsureConnected()) return;
|
||||
try
|
||||
{
|
||||
await _gantry!.SetAxisTargetPositionAsync(3, TargetZ);
|
||||
await _gantry.StartSingleAxisAsync(3);
|
||||
LoggerHelper.Info($"[BenchMovement] Z轴移动到 {TargetZ}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.Error($"[BenchMovement] Z轴移动失败: {ex.Message}");
|
||||
ShowErrorMessageBox($"Z轴移动失败: {ex.Message}", () => { });
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnMoveAll()
|
||||
{
|
||||
if (!EnsureConnected()) return;
|
||||
try
|
||||
{
|
||||
await _gantry!.SetAxisTargetPositionAsync(1, TargetX);
|
||||
await _gantry.SetAxisTargetPositionAsync(2, TargetY);
|
||||
await _gantry.SetAxisTargetPositionAsync(3, TargetZ);
|
||||
await _gantry.StartAllAxesAsync();
|
||||
LoggerHelper.Info($"[BenchMovement] 三轴同时移动: X={TargetX}, Y={TargetY}, Z={TargetZ}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.Error($"[BenchMovement] 三轴移动失败: {ex.Message}");
|
||||
ShowErrorMessageBox($"三轴移动失败: {ex.Message}", () => { });
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnGoHome()
|
||||
{
|
||||
if (!EnsureConnected()) return;
|
||||
try
|
||||
{
|
||||
await _gantry!.HomeAsync();
|
||||
LoggerHelper.Info("[BenchMovement] 回原点已触发");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.Error($"[BenchMovement] 回原点失败: {ex.Message}");
|
||||
ShowErrorMessageBox($"回原点失败: {ex.Message}", () => { });
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnEmergencyStop()
|
||||
{
|
||||
if (!EnsureConnected()) return;
|
||||
try
|
||||
{
|
||||
await _gantry!.SetEStopStateAsync(true);
|
||||
LoggerHelper.Info("[BenchMovement] 急停已触发");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.Error($"[BenchMovement] 急停失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnStopX()
|
||||
{
|
||||
if (!EnsureConnected()) return;
|
||||
try
|
||||
{
|
||||
await _gantry!.SetStopStateAsync(1, true);
|
||||
await Task.Delay(100);
|
||||
await _gantry.SetStopStateAsync(1, false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.Error($"[BenchMovement] X轴停止失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnStopY()
|
||||
{
|
||||
if (!EnsureConnected()) return;
|
||||
try
|
||||
{
|
||||
await _gantry!.SetStopStateAsync(2, true);
|
||||
await Task.Delay(100);
|
||||
await _gantry.SetStopStateAsync(2, false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.Error($"[BenchMovement] Y轴停止失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnStopZ()
|
||||
{
|
||||
if (!EnsureConnected()) return;
|
||||
try
|
||||
{
|
||||
await _gantry!.SetStopStateAsync(3, true);
|
||||
await Task.Delay(100);
|
||||
await _gantry.SetStopStateAsync(3, false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.Error($"[BenchMovement] Z轴停止失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnSetSpeed()
|
||||
{
|
||||
if (!EnsureConnected()) return;
|
||||
try
|
||||
{
|
||||
await _gantry!.SetAxisSpeedAsync(1, SpeedX);
|
||||
await _gantry.SetAxisSpeedAsync(2, SpeedY);
|
||||
await _gantry.SetAxisSpeedAsync(3, SpeedZ);
|
||||
await _gantry.SetHomePositionSpeedAsync(HomeSpeed);
|
||||
LoggerHelper.Info($"[BenchMovement] 速度设定完成: X={SpeedX}, Y={SpeedY}, Z={SpeedZ}, 回零={HomeSpeed}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.Error($"[BenchMovement] 速度设定失败: {ex.Message}");
|
||||
ShowErrorMessageBox($"速度设定失败: {ex.Message}", () => { });
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnSetHome()
|
||||
{
|
||||
if (!EnsureConnected()) return;
|
||||
try
|
||||
{
|
||||
await _gantry!.SetHomePositionAsync(HomeX, HomeY, HomeZ);
|
||||
LoggerHelper.Info($"[BenchMovement] 零点设定完成: X={HomeX}, Y={HomeY}, Z={HomeZ}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.Error($"[BenchMovement] 零点设定失败: {ex.Message}");
|
||||
ShowErrorMessageBox($"零点设定失败: {ex.Message}", () => { });
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnReadStatus()
|
||||
{
|
||||
await ReadDeviceParametersAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 辅助方法
|
||||
|
||||
private bool EnsureConnected()
|
||||
{
|
||||
if (_gantry == null || !_gantry.IsConnected)
|
||||
{
|
||||
ShowErrorMessageBox("设备未连接,请先连接台架", () => { });
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void UpdateConnectionStatus()
|
||||
{
|
||||
IsConnected = _gantry?.IsConnected ?? false;
|
||||
ConnectionStatus = IsConnected ? "已连接" : "未连接";
|
||||
}
|
||||
|
||||
private async Task ReadDeviceParametersAsync()
|
||||
{
|
||||
if (_gantry == null || !_gantry.IsConnected) return;
|
||||
try
|
||||
{
|
||||
var (x, y, z) = await _gantry.GetHomePositionAsync();
|
||||
HomeX = x; HomeY = y; HomeZ = z;
|
||||
|
||||
SpeedX = await _gantry.GetAxisSpeedAsync(1);
|
||||
SpeedY = await _gantry.GetAxisSpeedAsync(2);
|
||||
SpeedZ = await _gantry.GetAxisSpeedAsync(3);
|
||||
HomeSpeed = await _gantry.GetHomePositionSpeedAsync();
|
||||
|
||||
// 读取 6 轴绝对位置
|
||||
var positions = await _gantry.GetAllAbsolutePositionsAsync();
|
||||
AbsPos1 = positions.Axis1; AbsPos2 = positions.Axis2; AbsPos3 = positions.Axis3;
|
||||
AbsPos4 = positions.Axis4; AbsPos5 = positions.Axis5; AbsPos6 = positions.Axis6;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.Error($"[BenchMovement] 读取设备参数失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnPollTick(object? sender, EventArgs e)
|
||||
{
|
||||
if (_gantry == null || !_gantry.IsConnected) return;
|
||||
try
|
||||
{
|
||||
// 批量读取 6 轴绝对位置(一次性通信,高效)
|
||||
var pos = await _gantry.GetAllAbsolutePositionsAsync();
|
||||
AbsPos1 = pos.Axis1; AbsPos2 = pos.Axis2; AbsPos3 = pos.Axis3;
|
||||
AbsPos4 = pos.Axis4; AbsPos5 = pos.Axis5; AbsPos6 = pos.Axis6;
|
||||
}
|
||||
catch { /* 忽略轮询错误 */ }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 生命周期
|
||||
|
||||
public override void OnNavigatedTo(NavigationContext navigationContext)
|
||||
{
|
||||
base.OnNavigatedTo(navigationContext);
|
||||
if (!_isInitiated)
|
||||
{
|
||||
_isInitiated = true;
|
||||
InitGantryFromDeviceManager();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从 DeviceManager.DeviceMap 中查找 GantryControlTcp 实例,
|
||||
/// 优先使用当前打开的作用域,找不到则取任意已注册作用域。
|
||||
/// </summary>
|
||||
private void InitGantryFromDeviceManager()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 优先使用当前打开的作用域
|
||||
IScopedProvider? scope = null;
|
||||
if (!string.IsNullOrEmpty(_globalInfo.CurrentOpeningScope)
|
||||
&& _globalInfo.ScopeDic.TryGetValue(_globalInfo.CurrentOpeningScope, out scope))
|
||||
{
|
||||
// 找到了
|
||||
}
|
||||
else
|
||||
{
|
||||
// 退而求其次,取任意可用作用域
|
||||
scope = _globalInfo.ScopeDic.Values.FirstOrDefault();
|
||||
}
|
||||
|
||||
if (scope == null)
|
||||
{
|
||||
LoggerHelper.Warn("[BenchMovement] 无可用的作用域,无法解析 DeviceManager。");
|
||||
return;
|
||||
}
|
||||
|
||||
_deviceManager = scope.Resolve<DeviceManager>();
|
||||
_gantry = _deviceManager.DeviceMap.Values.OfType<GantryControlTcp>().FirstOrDefault();
|
||||
|
||||
if (_gantry != null)
|
||||
{
|
||||
LoggerHelper.Info($"[BenchMovement] 已从 DeviceManager 获取 GantryControlTcp 实例。");
|
||||
UpdateConnectionStatus();
|
||||
}
|
||||
else
|
||||
{
|
||||
LoggerHelper.Warn("[BenchMovement] DeviceManager 中未找到 GantryControlTcp 设备,请检查设备配置。");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.Error($"[BenchMovement] 初始化 GantryControlTcp 失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_pollTimer.Stop();
|
||||
// GantryControlTcp 由 DeviceManager 统一管理生命周期,此处仅停止轮询
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
394
BenchMovementModule/Views/BenchMovementView.xaml
Normal file
394
BenchMovementModule/Views/BenchMovementView.xaml
Normal file
@@ -0,0 +1,394 @@
|
||||
<UserControl x:Class="BenchMovementModule.Views.BenchMovementView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
xmlns:prism="http://prismlibrary.com/"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||
d:DesignHeight="1080" d:DesignWidth="1920">
|
||||
|
||||
<UserControl.Resources>
|
||||
<Style TargetType="TextBlock" x:Key="HeaderStyle">
|
||||
<Setter Property="Foreground" Value="#333333"/>
|
||||
<Setter Property="FontSize" Value="18"/>
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
<Setter Property="Margin" Value="2,2,2,5"/>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="TextBlock" x:Key="LabelStyle">
|
||||
<Setter Property="Foreground" Value="#555555"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
<Setter Property="Margin" Value="5"/>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="TextBlock" x:Key="ValueStyle">
|
||||
<Setter Property="Foreground" Value="#0056B3"/>
|
||||
<Setter Property="FontSize" Value="26"/>
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Center"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="TextBox">
|
||||
<Setter Property="Background" Value="White"/>
|
||||
<Setter Property="Foreground" Value="#333333"/>
|
||||
<Setter Property="BorderBrush" Value="#CCCCCC"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="Padding" Value="4,2"/>
|
||||
<Setter Property="Height" Value="28"/>
|
||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="Background" Value="#F5F5F5"/>
|
||||
<Setter Property="Foreground" Value="#333333"/>
|
||||
<Setter Property="BorderBrush" Value="#B8B8B8"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="Padding" Value="12,5"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="Height" Value="34"/>
|
||||
<Setter Property="Margin" Value="0,0,0,8"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border x:Name="btnBorder"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="3">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="btnBorder" Property="Background" Value="#EAEAEA"/>
|
||||
<Setter TargetName="btnBorder" Property="BorderBrush" Value="#4A90E2"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter TargetName="btnBorder" Property="Background" Value="#DCDCDC"/>
|
||||
<Setter TargetName="btnBorder" Property="BorderBrush" Value="#2A6099"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Button" x:Key="StopButtonStyle" BasedOn="{StaticResource {x:Type Button}}">
|
||||
<Setter Property="Background" Value="#FFF0F0"/>
|
||||
<Setter Property="Foreground" Value="#C00000"/>
|
||||
<Setter Property="BorderBrush" Value="#E0A0A0"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border x:Name="btnBorder" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1" CornerRadius="3">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="btnBorder" Property="Background" Value="#FFE0E0"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter TargetName="btnBorder" Property="Background" Value="#F0C0C0"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Button" x:Key="EmergencyButtonStyle" BasedOn="{StaticResource {x:Type Button}}">
|
||||
<Setter Property="Background" Value="#D9534F"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="BorderBrush" Value="#D43F3A"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border x:Name="btnBorder" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1" CornerRadius="4">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="btnBorder" Property="Background" Value="#C9302C"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter TargetName="btnBorder" Property="Background" Value="#AC2925"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="Button" x:Key="ConnectButtonStyle" BasedOn="{StaticResource {x:Type Button}}">
|
||||
<Setter Property="Background" Value="#5CB85C"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="BorderBrush" Value="#4CAE4C"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border x:Name="btnBorder" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1" CornerRadius="3">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="btnBorder" Property="Background" Value="#449D44"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter TargetName="btnBorder" Property="Background" Value="#3D8B3D"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style TargetType="GroupBox">
|
||||
<Setter Property="BorderBrush" Value="#D0D0D0"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="Margin" Value="6"/>
|
||||
<Setter Property="Padding" Value="10"/>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid Background="#F0F2F5">
|
||||
<TabControl Background="Transparent" BorderThickness="0">
|
||||
<TabControl.Resources>
|
||||
<Style TargetType="TabItem">
|
||||
<Setter Property="Background" Value="#E0E4E8"/>
|
||||
<Setter Property="Foreground" Value="#333333"/>
|
||||
<Setter Property="FontSize" Value="15"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
<Setter Property="Padding" Value="25,6"/>
|
||||
<Setter Property="Margin" Value="2,0,2,0"/>
|
||||
</Style>
|
||||
</TabControl.Resources>
|
||||
|
||||
<!-- ======================= 1. 控制面板 ======================= -->
|
||||
<TabItem Header="控制">
|
||||
<Grid Margin="10">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="4*"/>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- 顶部:连接状态条 -->
|
||||
<Border Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Background="White" BorderBrush="#D0D0D0" BorderThickness="1" CornerRadius="3" Padding="15,8" Margin="0,0,0,10">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Ellipse Width="14" Height="14" Margin="0,0,8,0">
|
||||
<Ellipse.Style>
|
||||
<Style TargetType="Ellipse">
|
||||
<Setter Property="Fill" Value="#999999"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsConnected}" Value="True">
|
||||
<Setter Property="Fill" Value="#5CB85C"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Ellipse.Style>
|
||||
</Ellipse>
|
||||
<TextBlock Text="{Binding ConnectionStatus}" FontSize="16" FontWeight="Bold" VerticalAlignment="Center" Margin="0,0,20,0"/>
|
||||
<Button Content="连接" Width="80" Margin="0" Style="{StaticResource ConnectButtonStyle}" Command="{Binding ConnectCommand}"/>
|
||||
<Button Content="断开" Width="80" Margin="8,0,0,0" Style="{StaticResource StopButtonStyle}" Command="{Binding DisconnectCommand}"/>
|
||||
<Button Content="刷新状态" Width="90" Margin="8,0,0,0" Command="{Binding ReadStatusCommand}"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- 左中:位置显示 & 寸动目标 -->
|
||||
<Grid Grid.Row="1" Grid.Column="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="1.5*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- 6轴绝对位置 -->
|
||||
<GroupBox Grid.Column="0">
|
||||
<GroupBox.Header>
|
||||
<TextBlock Text="绝对位置(只读)" Style="{StaticResource HeaderStyle}"/>
|
||||
</GroupBox.Header>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="轴1" Style="{StaticResource LabelStyle}"/>
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding AbsPos1}" Style="{StaticResource ValueStyle}"/>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="轴2" Style="{StaticResource LabelStyle}"/>
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding AbsPos2}" Style="{StaticResource ValueStyle}"/>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="轴3" Style="{StaticResource LabelStyle}"/>
|
||||
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding AbsPos3}" Style="{StaticResource ValueStyle}"/>
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="轴4" Style="{StaticResource LabelStyle}"/>
|
||||
<TextBlock Grid.Row="3" Grid.Column="1" Text="{Binding AbsPos4}" Style="{StaticResource ValueStyle}"/>
|
||||
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" Text="轴5" Style="{StaticResource LabelStyle}"/>
|
||||
<TextBlock Grid.Row="4" Grid.Column="1" Text="{Binding AbsPos5}" Style="{StaticResource ValueStyle}"/>
|
||||
|
||||
<TextBlock Grid.Row="5" Grid.Column="0" Text="轴6" Style="{StaticResource LabelStyle}"/>
|
||||
<TextBlock Grid.Row="5" Grid.Column="1" Text="{Binding AbsPos6}" Style="{StaticResource ValueStyle}"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
<!-- 寸动目标位置 -->
|
||||
<GroupBox Grid.Column="1">
|
||||
<GroupBox.Header>
|
||||
<TextBlock Text="寸动目标" Style="{StaticResource HeaderStyle}"/>
|
||||
</GroupBox.Header>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="X目标" Style="{StaticResource LabelStyle}"/>
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding TargetX}" Margin="5"/>
|
||||
<Button Grid.Row="0" Grid.Column="2" Content="移动" Width="60" Margin="5,0,5,0" Command="{Binding MoveXCommand}"/>
|
||||
<Button Grid.Row="0" Grid.Column="3" Content="停止" Width="60" Margin="0,0,5,0" Style="{StaticResource StopButtonStyle}" Command="{Binding StopXCommand}"/>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Y目标" Style="{StaticResource LabelStyle}"/>
|
||||
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding TargetY}" Margin="5"/>
|
||||
<Button Grid.Row="1" Grid.Column="2" Content="移动" Width="60" Margin="5,0,5,0" Command="{Binding MoveYCommand}"/>
|
||||
<Button Grid.Row="1" Grid.Column="3" Content="停止" Width="60" Margin="0,0,5,0" Style="{StaticResource StopButtonStyle}" Command="{Binding StopYCommand}"/>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="Z目标" Style="{StaticResource LabelStyle}"/>
|
||||
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding TargetZ}" Margin="5"/>
|
||||
<Button Grid.Row="2" Grid.Column="2" Content="移动" Width="60" Margin="5,0,5,0" Command="{Binding MoveZCommand}"/>
|
||||
<Button Grid.Row="2" Grid.Column="3" Content="停止" Width="60" Margin="0,0,5,0" Style="{StaticResource StopButtonStyle}" Command="{Binding StopZCommand}"/>
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
|
||||
<!-- 右侧:控制面板 -->
|
||||
<Grid Grid.Row="1" Grid.Column="1" Margin="6,6,0,6">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel Grid.Row="0">
|
||||
<Button Content="↩ 回原点" Command="{Binding GoHomeCommand}"/>
|
||||
<Button Content="⬆ 三轴同动" Command="{Binding MoveAllCommand}"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Row="1" VerticalAlignment="Center">
|
||||
<TextBlock Text="单轴控制" Style="{StaticResource LabelStyle}" HorizontalAlignment="Center" Margin="0,10,0,10"/>
|
||||
<Button Content="↕ X 移动" Command="{Binding MoveXCommand}"/>
|
||||
<Button Content="↔ Y 移动" Command="{Binding MoveYCommand}"/>
|
||||
<Button Content="↕ Z 移动" Command="{Binding MoveZCommand}"/>
|
||||
</StackPanel>
|
||||
|
||||
<Button Grid.Row="2" Content="❌ 急 停" Style="{StaticResource EmergencyButtonStyle}" FontWeight="Bold" FontSize="18" Height="55" Margin="0" Command="{Binding EmergencyStopCommand}"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
|
||||
<!-- ======================= 2. 设置 ======================= -->
|
||||
<TabItem Header="设置">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Margin="10">
|
||||
|
||||
<!-- 移动速度设定(脉冲) -->
|
||||
<GroupBox>
|
||||
<GroupBox.Header>
|
||||
<TextBlock Text="移动速度设定" Style="{StaticResource HeaderStyle}"/>
|
||||
</GroupBox.Header>
|
||||
<StackPanel Margin="5">
|
||||
<Grid Margin="0,0,0,6">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="160"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="X速度(脉冲)" Style="{StaticResource LabelStyle}"/>
|
||||
<TextBox Grid.Column="1" Text="{Binding SpeedX}"/>
|
||||
</Grid>
|
||||
<Grid Margin="0,0,0,6">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="160"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="Y速度(脉冲)" Style="{StaticResource LabelStyle}"/>
|
||||
<TextBox Grid.Column="1" Text="{Binding SpeedY}"/>
|
||||
</Grid>
|
||||
<Grid Margin="0,0,0,6">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="160"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="Z速度(脉冲)" Style="{StaticResource LabelStyle}"/>
|
||||
<TextBox Grid.Column="1" Text="{Binding SpeedZ}"/>
|
||||
</Grid>
|
||||
<Grid Margin="0,0,0,10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="160"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="回零速度(脉冲)" Style="{StaticResource LabelStyle}"/>
|
||||
<TextBox Grid.Column="1" Text="{Binding HomeSpeed}"/>
|
||||
</Grid>
|
||||
<Button Content="速度设定" Width="110" HorizontalAlignment="Left" Margin="0" Command="{Binding SetSpeedCommand}"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
|
||||
<!-- 零点设定 -->
|
||||
<GroupBox>
|
||||
<GroupBox.Header>
|
||||
<TextBlock Text="零点设定" Style="{StaticResource HeaderStyle}"/>
|
||||
</GroupBox.Header>
|
||||
<StackPanel Margin="5">
|
||||
<Grid Margin="0,0,0,6">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="120"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="X零点" Style="{StaticResource LabelStyle}"/>
|
||||
<TextBox Grid.Column="1" Text="{Binding HomeX}"/>
|
||||
</Grid>
|
||||
<Grid Margin="0,0,0,6">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="120"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="Y零点" Style="{StaticResource LabelStyle}"/>
|
||||
<TextBox Grid.Column="1" Text="{Binding HomeY}"/>
|
||||
</Grid>
|
||||
<Grid Margin="0,0,0,10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="120"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="Z零点" Style="{StaticResource LabelStyle}"/>
|
||||
<TextBox Grid.Column="1" Text="{Binding HomeZ}"/>
|
||||
</Grid>
|
||||
<Button Content="零点设定" Width="110" HorizontalAlignment="Left" Margin="0" Command="{Binding SetHomeCommand}"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
28
BenchMovementModule/Views/BenchMovementView.xaml.cs
Normal file
28
BenchMovementModule/Views/BenchMovementView.xaml.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BenchMovementModule.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// BenchMovementView.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class BenchMovementView : UserControl
|
||||
{
|
||||
public BenchMovementView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user