diff --git a/CSI-H238M/CSI-H238M/Models/AppConfig.cs b/CSI-H238M/CSI-H238M/Models/AppConfig.cs index f4b9666..f423c0d 100644 --- a/CSI-H238M/CSI-H238M/Models/AppConfig.cs +++ b/CSI-H238M/CSI-H238M/Models/AppConfig.cs @@ -174,6 +174,9 @@ namespace COFTester.Models public ushort TestStrokeRegister { get; set; } = 26; // 測試行程 (mm),Float,2個寄存器 public ushort SamplingRateRegister { get; set; } = 28; // 採樣頻率 (Hz),Float,2個寄存器 + // === 校準寄存器(寫入)=== + public ushort CalibrationRegister { get; set; } = 1300; // 校準命令寄存器 M1300 + public int RetryCount { get; set; } = 3; // 重試次數 public int RetryDelay { get; set; } = 500; // 重試延遲(毫秒) } @@ -208,6 +211,9 @@ namespace COFTester.Models public ushort TestStrokeRegister { get; set; } = 26; // 測試行程 (mm),Float,2個寄存器 public ushort SamplingRateRegister { get; set; } = 28; // 採樣頻率 (Hz),Float,2個寄存器 + // === 校準寄存器(寫入)=== + public ushort CalibrationRegister { get; set; } = 1300; // 校準命令寄存器 M1300 + public int RetryCount { get; set; } = 3; public int RetryDelay { get; set; } = 500; } diff --git a/CSI-H238M/CSI-H238M/Models/Model.cs b/CSI-H238M/CSI-H238M/Models/Model.cs index 81904ed..54d502b 100644 --- a/CSI-H238M/CSI-H238M/Models/Model.cs +++ b/CSI-H238M/CSI-H238M/Models/Model.cs @@ -338,6 +338,22 @@ namespace COFTester.Models void StartAcquisition(TestParameters parameters); void StopAcquisition(); void ResetSensors(); + + /// + /// 零點標定 + /// + void ZeroCalibration(); + + /// + /// 拉力校準 + /// + void ForceCalibration(); + + /// + /// 復歸 + /// + void ReturnToOrigin(); + bool IsConnected { get; } } diff --git a/CSI-H238M/CSI-H238M/Resources/LanguageResources.cs b/CSI-H238M/CSI-H238M/Resources/LanguageResources.cs index c500bc0..41809b3 100644 --- a/CSI-H238M/CSI-H238M/Resources/LanguageResources.cs +++ b/CSI-H238M/CSI-H238M/Resources/LanguageResources.cs @@ -130,6 +130,10 @@ namespace COFTester.Resources ["CalibrationInstruction"] = "请确保设备已连接,然后执行以下标定步骤:", ["ZeroCalibration"] = "零点标定", ["ZeroCalibrationNote"] = "说明:在无负载状态下执行零点标定,将当前读数设为零点。", + ["ForceCalibration"] = "拉力校准", + ["ForceCalibrationNote"] = "说明:在已知标准负载下执行拉力校准,校准传感器精度。", + ["ReturnToOrigin"] = "复归", + ["ReturnToOriginNote"] = "说明:将设备返回到初始位置。", // 测试参数标签 ["SpeedLabel"] = "速度:", @@ -271,6 +275,10 @@ namespace COFTester.Resources ["CalibrationInstruction"] = "Please ensure the device is connected, then perform the following calibration steps:", ["ZeroCalibration"] = "Zero Calibration", ["ZeroCalibrationNote"] = "Note: Perform zero calibration under no-load condition to set the current reading as zero point.", + ["ForceCalibration"] = "Force Calibration", + ["ForceCalibrationNote"] = "Note: Perform force calibration under known standard load to calibrate sensor accuracy.", + ["ReturnToOrigin"] = "Return to Origin", + ["ReturnToOriginNote"] = "Note: Return the device to the initial position.", // Test Parameter Labels ["SpeedLabel"] = "Speed:", @@ -406,6 +414,10 @@ namespace COFTester.Resources public string CalibrationInstruction => GetString("CalibrationInstruction"); public string ZeroCalibration => GetString("ZeroCalibration"); public string ZeroCalibrationNote => GetString("ZeroCalibrationNote"); + public string ForceCalibration => GetString("ForceCalibration"); + public string ForceCalibrationNote => GetString("ForceCalibrationNote"); + public string ReturnToOrigin => GetString("ReturnToOrigin"); + public string ReturnToOriginNote => GetString("ReturnToOriginNote"); // Test Parameter Labels public string SpeedLabel => GetString("SpeedLabel"); @@ -542,6 +554,10 @@ namespace COFTester.Resources OnPropertyChanged(nameof(CalibrationInstruction)); OnPropertyChanged(nameof(ZeroCalibration)); OnPropertyChanged(nameof(ZeroCalibrationNote)); + OnPropertyChanged(nameof(ForceCalibration)); + OnPropertyChanged(nameof(ForceCalibrationNote)); + OnPropertyChanged(nameof(ReturnToOrigin)); + OnPropertyChanged(nameof(ReturnToOriginNote)); // Test Parameter Labels OnPropertyChanged(nameof(SpeedLabel)); diff --git a/CSI-H238M/CSI-H238M/Services/ModbusService.cs b/CSI-H238M/CSI-H238M/Services/ModbusService.cs index 6c56a19..55a5e71 100644 --- a/CSI-H238M/CSI-H238M/Services/ModbusService.cs +++ b/CSI-H238M/CSI-H238M/Services/ModbusService.cs @@ -22,6 +22,21 @@ namespace COFTester.Services Reset = 2 } + /// + /// Modbus 校準命令枚舉(寄存器 M1300) + /// + public enum ModbusCalibrationCommand : ushort + { + /// 無操作 + None = 0, + /// 零點標定 + ZeroCalibration = 1, + /// 拉力校準 + ForceCalibration = 2, + /// 復歸 + Return = 3 + } + /// /// Modbus 設備狀態枚舉 /// @@ -139,10 +154,72 @@ namespace COFTester.Services } } + /// + /// 零點標定,向 M1300 寫入命令 1 + /// + public virtual void ZeroCalibration() + { + try + { + if (_modbusMaster != null && _isConnected) + { + System.Diagnostics.Debug.WriteLine("[Modbus] 發送零點標定命令 (1) 到 M1300"); + WriteCalibrationRegisterAsync((ushort)ModbusCalibrationCommand.ZeroCalibration).Wait(); + } + } + catch (Exception ex) + { + OnErrorOccurred($"零點標定失敗: {ex.Message}"); + } + } + + /// + /// 拉力校準,向 M1300 寫入命令 2 + /// + public virtual void ForceCalibration() + { + try + { + if (_modbusMaster != null && _isConnected) + { + System.Diagnostics.Debug.WriteLine("[Modbus] 發送拉力校準命令 (2) 到 M1300"); + WriteCalibrationRegisterAsync((ushort)ModbusCalibrationCommand.ForceCalibration).Wait(); + } + } + catch (Exception ex) + { + OnErrorOccurred($"拉力校準失敗: {ex.Message}"); + } + } + + /// + /// 復歸,向 M1300 寫入命令 3 + /// + public virtual void ReturnToOrigin() + { + try + { + if (_modbusMaster != null && _isConnected) + { + System.Diagnostics.Debug.WriteLine("[Modbus] 發送復歸命令 (3) 到 M1300"); + WriteCalibrationRegisterAsync((ushort)ModbusCalibrationCommand.Return).Wait(); + } + } + catch (Exception ex) + { + OnErrorOccurred($"復歸失敗: {ex.Message}"); + } + } + protected abstract Task AcquisitionLoopAsync(TestParameters parameters, CancellationToken token); protected abstract Task ReadSensorDataAsync(); protected abstract Task WriteControlRegisterAsync(ushort value); + /// + /// 寫入校準命令到 M1300 寄存器 + /// + protected abstract Task WriteCalibrationRegisterAsync(ushort value); + /// /// 寫入測試參數到 PLC 寄存器 /// @@ -392,6 +469,23 @@ namespace COFTester.Services } } + /// + /// 寫入校準命令到 M1300 + /// 0 = 無操作 + /// 1 = 零點標定 + /// 2 = 拉力校準 + /// 3 = 復歸 + /// + protected override async Task WriteCalibrationRegisterAsync(ushort value) + { + if (_modbusMaster != null) + { + await _modbusMaster.WriteSingleRegisterAsync( + _config.SlaveId, _config.CalibrationRegister, value); + System.Diagnostics.Debug.WriteLine($"[ModbusTCP] 校準寄存器[{_config.CalibrationRegister}] = {value}"); + } + } + /// /// 寫入測試參數到 PLC 寄存器 /// 參數映射: @@ -674,6 +768,23 @@ namespace COFTester.Services } } + /// + /// 寫入校準命令到 M1300 + /// 0 = 無操作 + /// 1 = 零點標定 + /// 2 = 拉力校準 + /// 3 = 復歸 + /// + protected override async Task WriteCalibrationRegisterAsync(ushort value) + { + if (_modbusMaster != null) + { + await _modbusMaster.WriteSingleRegisterAsync( + _config.SlaveId, _config.CalibrationRegister, value); + System.Diagnostics.Debug.WriteLine($"[ModbusRTU] 校準寄存器[{_config.CalibrationRegister}] = {value}"); + } + } + /// /// 寫入測試參數到 PLC 寄存器 /// @@ -957,6 +1068,19 @@ namespace COFTester.Services } } + /// + /// 寫入校準命令到 M1300 + /// + protected override async Task WriteCalibrationRegisterAsync(ushort value) + { + if (_modbusMaster != null) + { + await _modbusMaster.WriteSingleRegisterAsync( + _config.SlaveId, _config.CalibrationRegister, value); + System.Diagnostics.Debug.WriteLine($"[ModbusASCII] 校準寄存器[{_config.CalibrationRegister}] = {value}"); + } + } + /// /// 寫入測試參數到 PLC 寄存器 /// @@ -1164,6 +1288,51 @@ namespace COFTester.Services } } + public void ZeroCalibration() + { + try + { + if (_serialPort != null && _isConnected) + { + _serialPort.WriteLine("ZERO_CAL"); + } + } + catch (Exception ex) + { + OnErrorOccurred($"零點標定失败: {ex.Message}"); + } + } + + public void ForceCalibration() + { + try + { + if (_serialPort != null && _isConnected) + { + _serialPort.WriteLine("FORCE_CAL"); + } + } + catch (Exception ex) + { + OnErrorOccurred($"拉力校準失败: {ex.Message}"); + } + } + + public void ReturnToOrigin() + { + try + { + if (_serialPort != null && _isConnected) + { + _serialPort.WriteLine("RETURN"); + } + } + catch (Exception ex) + { + OnErrorOccurred($"復歸失败: {ex.Message}"); + } + } + private async Task AcquisitionLoopAsync(TestParameters parameters, CancellationToken token) { try diff --git a/CSI-H238M/CSI-H238M/Services/Services.cs b/CSI-H238M/CSI-H238M/Services/Services.cs index 40fade8..533329e 100644 --- a/CSI-H238M/CSI-H238M/Services/Services.cs +++ b/CSI-H238M/CSI-H238M/Services/Services.cs @@ -511,5 +511,23 @@ namespace COFTester.Services { // 模擬傳感器清零(無實際操作) } + + public void ZeroCalibration() + { + // 模擬零點標定(無實際操作) + System.Diagnostics.Debug.WriteLine("[Simulated] 零點標定完成"); + } + + public void ForceCalibration() + { + // 模擬拉力校準(無實際操作) + System.Diagnostics.Debug.WriteLine("[Simulated] 拉力校準完成"); + } + + public void ReturnToOrigin() + { + // 模擬復歸(無實際操作) + System.Diagnostics.Debug.WriteLine("[Simulated] 復歸完成"); + } } } diff --git a/CSI-H238M/CSI-H238M/ViewModels/ViewModel.cs b/CSI-H238M/CSI-H238M/ViewModels/ViewModel.cs index 3ce4d56..fb60cf9 100644 --- a/CSI-H238M/CSI-H238M/ViewModels/ViewModel.cs +++ b/CSI-H238M/CSI-H238M/ViewModels/ViewModel.cs @@ -66,6 +66,11 @@ namespace COFTester.ViewModels OpenConfigCommand = new RelayCommand(OpenConfig); ClearAllTestsCommand = new RelayCommand(ClearAllTests, () => !_isTesting && TestRecords?.Count > 0); GenerateReportCommand = new RelayCommand(GenerateReport, () => TestRecords?.Count > 0); + + // 校準命令 + ZeroCalibrationCommand = new RelayCommand(ZeroCalibration, () => !_isTesting && IsConnected); + ForceCalibrationCommand = new RelayCommand(ForceCalibration, () => !_isTesting && IsConnected); + ReturnToOriginCommand = new RelayCommand(ReturnToOrigin, () => !_isTesting && IsConnected); Parameters = _config.DefaultTestParameters ?? new TestParameters(); TestRecords = new ObservableCollection(); @@ -418,6 +423,11 @@ namespace COFTester.ViewModels public ICommand OpenConfigCommand { get; } public ICommand ClearAllTestsCommand { get; } public ICommand GenerateReportCommand { get; } + + // 校準命令 + public ICommand ZeroCalibrationCommand { get; } + public ICommand ForceCalibrationCommand { get; } + public ICommand ReturnToOriginCommand { get; } #endregion #region Event Handlers @@ -622,6 +632,111 @@ namespace COFTester.ViewModels _daqService.ResetSensors(); } + /// + /// 零點標定 - 向 M1300 寫入命令 1 + /// + private void ZeroCalibration() + { + try + { + if (!IsConnected) + { + StatusMessage = "请先连接设备"; + MessageBox.Show("请先连接设备后再执行零点标定", "提示", MessageBoxButton.OK, MessageBoxImage.Information); + return; + } + + StatusMessage = "正在执行零点标定..."; + _daqService.ZeroCalibration(); + StatusMessage = "零点标定完成"; + + System.Diagnostics.Debug.WriteLine("[ViewModel] 零点标定命令已发送"); + + MessageBox.Show("零点标定完成!\n\n当前读数已设为零点。", + "标定成功", + MessageBoxButton.OK, + MessageBoxImage.Information); + } + catch (Exception ex) + { + StatusMessage = $"零点标定失败: {ex.Message}"; + MessageBox.Show($"零点标定时发生错误:\n{ex.Message}", + "错误", + MessageBoxButton.OK, + MessageBoxImage.Error); + } + } + + /// + /// 拉力校准 - 向 M1300 写入命令 2 + /// + private void ForceCalibration() + { + try + { + if (!IsConnected) + { + StatusMessage = "请先连接设备"; + MessageBox.Show("请先连接设备后再执行拉力校准", "提示", MessageBoxButton.OK, MessageBoxImage.Information); + return; + } + + StatusMessage = "正在执行拉力校准..."; + _daqService.ForceCalibration(); + StatusMessage = "拉力校准完成"; + + System.Diagnostics.Debug.WriteLine("[ViewModel] 拉力校准命令已发送"); + + MessageBox.Show("拉力校准完成!\n\n传感器已校准。", + "校准成功", + MessageBoxButton.OK, + MessageBoxImage.Information); + } + catch (Exception ex) + { + StatusMessage = $"拉力校准失败: {ex.Message}"; + MessageBox.Show($"拉力校准时发生错误:\n{ex.Message}", + "错误", + MessageBoxButton.OK, + MessageBoxImage.Error); + } + } + + /// + /// 复归 - 向 M1300 写入命令 3 + /// + private void ReturnToOrigin() + { + try + { + if (!IsConnected) + { + StatusMessage = "请先连接设备"; + MessageBox.Show("请先连接设备后再执行复归", "提示", MessageBoxButton.OK, MessageBoxImage.Information); + return; + } + + StatusMessage = "正在执行复归..."; + _daqService.ReturnToOrigin(); + StatusMessage = "复归完成"; + + System.Diagnostics.Debug.WriteLine("[ViewModel] 复归命令已发送"); + + MessageBox.Show("复归完成!\n\n设备已返回原点。", + "复归成功", + MessageBoxButton.OK, + MessageBoxImage.Information); + } + catch (Exception ex) + { + StatusMessage = $"复归失败: {ex.Message}"; + MessageBox.Show($"复归时发生错误:\n{ex.Message}", + "错误", + MessageBoxButton.OK, + MessageBoxImage.Error); + } + } + /// /// 添加曲线到图表 /// diff --git a/CSI-H238M/CSI-H238M/Views/CalibrationPage.xaml b/CSI-H238M/CSI-H238M/Views/CalibrationPage.xaml index 556ab6c..a04a81c 100644 --- a/CSI-H238M/CSI-H238M/Views/CalibrationPage.xaml +++ b/CSI-H238M/CSI-H238M/Views/CalibrationPage.xaml @@ -71,7 +71,8 @@ - + + + + + + + diff --git a/CSI-H238M/config.json b/CSI-H238M/config.json index 6562d32..892a603 100644 --- a/CSI-H238M/config.json +++ b/CSI-H238M/config.json @@ -15,6 +15,7 @@ "TestDurationRegister": 24, "TestStrokeRegister": 26, "SamplingRateRegister": 28, + "CalibrationRegister": 1300, "RetryCount": 3, "RetryDelay": 500 }, @@ -37,6 +38,7 @@ "TestDurationRegister": 24, "TestStrokeRegister": 26, "SamplingRateRegister": 28, + "CalibrationRegister": 1300, "RetryCount": 3, "RetryDelay": 500 },