From 8c0af19f02c451dfaaca788b8d910713a80dc908 Mon Sep 17 00:00:00 2001 From: xyy <544939200@qq.com> Date: Tue, 16 Jun 2026 20:50:05 +0800 Subject: [PATCH] --- ...试仪(2).gxw => CSI-Z173 吸入制剂药物测试仪(4).gxw | Bin 1019904 -> 1040384 bytes Models/PlcConfiguration.cs | 8 +- Services/ModbusTcpPlcService.cs | 20 ++-- ViewModels/MainViewModel.cs | 91 +++++++++++++++++- Views/MainWindow.xaml | 68 ++++++++----- 5 files changed, 148 insertions(+), 39 deletions(-) rename CSI-Z173 吸入制剂药物测试仪(2).gxw => CSI-Z173 吸入制剂药物测试仪(4).gxw (91%) diff --git a/CSI-Z173 吸入制剂药物测试仪(2).gxw b/CSI-Z173 吸入制剂药物测试仪(4).gxw similarity index 91% rename from CSI-Z173 吸入制剂药物测试仪(2).gxw rename to CSI-Z173 吸入制剂药物测试仪(4).gxw index 2c1f428743452355db9f9fddd1a03e0e00195cc0..9d1246729c1eaad46ad336b2095bed2e20d63fc9 100644 GIT binary patch delta 25322 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 Q>TGr&!`~r&#dop)0xkVOYXATM diff --git a/Models/PlcConfiguration.cs b/Models/PlcConfiguration.cs index c881c0e..bcbb863 100644 --- a/Models/PlcConfiguration.cs +++ b/Models/PlcConfiguration.cs @@ -12,8 +12,8 @@ namespace AciTester.Models public class PlcConfiguration { // ========== 网络连接参数 ========== - public string IpAddress { get; set; } // PLC IP 地址 - public int Port { get; set; } // Modbus TCP 端口 + public string IpAddress { get; set; } = "192.168.1.10"; // PLC IP 地址 + public int Port { get; set; } = 502; // Modbus TCP 端口 public byte SlaveId { get; set; } = 1; // 从站地址(默认1) // 以下属性用于与上位机交互(但实际按工位读取,此处保留兼容) @@ -32,10 +32,10 @@ namespace AciTester.Models public ushort PressureRegisterStation2 { get; set; } // 工位2 public ushort PressureRegisterStation3 { get; set; } // 工位3 + public ushort ValveCoil { get; set; } = 5; // 假设 M5 对应线圈地址 5 - - public ushort PumpCoil { get; set; } // 高压超限 M180 + public ushort PumpCoil { get; set; } = 6; // 高压超限 M180 public ushort FlowRegister { get; set; } // 高压超限 M180 diff --git a/Services/ModbusTcpPlcService.cs b/Services/ModbusTcpPlcService.cs index 77eb6c2..d38421d 100644 --- a/Services/ModbusTcpPlcService.cs +++ b/Services/ModbusTcpPlcService.cs @@ -194,17 +194,25 @@ namespace AciTester.Services { await EnsureConnectedAsync(); var regs = await ReadHoldingRegistersAsync(startAddress, 2); - return (regs[0] << 16) | regs[1]; + + return regs[0]; // 暂时返回大端,您根据日志判断 } public async Task WriteInt32Async(ushort startAddress, int value) { await EnsureConnectedAsync(); - var bytes = BitConverter.GetBytes(value); - if (BitConverter.IsLittleEndian) Array.Reverse(bytes); - ushort high = (ushort)((bytes[0] << 8) | bytes[1]); - ushort low = (ushort)((bytes[2] << 8) | bytes[3]); - await _master.WriteMultipleRegistersAsync(_config.SlaveId, startAddress, new ushort[] { high, low }); + ushort[] dwellTimeRegisters = ConvertIntToRegisters(value); + await _master.WriteMultipleRegistersAsync(1, startAddress, dwellTimeRegisters); + } + + // 将整数转换为寄存器数组(2个寄存器) + private ushort[] ConvertIntToRegisters(int value) + { + byte[] bytes = BitConverter.GetBytes(value); + ushort[] registers = new ushort[2]; + registers[0] = BitConverter.ToUInt16(bytes, 0); // 第一个寄存器(低位) + registers[1] = BitConverter.ToUInt16(bytes, 2); // 第二个寄存器(高位) + return registers; } } diff --git a/ViewModels/MainViewModel.cs b/ViewModels/MainViewModel.cs index 8ba630c..349aa53 100644 --- a/ViewModels/MainViewModel.cs +++ b/ViewModels/MainViewModel.cs @@ -18,7 +18,7 @@ namespace AciTester.ViewModels private CancellationTokenSource _testCts; private bool _alarmShownLow = false; private bool _alarmShownHigh = false; - + public IAsyncRelayCommand OpenValveCommand { get; } [ObservableProperty] private bool isConnected; @@ -34,6 +34,9 @@ namespace AciTester.ViewModels [ObservableProperty] private bool isTesting; + [ObservableProperty] + private bool canStopTest; // 控制“停止测试”按钮的启用状态 + [ObservableProperty] private int sampleTimeSeconds = 60; @@ -55,6 +58,17 @@ namespace AciTester.ViewModels [ObservableProperty] private bool constantTempStartEnabled = true; // 是否允许恒温启动(除霜时为false) + public IAsyncRelayCommand StartPumpCommand { get; } + public IAsyncRelayCommand StopPumpCommand { get; } + // 阀门/泵状态(用于界面显示) + [ObservableProperty] + private bool valveStatus; // true=开启, false=关闭 + + [ObservableProperty] + private bool pumpStatus; // true=运行, false=停止 + + public IAsyncRelayCommand CloseValveCommand { get; } + public MainViewModel() { _config = new PlcConfiguration(); @@ -77,6 +91,7 @@ namespace AciTester.ViewModels ConnectCommand = new AsyncRelayCommand(ConnectAsync); DisconnectCommand = new RelayCommand(Disconnect); StartTestCommand = new AsyncRelayCommand(StartTestAsync); + StopTestCommand = new AsyncRelayCommand(StopTestAsync, () => IsTesting); CalculateCommand = new RelayCommand(CalculateResult); ExportReportCommand = new AsyncRelayCommand(ExportReportAsync); @@ -88,6 +103,28 @@ namespace AciTester.ViewModels RealTime = new RealTimeData(); Calibration = new CalibrationConfig(); + OpenValveCommand = new AsyncRelayCommand(async () => + { + await _plcService.WriteCoilAsync(_config.ValveCoil, true); + ValveStatus = true; + }); + CloseValveCommand = new AsyncRelayCommand(async () => + { + await _plcService.WriteCoilAsync(_config.ValveCoil, false); + ValveStatus = false; + }); + + StartPumpCommand = new AsyncRelayCommand(async () => + { + await _plcService.WriteCoilAsync(_config.PumpCoil, true); + PumpStatus = true; + }); + StopPumpCommand = new AsyncRelayCommand(async () => + { + await _plcService.WriteCoilAsync(_config.PumpCoil, false); + PumpStatus = false; + }); + // 监听属性变化,当除霜启动时更新恒温启动使能 RealTime.PropertyChanged += async (s, e) => @@ -101,8 +138,9 @@ namespace AciTester.ViewModels await WriteDefrostTimeSetAsync(RealTime.DefrostTimeSet); } }; - } + } + public IAsyncRelayCommand StopTestCommand { get; } public IAsyncRelayCommand ConnectCommand { get; } public IRelayCommand DisconnectCommand { get; } public IAsyncRelayCommand StartTestCommand { get; } @@ -113,6 +151,38 @@ namespace AciTester.ViewModels public IAsyncRelayCommand WriteDefrostTempSetCommand { get; } public IAsyncRelayCommand WriteDefrostTimeSetCommand { get; } + private async Task StopTestAsync() + { + if (!IsTesting) return; + + try + { + // 停止真空泵 + await _plcService.WriteCoilAsync(_config.PumpCoil, false); + IsPumpRunning = false; + } + catch (Exception ex) + { + MessageBox.Show($"停止泵失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); + } + finally + { + // 重置状态 + IsTesting = false; + CanStopTest = false; + _testCts?.Cancel(); // 取消倒计时 + + RemainingSeconds = 0; + + // 更新按钮状态 + StopTestCommand.NotifyCanExecuteChanged(); + } + + //MessageBox.Show("测试已手动停止,请进行称重并录入数据。", "提示", MessageBoxButton.OK, MessageBoxImage.Information); + } + + + private async Task ConnectAsync() { try @@ -179,10 +249,21 @@ namespace AciTester.ViewModels RealTime.DifferentialPressure = calibratedImp - calibratedPump; }); + // 在 ReadRealTimeLoop 中添加 + var valve = await _plcService.ReadCoilAsync(_config.ValveCoil); + var pump = await _plcService.ReadCoilAsync(_config.PumpCoil); + Application.Current.Dispatcher.Invoke(() => + { + ValveStatus = valve; + PumpStatus = pump; + }); + + + if (calibrated < Calibration.FlowLowLimit || calibrated > Calibration.FlowHighLimit) { - Application.Current.Dispatcher.Invoke(() => - MessageBox.Show($"流量异常: {calibrated:F2} L/min", "警告", MessageBoxButton.OK, MessageBoxImage.Warning)); + //Application.Current.Dispatcher.Invoke(() => + // MessageBox.Show($"流量异常: {calibrated:F2} L/min", "警告", MessageBoxButton.OK, MessageBoxImage.Warning)); } } catch { } @@ -322,7 +403,7 @@ namespace AciTester.ViewModels IsTesting = true; _testCts = new CancellationTokenSource(); - + //StopTestCommand.NotifyCanExecuteChanged(); try { await _plcService.WriteCoilAsync(_config.PumpCoil, true); diff --git a/Views/MainWindow.xaml b/Views/MainWindow.xaml index 280c33a..b583d80 100644 --- a/Views/MainWindow.xaml +++ b/Views/MainWindow.xaml @@ -205,36 +205,56 @@ - + - - - -