From dce31188da3d8ddc75cd9bdb1b6ee1d8e2b01146 Mon Sep 17 00:00:00 2001 From: "GukSang.Jin" Date: Thu, 29 Jan 2026 19:37:49 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CSI-H238M/CSI-H238M/Models/Model.cs | 10 +++ CSI-H238M/CSI-H238M/Services/ModbusService.cs | 76 ++++++++++++++++--- CSI-H238M/CSI-H238M/Services/Services.cs | 8 +- CSI-H238M/CSI-H238M/ViewModels/ViewModel.cs | 8 +- 4 files changed, 88 insertions(+), 14 deletions(-) diff --git a/CSI-H238M/CSI-H238M/Models/Model.cs b/CSI-H238M/CSI-H238M/Models/Model.cs index 2918b70..448d8f6 100644 --- a/CSI-H238M/CSI-H238M/Models/Model.cs +++ b/CSI-H238M/CSI-H238M/Models/Model.cs @@ -15,6 +15,16 @@ namespace COFTester.Models public double Displacement { get; set; } // 位移 (mm) public double Force { get; set; } // 力值 (N) public DateTime Timestamp { get; set; } // 採樣時間戳 + + /// + /// 升降位置 (mm) - 從 D12 寄存器讀取 + /// + public double VerticalPosition { get; set; } + + /// + /// 水平位置 (mm) - 從 D16 寄存器讀取 + /// + public double HorizontalPosition { get; set; } } /// diff --git a/CSI-H238M/CSI-H238M/Services/ModbusService.cs b/CSI-H238M/CSI-H238M/Services/ModbusService.cs index 36645d9..4d2c086 100644 --- a/CSI-H238M/CSI-H238M/Services/ModbusService.cs +++ b/CSI-H238M/CSI-H238M/Services/ModbusService.cs @@ -444,6 +444,13 @@ namespace COFTester.Services protected abstract Task AcquisitionLoopAsync(TestParameters parameters, CancellationToken token); protected abstract Task ReadSensorDataAsync(); + /// + /// 讀取位置數據(升降位置和水平位置) + /// D12 升降位置(只讀), D16 水平位置(只讀) + /// + /// 元組 (升降位置, 水平位置) + protected abstract Task<(double verticalPos, double horizontalPos)> ReadPositionDataAsync(); + /// /// 寫入校準命令到 M1300 寄存器 /// @@ -594,7 +601,7 @@ namespace COFTester.Services /// /// 數據採集主循環 - /// 正確流程:1. 寫入測試參數 → 2. 循環讀取數據 + /// 正確流程:1. 寫入測試參數 → 2. 循環讀取數據(力值、位移、位置) /// 注意:不再發送 Start/Stop 命令,由方向控制(M0-M3)來控制運動 /// protected override async Task AcquisitionLoopAsync(TestParameters parameters, CancellationToken token) @@ -616,12 +623,29 @@ namespace COFTester.Services System.Diagnostics.Debug.WriteLine($"[ModbusTCP] 開始數據採集: {totalPoints} 點, 間隔 {intervalMs:F1}ms"); System.Diagnostics.Debug.WriteLine($"[ModbusTCP] 注意:請使用方向控制按鈕(M0-M3)來啟動運動"); - // 3. 循環讀取傳感器數據 + // 3. 循環讀取傳感器數據(包含力值、位移和位置) for (int i = 0; i < totalPoints && !token.IsCancellationRequested; i++) { + // 讀取力值和位移 var dataPoint = await ReadSensorDataAsync(); + if (dataPoint != null) { + // 讀取升降位置和水平位置 + try + { + var (verticalPos, horizontalPos) = await ReadPositionDataAsync(); + dataPoint.VerticalPosition = verticalPos; + dataPoint.HorizontalPosition = horizontalPos; + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"[ModbusTCP] 讀取位置數據失敗: {ex.Message}"); + // 位置讀取失敗不影響主數據採集,繼續執行 + dataPoint.VerticalPosition = 0; + dataPoint.HorizontalPosition = 0; + } + OnDataReceived(dataPoint); } await Task.Delay((int)intervalMs, token); @@ -795,7 +819,7 @@ namespace COFTester.Services /// 讀取位置數據(升降位置和水平位置) /// D12 升降位置(只讀), D16 水平位置(只讀) /// - protected virtual async Task<(double verticalPos, double horizontalPos)> ReadPositionDataAsync() + protected override async Task<(double verticalPos, double horizontalPos)> ReadPositionDataAsync() { if (_modbusMaster == null) return (0, 0); @@ -926,7 +950,7 @@ namespace COFTester.Services /// /// 數據採集主循環 - /// 正確流程:1. 寫入測試參數 → 2. 循環讀取數據 + /// 正確流程:1. 寫入測試參數 → 2. 循環讀取數據(力值、位移、位置) /// 注意:不再發送 Start/Stop 命令,由方向控制(M0-M3)來控制運動 /// protected override async Task AcquisitionLoopAsync(TestParameters parameters, CancellationToken token) @@ -948,12 +972,29 @@ namespace COFTester.Services System.Diagnostics.Debug.WriteLine($"[ModbusRTU] 開始數據採集: {totalPoints} 點, 間隔 {intervalMs:F1}ms"); System.Diagnostics.Debug.WriteLine($"[ModbusRTU] 注意:請使用方向控制按鈕(M0-M3)來啟動運動"); - // 3. 循環讀取傳感器數據 + // 3. 循環讀取傳感器數據(包含力值、位移和位置) for (int i = 0; i < totalPoints && !token.IsCancellationRequested; i++) { + // 讀取力值和位移 var dataPoint = await ReadSensorDataAsync(); + if (dataPoint != null) { + // 讀取升降位置和水平位置 + try + { + var (verticalPos, horizontalPos) = await ReadPositionDataAsync(); + dataPoint.VerticalPosition = verticalPos; + dataPoint.HorizontalPosition = horizontalPos; + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"[ModbusRTU] 讀取位置數據失敗: {ex.Message}"); + // 位置讀取失敗不影響主數據採集,繼續執行 + dataPoint.VerticalPosition = 0; + dataPoint.HorizontalPosition = 0; + } + OnDataReceived(dataPoint); } await Task.Delay((int)intervalMs, token); @@ -1149,7 +1190,7 @@ namespace COFTester.Services /// /// 讀取位置數據 /// - protected virtual async Task<(double verticalPos, double horizontalPos)> ReadPositionDataAsync() + protected override async Task<(double verticalPos, double horizontalPos)> ReadPositionDataAsync() { if (_modbusMaster == null) return (0, 0); @@ -1270,7 +1311,7 @@ namespace COFTester.Services /// /// 數據採集主循環 - /// 正確流程:1. 寫入測試參數 → 2. 循環讀取數據 + /// 正確流程:1. 寫入測試參數 → 2. 循環讀取數據(力值、位移、位置) /// 注意:不再發送 Start/Stop 命令,由方向控制(M0-M3)來控制運動 /// protected override async Task AcquisitionLoopAsync(TestParameters parameters, CancellationToken token) @@ -1291,12 +1332,29 @@ namespace COFTester.Services System.Diagnostics.Debug.WriteLine($"[ModbusASCII] 開始數據採集: {totalPoints} 點, 間隔 {intervalMs:F1}ms"); System.Diagnostics.Debug.WriteLine($"[ModbusASCII] 注意:請使用方向控制按鈕(M0-M3)來啟動運動"); - // 3. 循環讀取傳感器數據 + // 3. 循環讀取傳感器數據(包含力值、位移和位置) for (int i = 0; i < totalPoints && !token.IsCancellationRequested; i++) { + // 讀取力值和位移 var dataPoint = await ReadSensorDataAsync(); + if (dataPoint != null) { + // 讀取升降位置和水平位置 + try + { + var (verticalPos, horizontalPos) = await ReadPositionDataAsync(); + dataPoint.VerticalPosition = verticalPos; + dataPoint.HorizontalPosition = horizontalPos; + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"[ModbusASCII] 讀取位置數據失敗: {ex.Message}"); + // 位置讀取失敗不影響主數據採集,繼續執行 + dataPoint.VerticalPosition = 0; + dataPoint.HorizontalPosition = 0; + } + OnDataReceived(dataPoint); } await Task.Delay((int)intervalMs, token); @@ -1480,7 +1538,7 @@ namespace COFTester.Services /// /// 讀取位置數據 /// - protected virtual async Task<(double verticalPos, double horizontalPos)> ReadPositionDataAsync() + protected override async Task<(double verticalPos, double horizontalPos)> ReadPositionDataAsync() { if (_modbusMaster == null) return (0, 0); diff --git a/CSI-H238M/CSI-H238M/Services/Services.cs b/CSI-H238M/CSI-H238M/Services/Services.cs index e763624..7eae4fd 100644 --- a/CSI-H238M/CSI-H238M/Services/Services.cs +++ b/CSI-H238M/CSI-H238M/Services/Services.cs @@ -475,11 +475,17 @@ namespace COFTester.Services // 確保力值非負 force = Math.Max(0, force); + // 模擬位置數據(與位移同步變化) + double verticalPos = 0.0; // 模擬升降位置(可根據需要調整) + double horizontalPos = currentDisp; // 模擬水平位置(與位移一致) + DataReceived?.Invoke(this, new TestDataPoint { Displacement = currentDisp, Force = force, - Timestamp = DateTime.Now + Timestamp = DateTime.Now, + VerticalPosition = verticalPos, + HorizontalPosition = horizontalPos }); await Task.Delay((int)intervalMs, _cts.Token); diff --git a/CSI-H238M/CSI-H238M/ViewModels/ViewModel.cs b/CSI-H238M/CSI-H238M/ViewModels/ViewModel.cs index 0ae889c..80fcfd8 100644 --- a/CSI-H238M/CSI-H238M/ViewModels/ViewModel.cs +++ b/CSI-H238M/CSI-H238M/ViewModels/ViewModel.cs @@ -446,13 +446,13 @@ namespace COFTester.ViewModels // 使用 Dispatcher 確保在 UI 線程更新 Application.Current?.Dispatcher.InvokeAsync(() => { + // 更新力值和位移 CurrentForce = point.Force; CurrentDisp = point.Displacement; - // Update position displays (using displacement as position for now) - // In a real system, these would come from separate position sensors - LiftPosition = 0.0; // Placeholder - would come from vertical position sensor - HorizontalPosition = point.Displacement; // Using displacement as horizontal position + // 更新實際位置數據(從 PLC 讀取) + LiftPosition = point.VerticalPosition; // D12 升降位置 + HorizontalPosition = point.HorizontalPosition; // D16 水平位置 _realTimePoints.Add(point); OnPropertyChanged(nameof(DataPointsCount));