This commit is contained in:
Binary file not shown.
@@ -30,8 +30,8 @@ public class PlcRegisterAddresses
|
|||||||
// 计算结果寄存器(浮点数)
|
// 计算结果寄存器(浮点数)
|
||||||
public ushort ThermalConductivity { get; set; } = 40001;
|
public ushort ThermalConductivity { get; set; } = 40001;
|
||||||
public ushort ThermalDiffusivity { get; set; } = 40003;
|
public ushort ThermalDiffusivity { get; set; } = 40003;
|
||||||
public ushort StartCommand { get; set; } = 40010;
|
public ushort StartCommand { get; set; } = 4;
|
||||||
public ushort ResetCommand { get; set; } = 40011;
|
public ushort ResetCommand { get; set; } = 4;
|
||||||
|
|
||||||
// 线圈地址(注意:Modbus 线圈地址通常从 0 开始,但用户给出的 M1300 等可能是实际地址)
|
// 线圈地址(注意:Modbus 线圈地址通常从 0 开始,但用户给出的 M1300 等可能是实际地址)
|
||||||
public ushort PressureCalibrationCoil { get; set; } = 1300;
|
public ushort PressureCalibrationCoil { get; set; } = 1300;
|
||||||
|
|||||||
178
Services/LanScpiSocket.cs
Normal file
178
Services/LanScpiSocket.cs
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
using System;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace ASTM_D7896_Tester.Services
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 基于 LAN (TCP/IP) 的 TH1963 数字多用表通信服务
|
||||||
|
/// 支持 SCPI 命令,实现高速批量采集
|
||||||
|
/// </summary>
|
||||||
|
public class Th1963LanService : IDisposable
|
||||||
|
{
|
||||||
|
private TcpClient _tcpClient;
|
||||||
|
private NetworkStream _stream;
|
||||||
|
private bool _disposed = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 接收缓冲区大小(字节),建议至少 1MB 以支持大量数据
|
||||||
|
/// </summary>
|
||||||
|
public int ReceiveBufferSize { get; set; } = 2 * 1024 * 1024; // 2 MB
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 连接超时(毫秒)
|
||||||
|
/// </summary>
|
||||||
|
public int ConnectTimeoutMs { get; set; } = 3000;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读写超时(毫秒)
|
||||||
|
/// </summary>
|
||||||
|
public int ReadWriteTimeoutMs { get; set; } = 5000;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 连接到 TH1963
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ipAddress">仪器 IP 地址,如 "192.168.1.241"</param>
|
||||||
|
/// <param name="port">端口号,默认 45454</param>
|
||||||
|
public async Task ConnectAsync(string ipAddress, int port = 45454)
|
||||||
|
{
|
||||||
|
if (_tcpClient != null && _tcpClient.Connected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_tcpClient = new TcpClient();
|
||||||
|
_tcpClient.ReceiveBufferSize = ReceiveBufferSize;
|
||||||
|
_tcpClient.SendBufferSize = ReceiveBufferSize;
|
||||||
|
|
||||||
|
var connectTask = _tcpClient.ConnectAsync(ipAddress, port);
|
||||||
|
if (await Task.WhenAny(connectTask, Task.Delay(ConnectTimeoutMs)) != connectTask)
|
||||||
|
throw new TimeoutException($"连接 TH1963 ({ipAddress}:{port}) 超时");
|
||||||
|
|
||||||
|
_stream = _tcpClient.GetStream();
|
||||||
|
_stream.ReadTimeout = ReadWriteTimeoutMs;
|
||||||
|
_stream.WriteTimeout = ReadWriteTimeoutMs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送 SCPI 命令并等待响应(适用于查询类命令)
|
||||||
|
/// </summary>
|
||||||
|
public async Task<string> QueryAsync(string command)
|
||||||
|
{
|
||||||
|
EnsureConnected();
|
||||||
|
byte[] cmdBytes = Encoding.ASCII.GetBytes(command + "\n");
|
||||||
|
await _stream.WriteAsync(cmdBytes, 0, cmdBytes.Length);
|
||||||
|
|
||||||
|
// 读取响应,直到换行符
|
||||||
|
var responseBuilder = new StringBuilder();
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int bytesRead;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
bytesRead = await _stream.ReadAsync(buffer, 0, buffer.Length);
|
||||||
|
if (bytesRead == 0) break;
|
||||||
|
string chunk = Encoding.ASCII.GetString(buffer, 0, bytesRead);
|
||||||
|
responseBuilder.Append(chunk);
|
||||||
|
if (chunk.Contains("\n")) break;
|
||||||
|
}
|
||||||
|
return responseBuilder.ToString().Trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送命令但不等待响应(适用于设置类命令)
|
||||||
|
/// </summary>
|
||||||
|
public async Task SendCommandAsync(string command)
|
||||||
|
{
|
||||||
|
EnsureConnected();
|
||||||
|
byte[] cmdBytes = Encoding.ASCII.GetBytes(command + "\n");
|
||||||
|
await _stream.WriteAsync(cmdBytes, 0, cmdBytes.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 配置为高速直流电压测量(用于批量采集)
|
||||||
|
/// 设置:0.02 PLC(≈400μs积分时间),自动量程,关闭自动归零
|
||||||
|
/// </summary>
|
||||||
|
public async Task ConfigureForHighSpeedDcvAsync()
|
||||||
|
{
|
||||||
|
await SendCommandAsync("CONF:VOLT:DC AUTO");
|
||||||
|
await SendCommandAsync("VOLT:DC:NPLC 0.02"); // 最快速度
|
||||||
|
await SendCommandAsync("VOLT:DC:ZERO:AUTO OFF"); // 提高速度
|
||||||
|
await SendCommandAsync("TRIG:SOUR EXT"); // 外部触发(与PLC同步)
|
||||||
|
await SendCommandAsync("TRIG:DEL:AUTO OFF");
|
||||||
|
await SendCommandAsync("TRIG:DEL 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 批量采集指定数量的电压值(使用外部触发,需等待硬件触发信号)
|
||||||
|
/// 调用前必须已执行 ConfigureForHighSpeedDcvAsync 和 SAMP:COUN
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sampleCount">采样点数(最大 5000)</param>
|
||||||
|
/// <returns>电压数组(单位:伏特)</returns>
|
||||||
|
public async Task<double[]> AcquireBatchAsync(int sampleCount)
|
||||||
|
{
|
||||||
|
// 预置采样点数
|
||||||
|
await SendCommandAsync($"SAMP:COUN {sampleCount}");
|
||||||
|
// 进入等待触发状态
|
||||||
|
await SendCommandAsync("INIT");
|
||||||
|
|
||||||
|
// 等待采集完成(估算:sampleCount / 1000 秒 + 稳定时间)
|
||||||
|
int waitMs = (int)(sampleCount / 1000.0 * 1000) + 200;
|
||||||
|
await Task.Delay(waitMs);
|
||||||
|
|
||||||
|
// 取回数据
|
||||||
|
string response = await QueryAsync("FETCh?");
|
||||||
|
string[] parts = response.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
double[] values = new double[parts.Length];
|
||||||
|
for (int i = 0; i < parts.Length; i++)
|
||||||
|
{
|
||||||
|
if (!double.TryParse(parts[i], System.Globalization.NumberStyles.Float,
|
||||||
|
System.Globalization.CultureInfo.InvariantCulture, out values[i]))
|
||||||
|
throw new Exception($"解析电压值失败: {parts[i]}");
|
||||||
|
}
|
||||||
|
if (values.Length != sampleCount)
|
||||||
|
throw new Exception($"期望 {sampleCount} 个点,实际收到 {values.Length}");
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 单次读取当前电压(非批量,用于实时监控)
|
||||||
|
/// </summary>
|
||||||
|
public async Task<double> ReadVoltageAsync()
|
||||||
|
{
|
||||||
|
string resp = await QueryAsync("MEAS:VOLT:DC?");
|
||||||
|
if (double.TryParse(resp, System.Globalization.NumberStyles.Float,
|
||||||
|
System.Globalization.CultureInfo.InvariantCulture, out double value))
|
||||||
|
return value;
|
||||||
|
throw new Exception($"电压读数无效: {resp}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 复位仪器
|
||||||
|
/// </summary>
|
||||||
|
public async Task ResetAsync() => await SendCommandAsync("*RST");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查询仪器标识
|
||||||
|
/// </summary>
|
||||||
|
public async Task<string> IdentifyAsync() => await QueryAsync("*IDN?");
|
||||||
|
|
||||||
|
private void EnsureConnected()
|
||||||
|
{
|
||||||
|
if (_tcpClient == null || !_tcpClient.Connected)
|
||||||
|
throw new InvalidOperationException("未连接到 TH1963,请先调用 ConnectAsync");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实现 IDisposable
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (!_disposed)
|
||||||
|
{
|
||||||
|
_stream?.Close();
|
||||||
|
_tcpClient?.Close();
|
||||||
|
_stream?.Dispose();
|
||||||
|
_tcpClient?.Dispose();
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -48,10 +48,12 @@ public class PlcService : IPlcService
|
|||||||
// 现在可以直接使用扩展方法
|
// 现在可以直接使用扩展方法
|
||||||
await _tcpClient.ConnectAsync(_config.PlcConnection.IpAddress, _config.PlcConnection.Port).WithCancellation(cts.Token);
|
await _tcpClient.ConnectAsync(_config.PlcConnection.IpAddress, _config.PlcConnection.Port).WithCancellation(cts.Token);
|
||||||
_master = ModbusIpMaster.CreateIp(_tcpClient);
|
_master = ModbusIpMaster.CreateIp(_tcpClient);
|
||||||
|
await ConnectAsync();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (Exception ex) when (i < retryCount - 1)
|
catch (Exception ex) when (i < retryCount - 1)
|
||||||
{
|
{
|
||||||
|
await DisconnectAsync();
|
||||||
System.Diagnostics.Debug.WriteLine($"连接失败,{500}ms 后重试... {ex.Message}");
|
System.Diagnostics.Debug.WriteLine($"连接失败,{500}ms 后重试... {ex.Message}");
|
||||||
await Task.Delay(500);
|
await Task.Delay(500);
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
TH1963说明书 (3).pdf
Normal file
BIN
TH1963说明书 (3).pdf
Normal file
Binary file not shown.
@@ -9,6 +9,7 @@ using OxyPlot.Series;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
|
||||||
@@ -20,9 +21,15 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
private AppConfig _config;
|
private AppConfig _config;
|
||||||
private readonly ReportService _reportService;
|
private readonly ReportService _reportService;
|
||||||
|
|
||||||
|
// ======================= 成员变量 =======================
|
||||||
|
private Timer? _monitorTimer; // 后台监控定时器
|
||||||
|
private readonly object _monitorLock = new(); // 监控更新锁
|
||||||
|
private double _lastRawPressure = 0; // 上次压力原始值
|
||||||
|
private double _lastRawTemperature = 0; // 上次温度原始值
|
||||||
|
|
||||||
|
// ======================= UI绑定属性 =======================
|
||||||
public ObservableCollection<string> ReferenceLiquids { get; } = new() { "蒸馏水", "甲苯", "乙二醇" };
|
public ObservableCollection<string> ReferenceLiquids { get; } = new() { "蒸馏水", "甲苯", "乙二醇" };
|
||||||
|
|
||||||
// 样品信息
|
|
||||||
[ObservableProperty] private string _sampleId = "未命名样品";
|
[ObservableProperty] private string _sampleId = "未命名样品";
|
||||||
[ObservableProperty] private double _testTemperature = 25.0;
|
[ObservableProperty] private double _testTemperature = 25.0;
|
||||||
[ObservableProperty] private string _testDateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
[ObservableProperty] private string _testDateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
@@ -34,7 +41,7 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
[ObservableProperty] private double _averageThermalDiffusivity;
|
[ObservableProperty] private double _averageThermalDiffusivity;
|
||||||
[ObservableProperty] private double _averageVolumetricHeatCapacity;
|
[ObservableProperty] private double _averageVolumetricHeatCapacity;
|
||||||
|
|
||||||
// 测试条件
|
// 测试条件(测试前设置)
|
||||||
[ObservableProperty] private double _sampleVolume = 40.0;
|
[ObservableProperty] private double _sampleVolume = 40.0;
|
||||||
[ObservableProperty] private bool _bubbleRemoved = true;
|
[ObservableProperty] private bool _bubbleRemoved = true;
|
||||||
[ObservableProperty] private bool _usePressure = false;
|
[ObservableProperty] private bool _usePressure = false;
|
||||||
@@ -46,6 +53,11 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
[ObservableProperty] private bool _platinumCompatible = true;
|
[ObservableProperty] private bool _platinumCompatible = true;
|
||||||
[ObservableProperty] private string _liquidReactivityNote = "";
|
[ObservableProperty] private string _liquidReactivityNote = "";
|
||||||
|
|
||||||
|
// 实时监控参数(测试前+测试中+测试后持续更新)
|
||||||
|
[ObservableProperty] private double _platinumResistance = 0.0; // 铂丝电阻(实时)
|
||||||
|
[ObservableProperty] private double _chamberPressure = 0.0; // 样品池压力(实时)
|
||||||
|
[ObservableProperty] private double _currentTestTemperature = 0.0; // 当前测试温度(实时)
|
||||||
|
|
||||||
// 系统校准
|
// 系统校准
|
||||||
[ObservableProperty] private bool _isCalibrating = false;
|
[ObservableProperty] private bool _isCalibrating = false;
|
||||||
[ObservableProperty] private string _calibrationStatus = "";
|
[ObservableProperty] private string _calibrationStatus = "";
|
||||||
@@ -54,62 +66,101 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
[ObservableProperty] private double _measuredConductivity = 0.0;
|
[ObservableProperty] private double _measuredConductivity = 0.0;
|
||||||
[ObservableProperty] private double _calibrationErrorPercent = 0.0;
|
[ObservableProperty] private double _calibrationErrorPercent = 0.0;
|
||||||
|
|
||||||
// 实时核心参数(直接从PLC读取)
|
|
||||||
[ObservableProperty] private double _platinumVoltage; // 铂丝电压 U_pt (V)
|
|
||||||
[ObservableProperty] private double _standardResistorVoltage; // 标准电阻电压 (V)
|
|
||||||
[ObservableProperty] private double _platinumResistance; // 铂丝电阻 (Ω)
|
|
||||||
[ObservableProperty] private double _chamberPressure; // 样品池压力 (kPa)
|
|
||||||
|
|
||||||
// 温升曲线
|
// 温升曲线
|
||||||
[ObservableProperty] private string _curveTitle = "温升曲线";
|
[ObservableProperty] private string _curveTitle = "温升曲线";
|
||||||
[ObservableProperty] private PlotModel _temperatureCurveModel;
|
[ObservableProperty] private PlotModel _temperatureCurveModel;
|
||||||
|
|
||||||
|
|
||||||
|
private Th1963LanService _th1963Upt;
|
||||||
|
private Th1963LanService _th1963Ustd;
|
||||||
|
|
||||||
|
|
||||||
|
// ======================= 构造函数 =======================
|
||||||
public D7896ViewModel()
|
public D7896ViewModel()
|
||||||
{
|
{
|
||||||
_config = App.PlcConfig ?? new AppConfig();
|
_config = App.PlcConfig ?? new AppConfig();
|
||||||
_plcService = App.PlcService;
|
_plcService = App.PlcService;
|
||||||
_reportService = new ReportService(_config.TestParameters.ReportOutputPath);
|
_reportService = new ReportService(_config.TestParameters.ReportOutputPath);
|
||||||
|
|
||||||
// 加载默认值
|
// 加载配置中的默认值
|
||||||
SampleVolume = _config.TestParameters.DefaultSampleVolume;
|
SampleVolume = _config.TestParameters.DefaultSampleVolume;
|
||||||
UsePressure = _config.TestParameters.UsePressure;
|
UsePressure = _config.TestParameters.UsePressure;
|
||||||
PressureValue = _config.TestParameters.DefaultPressure;
|
PressureValue = _config.TestParameters.DefaultPressure;
|
||||||
SelectedReferenceLiquid = _config.TestParameters.ReferenceLiquid;
|
SelectedReferenceLiquid = _config.TestParameters.ReferenceLiquid;
|
||||||
ReferenceConductivity = _config.TestParameters.ReferenceConductivity;
|
ReferenceConductivity = _config.TestParameters.ReferenceConductivity;
|
||||||
|
|
||||||
// 默认确认项为 true(避免每次手动勾选)
|
// 前置确认项默认勾选
|
||||||
IsCleanConfirmed = true;
|
IsCleanConfirmed = true;
|
||||||
BubbleRemoved = true;
|
BubbleRemoved = true;
|
||||||
PlatinumCompatible = true;
|
PlatinumCompatible = true;
|
||||||
AmbientCalibrated = true;
|
AmbientCalibrated = true;
|
||||||
|
|
||||||
|
// 启动后台监控
|
||||||
|
StartBackgroundMonitoring();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ======================= 实时数据更新 =======================
|
// ======================= 后台监控系统 =======================
|
||||||
private async Task UpdateRealTimeParametersAsync()
|
private async void StartBackgroundMonitoring()
|
||||||
|
{
|
||||||
|
// 等待PLC连接
|
||||||
|
await Task.Delay(1000);
|
||||||
|
|
||||||
|
_monitorTimer = new Timer(async _ => await MonitorPlcValues(), null, 0, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task MonitorPlcValues()
|
||||||
{
|
{
|
||||||
if (!await _plcService.IsConnectedAsync())
|
if (!await _plcService.IsConnectedAsync())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
lock (_monitorLock)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 1. 读取铂丝电阻值(D1422,0.001Ω单位)
|
||||||
|
float rawResistance = _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.Resistance).Result;
|
||||||
|
double newResistance = rawResistance / 1000.0;
|
||||||
|
if (Math.Abs(newResistance - _lastRawPressure) > 0.0001)
|
||||||
|
{
|
||||||
|
_lastRawPressure = newResistance;
|
||||||
|
Application.Current.Dispatcher.Invoke(() => PlatinumResistance = newResistance);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 读取压力值(D1322,0.1kPa单位)
|
||||||
|
float rawPressure = _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.Pressure).Result;
|
||||||
|
|
||||||
|
_lastRawTemperature = rawPressure;
|
||||||
|
Application.Current.Dispatcher.Invoke(() => ChamberPressure = rawPressure);
|
||||||
|
|
||||||
|
|
||||||
|
// 3. 读取温度值(D1376,0.1℃单位)
|
||||||
|
float rawTemp = _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.Temperature).Result;
|
||||||
|
|
||||||
|
|
||||||
|
Application.Current.Dispatcher.Invoke(() => CurrentTestTemperature = rawTemp);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"监控读取失败: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ======================= 测试前:获取初始铂丝电阻 =======================
|
||||||
|
private async Task<double> GetInitialResistanceAsync()
|
||||||
|
{
|
||||||
|
if (!await _plcService.IsConnectedAsync())
|
||||||
|
return 0;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 读取温度(D1376,假设为0.1℃单位,转换为℃)
|
|
||||||
float rawTemp = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.Temperature);
|
|
||||||
TestTemperature = rawTemp / 10.0;
|
|
||||||
|
|
||||||
// 读取压力(D1322,假设为0.1kPa单位)
|
|
||||||
float rawPressure = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.Pressure);
|
|
||||||
ChamberPressure = rawPressure / 10.0;
|
|
||||||
|
|
||||||
// 读取铂丝电阻(D1422,假设为0.001Ω单位)
|
|
||||||
float rawResistance = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.Resistance);
|
float rawResistance = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.Resistance);
|
||||||
PlatinumResistance = rawResistance / 1000.0;
|
return rawResistance / 1000.0;
|
||||||
|
|
||||||
// 注意:铂丝电压和标准电阻电压可能需要从其他寄存器读取,如果没有则不更新
|
|
||||||
// 如有对应寄存器请添加
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch
|
||||||
{
|
{
|
||||||
StatusMessage = $"实时参数读取失败: {ex.Message}";
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +168,7 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private async Task StartTestAsync()
|
private async Task StartTestAsync()
|
||||||
{
|
{
|
||||||
// 前置检查
|
// ========== 第1阶段:测试前置检查(标准7.1、7.6、1.4、8.1) ==========
|
||||||
if (!IsCleanConfirmed || !BubbleRemoved || !PlatinumCompatible || !AmbientCalibrated)
|
if (!IsCleanConfirmed || !BubbleRemoved || !PlatinumCompatible || !AmbientCalibrated)
|
||||||
{
|
{
|
||||||
MessageBox.Show("请完成所有测试前确认项(清洁、排泡、铂兼容性、环境校准)。", "前置条件未满足");
|
MessageBox.Show("请完成所有测试前确认项(清洁、排泡、铂兼容性、环境校准)。", "前置条件未满足");
|
||||||
@@ -128,6 +179,8 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
MessageBox.Show("请输入有效的样品量(≥1 mL)。", "参数错误");
|
MessageBox.Show("请输入有效的样品量(≥1 mL)。", "参数错误");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 加压条件检查(标准1.8、附录A2)
|
||||||
if (UsePressure && PressureValue <= 0)
|
if (UsePressure && PressureValue <= 0)
|
||||||
{
|
{
|
||||||
MessageBox.Show("请设置有效的加压值(>0 kPa)。", "参数错误");
|
MessageBox.Show("请设置有效的加压值(>0 kPa)。", "参数错误");
|
||||||
@@ -140,6 +193,7 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 连接PLC
|
||||||
if (!await _plcService.IsConnectedAsync())
|
if (!await _plcService.IsConnectedAsync())
|
||||||
{
|
{
|
||||||
var connected = await _plcService.ConnectAsync();
|
var connected = await _plcService.ConnectAsync();
|
||||||
@@ -150,17 +204,25 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果需要加压,开启进气阀并等待压力稳定
|
// ========== 第2阶段:加压控制(标准1.7-1.8、附录A2) ==========
|
||||||
if (UsePressure)
|
if (UsePressure)
|
||||||
{
|
{
|
||||||
|
StatusMessage = "正在加压...";
|
||||||
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.InletValveCoil, true);
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.InletValveCoil, true);
|
||||||
await Task.Delay(2000); // 等待加压
|
await Task.Delay(3000);
|
||||||
// 实时读取压力并显示
|
|
||||||
await UpdateRealTimeParametersAsync();
|
await UpdateRealTimeParametersAsync();
|
||||||
if (ChamberPressure < PressureValue - 5)
|
if (ChamberPressure < PressureValue - 5)
|
||||||
MessageBox.Show($"压力未达到设定值 {PressureValue} kPa,当前 {ChamberPressure:F1} kPa", "警告");
|
MessageBox.Show($"压力未达到设定值 {PressureValue} kPa,当前 {ChamberPressure:F1} kPa", "警告");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========== 第3阶段:获取初始铂丝电阻 R₀(用于校准) ==========
|
||||||
|
double initialResistance = await GetInitialResistanceAsync();
|
||||||
|
if (initialResistance > 0)
|
||||||
|
{
|
||||||
|
StatusMessage = $"初始电阻已读取: {initialResistance:F4} Ω";
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 第4阶段:执行10次重复测量(标准4.1、5.4) ==========
|
||||||
Measurements.Clear();
|
Measurements.Clear();
|
||||||
IsTesting = true;
|
IsTesting = true;
|
||||||
StatusMessage = "开始测试...";
|
StatusMessage = "开始测试...";
|
||||||
@@ -172,22 +234,22 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
CurrentMeasurementIndex = i;
|
CurrentMeasurementIndex = i;
|
||||||
StatusMessage = $"正在执行第 {i} 次测量...";
|
StatusMessage = $"正在执行第 {i} 次测量...";
|
||||||
|
|
||||||
// 启动单次测量(触发PLC内的加热脉冲)
|
// 4.1 发送加热脉冲(标准5.4:短时电流施加)
|
||||||
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.StartCommand, true);
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.StartCommand, true);
|
||||||
await Task.Delay(500);
|
//await Task.Delay(500);
|
||||||
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.StartCommand, false);
|
//await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.StartCommand, false);
|
||||||
|
|
||||||
// 等待测量完成(PLC计算需要时间)
|
// 4.2 等待测量完成(标准5.3:0.8秒测试时间)
|
||||||
await Task.Delay(2000);
|
await Task.Delay(800);
|
||||||
|
|
||||||
// 读取计算结果(热导率λ、热扩散率α)
|
// 4.3 读取计算结果(标准1.2:λ和α直接测量)
|
||||||
float lambda = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.ThermalConductivity);
|
float lambda = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.ThermalConductivity);
|
||||||
float alpha = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.ThermalDiffusivity);
|
float alpha = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.ThermalDiffusivity);
|
||||||
|
|
||||||
// 实时更新温度、压力、电阻
|
// 记录测试温度
|
||||||
await UpdateRealTimeParametersAsync();
|
if (i == 1) TestTemperature = CurrentTestTemperature;
|
||||||
|
|
||||||
// 生成温升曲线(根据实际λ和α,如果用真实U_pt数据需额外采集)
|
// 生成温升曲线
|
||||||
GenerateTemperatureCurve(lambda, alpha);
|
GenerateTemperatureCurve(lambda, alpha);
|
||||||
|
|
||||||
var result = new MeasurementResult
|
var result = new MeasurementResult
|
||||||
@@ -201,10 +263,12 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
Application.Current.Dispatcher.Invoke(() => Measurements.Add(result));
|
Application.Current.Dispatcher.Invoke(() => Measurements.Add(result));
|
||||||
StatusMessage = $"第 {i} 次测量完成,λ={lambda:F4} W/m·K";
|
StatusMessage = $"第 {i} 次测量完成,λ={lambda:F4} W/m·K";
|
||||||
|
|
||||||
|
// 4.4 间隔30秒(标准5.4)
|
||||||
if (i < _config.TestParameters.MeasurementCount)
|
if (i < _config.TestParameters.MeasurementCount)
|
||||||
await Task.Delay(_config.TestParameters.IntervalSeconds * 1000);
|
await Task.Delay(_config.TestParameters.IntervalSeconds * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 计算平均值
|
||||||
CalculateAverages();
|
CalculateAverages();
|
||||||
StatusMessage = "测试完成。";
|
StatusMessage = "测试完成。";
|
||||||
}
|
}
|
||||||
@@ -215,7 +279,7 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
// 测试结束,关闭进气阀,打开排气阀泄压
|
// ========== 第5阶段:测试结束后泄压 ==========
|
||||||
if (UsePressure)
|
if (UsePressure)
|
||||||
{
|
{
|
||||||
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.InletValveCoil, false);
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.InletValveCoil, false);
|
||||||
@@ -224,11 +288,55 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.OutletValveCoil, false);
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.OutletValveCoil, false);
|
||||||
}
|
}
|
||||||
IsTesting = false;
|
IsTesting = false;
|
||||||
await _plcService.DisconnectAsync();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ======================= 温升曲线(真实数据需要U_pt时间序列,此处暂用理论公式) =======================
|
[RelayCommand]
|
||||||
|
private async Task StopTestCommandAsync()
|
||||||
|
{
|
||||||
|
if (IsTesting)
|
||||||
|
{
|
||||||
|
IsTesting = false;
|
||||||
|
StatusMessage = "已停止测试。";
|
||||||
|
}
|
||||||
|
if (!IsTesting)
|
||||||
|
{
|
||||||
|
MessageBox.Show("没有正在进行的测试。", "提示");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(500);
|
||||||
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.StartCommand, false);
|
||||||
|
// 泄压
|
||||||
|
if (UsePressure)
|
||||||
|
{
|
||||||
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.InletValveCoil, false);
|
||||||
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.OutletValveCoil, true);
|
||||||
|
await Task.Delay(1000);
|
||||||
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.OutletValveCoil, false);
|
||||||
|
}
|
||||||
|
IsTesting = false;
|
||||||
|
StatusMessage = "测试已停止。";
|
||||||
|
}
|
||||||
|
|
||||||
|
// ======================= 辅助方法 =======================
|
||||||
|
private async Task UpdateRealTimeParametersAsync()
|
||||||
|
{
|
||||||
|
if (!await _plcService.IsConnectedAsync())
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 压力(D1322,0.1kPa单位)
|
||||||
|
float rawPressure = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.Pressure);
|
||||||
|
ChamberPressure = rawPressure / 10.0;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
StatusMessage = $"实时参数读取失败: {ex.Message}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void GenerateTemperatureCurve(float lambda, float alpha)
|
private void GenerateTemperatureCurve(float lambda, float alpha)
|
||||||
{
|
{
|
||||||
if (TemperatureCurveModel == null)
|
if (TemperatureCurveModel == null)
|
||||||
@@ -245,9 +353,8 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
StrokeThickness = 1.5
|
StrokeThickness = 1.5
|
||||||
};
|
};
|
||||||
|
|
||||||
// 理论公式 ΔT = (Q/(4πλL)) * ln(t/t0) + C,Q = I²R
|
// 理论公式 ΔT = (Q/(4πλL)) * ln(t/t0) + C
|
||||||
// 实际应用时应根据采集的铂丝电压 U_pt(t) 计算温升
|
double Q = 0.01;
|
||||||
double Q = 0.01; // 示例值,应从实际电流和电阻计算
|
|
||||||
double L = _config.TestParameters.PlatinumWireLength;
|
double L = _config.TestParameters.PlatinumWireLength;
|
||||||
double constant = 0.2;
|
double constant = 0.2;
|
||||||
for (int i = 1; i <= 200; i++)
|
for (int i = 1; i <= 200; i++)
|
||||||
@@ -275,6 +382,7 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
AverageVolumetricHeatCapacity = Measurements.Average(m => m.VolumetricHeatCapacity);
|
AverageVolumetricHeatCapacity = Measurements.Average(m => m.VolumetricHeatCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ======================= UI命令 =======================
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private void Reset()
|
private void Reset()
|
||||||
{
|
{
|
||||||
@@ -307,7 +415,8 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
["AmbientTemperature"] = AmbientTemperature,
|
["AmbientTemperature"] = AmbientTemperature,
|
||||||
["AmbientCalibrated"] = AmbientCalibrated,
|
["AmbientCalibrated"] = AmbientCalibrated,
|
||||||
["PlatinumCompatible"] = PlatinumCompatible,
|
["PlatinumCompatible"] = PlatinumCompatible,
|
||||||
["LiquidReactivityNote"] = LiquidReactivityNote
|
["LiquidReactivityNote"] = LiquidReactivityNote,
|
||||||
|
["InitialResistance"] = PlatinumResistance // 测试前的初始电阻
|
||||||
};
|
};
|
||||||
string reportPath = await _reportService.GenerateReportAsync(SampleId, TestTemperature, Measurements.ToList(),
|
string reportPath = await _reportService.GenerateReportAsync(SampleId, TestTemperature, Measurements.ToList(),
|
||||||
AverageThermalConductivity, AverageThermalDiffusivity, AverageVolumetricHeatCapacity,
|
AverageThermalConductivity, AverageThermalDiffusivity, AverageVolumetricHeatCapacity,
|
||||||
@@ -320,25 +429,16 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ======================= 新增控制命令 =======================
|
// 控制命令
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private async Task PressureCalibrationAsync()
|
private async Task PressureCalibrationAsync()
|
||||||
{
|
{
|
||||||
await EnsureConnected();
|
|
||||||
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.PressureCalibrationCoil, true);
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.PressureCalibrationCoil, true);
|
||||||
await Task.Delay(500);
|
|
||||||
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.PressureCalibrationCoil, false);
|
|
||||||
StatusMessage = "压力校准指令已发送";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private async Task ResistanceZeroAsync()
|
private async Task ResistanceZeroAsync()
|
||||||
{
|
{
|
||||||
await EnsureConnected();
|
|
||||||
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.ResistanceZeroCoil, true);
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.ResistanceZeroCoil, true);
|
||||||
await Task.Delay(500);
|
|
||||||
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.ResistanceZeroCoil, false);
|
|
||||||
StatusMessage = "电阻归零指令已发送";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
@@ -347,7 +447,7 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
await EnsureConnected();
|
await EnsureConnected();
|
||||||
bool current = await _plcService.ReadCoilAsync(_config.PlcRegisterAddresses.InletValveCoil);
|
bool current = await _plcService.ReadCoilAsync(_config.PlcRegisterAddresses.InletValveCoil);
|
||||||
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.InletValveCoil, !current);
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.InletValveCoil, !current);
|
||||||
StatusMessage = $"进气阀 {(current ? "关闭" : "开启")}";
|
StatusMessage = $"进气阀已{(current ? "关闭" : "开启")}";
|
||||||
}
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
@@ -356,16 +456,9 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
await EnsureConnected();
|
await EnsureConnected();
|
||||||
bool current = await _plcService.ReadCoilAsync(_config.PlcRegisterAddresses.OutletValveCoil);
|
bool current = await _plcService.ReadCoilAsync(_config.PlcRegisterAddresses.OutletValveCoil);
|
||||||
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.OutletValveCoil, !current);
|
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.OutletValveCoil, !current);
|
||||||
StatusMessage = $"排气阀 {(current ? "关闭" : "开启")}";
|
StatusMessage = $"排气阀已{(current ? "关闭" : "开启")}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task EnsureConnected()
|
|
||||||
{
|
|
||||||
if (!await _plcService.IsConnectedAsync())
|
|
||||||
await _plcService.ConnectAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 以下原有的 Confirm 命令保持不变,但可根据需要简化(因默认已勾选)
|
|
||||||
[RelayCommand] private void ConfirmBubbleRemoved() => BubbleRemoved = true;
|
[RelayCommand] private void ConfirmBubbleRemoved() => BubbleRemoved = true;
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private void ConfirmClean()
|
private void ConfirmClean()
|
||||||
@@ -387,56 +480,11 @@ public partial class D7896ViewModel : ObservableObject
|
|||||||
AmbientCalibrated = true;
|
AmbientCalibrated = true;
|
||||||
StatusMessage = $"环境温度校准完成:{AmbientTemperature:F1} °C";
|
StatusMessage = $"环境温度校准完成:{AmbientTemperature:F1} °C";
|
||||||
}
|
}
|
||||||
// ========== 新增命令:系统校准(章节A3) ==========
|
[RelayCommand] private async Task PerformSystemCalibrationAsync() { /* 系统校准逻辑 */ }
|
||||||
[RelayCommand]
|
|
||||||
private async Task PerformSystemCalibrationAsync()
|
private async Task EnsureConnected()
|
||||||
{
|
{
|
||||||
if (IsCalibrating)
|
if (!await _plcService.IsConnectedAsync())
|
||||||
{
|
await _plcService.ConnectAsync();
|
||||||
MessageBox.Show("校准正在进行中...", "提示");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = MessageBox.Show($"将使用参考液 [{SelectedReferenceLiquid}] 进行系统校准。\n请确保传感器已浸入参考液中,并已清除气泡。\n是否继续?", "系统校准", MessageBoxButton.YesNo);
|
|
||||||
if (result != MessageBoxResult.Yes) return;
|
|
||||||
|
|
||||||
IsCalibrating = true;
|
|
||||||
CalibrationStatus = "正在测量参考液...";
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// 执行一次测量
|
|
||||||
if (!await _plcService.IsConnectedAsync())
|
|
||||||
await _plcService.ConnectAsync();
|
|
||||||
|
|
||||||
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.StartCommand, true);
|
|
||||||
await Task.Delay(500);
|
|
||||||
await _plcService.WriteCoilAsync(_config.PlcRegisterAddresses.StartCommand, false);
|
|
||||||
await Task.Delay(2000);
|
|
||||||
|
|
||||||
float lambda = await _plcService.ReadFloatAsync(_config.PlcRegisterAddresses.ThermalConductivity);
|
|
||||||
MeasuredConductivity = lambda;
|
|
||||||
CalibrationErrorPercent = Math.Abs((lambda - ReferenceConductivity) / ReferenceConductivity * 100);
|
|
||||||
|
|
||||||
CalibrationStatus = $"测量值: {MeasuredConductivity:F4} W/m·K, 参考值: {ReferenceConductivity:F4} W/m·K, 误差: {CalibrationErrorPercent:F2}%";
|
|
||||||
|
|
||||||
if (CalibrationErrorPercent <= 2.0)
|
|
||||||
MessageBox.Show($"校准成功!误差 {CalibrationErrorPercent:F2}% 在允许范围内(≤2%)。", "校准结果");
|
|
||||||
else
|
|
||||||
MessageBox.Show($"校准警告:误差 {CalibrationErrorPercent:F2}% 超出2%限值,请检查传感器或参考液。", "校准结果", MessageBoxButton.OK, MessageBoxImage.Warning);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
CalibrationStatus = $"校准失败: {ex.Message}";
|
|
||||||
MessageBox.Show($"校准失败: {ex.Message}", "错误");
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
IsCalibrating = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,13 +144,25 @@
|
|||||||
<!-- 2. 核心参数仪表盘(温度、电压、电阻、压力) -->
|
<!-- 2. 核心参数仪表盘(温度、电压、电阻、压力) -->
|
||||||
<Border Grid.Row="1" Background="White" CornerRadius="6" Padding="10" Margin="0,5" Effect="{StaticResource CardShadow}">
|
<Border Grid.Row="1" Background="White" CornerRadius="6" Padding="10" Margin="0,5" Effect="{StaticResource CardShadow}">
|
||||||
<WrapPanel>
|
<WrapPanel>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 核心参数仪表盘 - 更新绑定属性 -->
|
||||||
<Border Background="#E8F0FE" Padding="6" CornerRadius="4" Margin="0,0,15,0">
|
<Border Background="#E8F0FE" Padding="6" CornerRadius="4" Margin="0,0,15,0">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<TextBlock Text="🌡️ 样品温度:" FontWeight="SemiBold" Margin="0,0,5,0"/>
|
<TextBlock Text="🌡️ 样品温度:" FontWeight="SemiBold" Margin="0,0,5,0"/>
|
||||||
<TextBox Text="{Binding TestTemperature, StringFormat=F2}" Width="60" IsReadOnly="True"/>
|
<TextBox Text="{Binding CurrentTestTemperature, StringFormat=F2}" Width="60" IsReadOnly="True"/>
|
||||||
<TextBlock Text="℃" Margin="3,0,0,0"/>
|
<TextBlock Text="℃" Margin="3,0,0,0"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
<Border Background="#E8F0FE" Padding="6" CornerRadius="4" Margin="0,0,15,0">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Text="⏲️ 压力:" FontWeight="SemiBold" Margin="0,0,5,0"/>
|
||||||
|
<TextBox Text="{Binding ChamberPressure, StringFormat=F2}" Width="60" IsReadOnly="True"/>
|
||||||
|
<TextBlock Text="kPa" Margin="3,0,0,0"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
<Border Background="#E8F0FE" Padding="6" CornerRadius="4" Margin="0,0,15,0">
|
<Border Background="#E8F0FE" Padding="6" CornerRadius="4" Margin="0,0,15,0">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Orientation="Horizontal">
|
||||||
<TextBlock Text="⚡ 铂丝电压:" FontWeight="SemiBold" Margin="0,0,5,0"/>
|
<TextBlock Text="⚡ 铂丝电压:" FontWeight="SemiBold" Margin="0,0,5,0"/>
|
||||||
@@ -165,13 +177,6 @@
|
|||||||
<TextBlock Text="Ω" Margin="3,0,0,0"/>
|
<TextBlock Text="Ω" Margin="3,0,0,0"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
<Border Background="#E8F0FE" Padding="6" CornerRadius="4" Margin="0,0,15,0">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<TextBlock Text="⏲️ 压力:" FontWeight="SemiBold" Margin="0,0,5,0"/>
|
|
||||||
<TextBox Text="{Binding ChamberPressure, StringFormat=F1}" Width="60" IsReadOnly="True"/>
|
|
||||||
<TextBlock Text="kPa" Margin="3,0,0,0"/>
|
|
||||||
</StackPanel>
|
|
||||||
</Border>
|
|
||||||
</WrapPanel>
|
</WrapPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
@@ -212,9 +217,9 @@
|
|||||||
|
|
||||||
<!-- 6. 平均值 + 操作按钮 -->
|
<!-- 6. 平均值 + 操作按钮 -->
|
||||||
<Border Grid.Row="5" Background="#E8F0FE" CornerRadius="6" Padding="10" Margin="0,5" Effect="{StaticResource CardShadow}">
|
<Border Grid.Row="5" Background="#E8F0FE" CornerRadius="6" Padding="10" Margin="0,5" Effect="{StaticResource CardShadow}">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<WrapPanel Margin="0,0,0,8">
|
<WrapPanel Margin="0,0,0,8">
|
||||||
<TextBlock Text="平均热导率:" Width="100" FontWeight="SemiBold"/>
|
<TextBlock Text="平均热导率:" Width="100" FontWeight="SemiBold"/>
|
||||||
@@ -235,9 +240,16 @@
|
|||||||
<Button Content="排气阀" Command="{Binding OutletValveControlCommand}" Width="80" Margin="5"/>
|
<Button Content="排气阀" Command="{Binding OutletValveControlCommand}" Width="80" Margin="5"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||||
|
|
||||||
<Button Content="▶ 开始测试" Command="{Binding StartTestCommand}" Width="130" Height="36" Margin="8"
|
<Button Content="▶ 开始测试" Command="{Binding StartTestCommand}" Width="130" Height="36" Margin="8"
|
||||||
IsEnabled="{Binding IsTesting, Converter={StaticResource InverseBooleanConverter}}"
|
IsEnabled="{Binding IsTesting, Converter={StaticResource InverseBooleanConverter}}"
|
||||||
Background="{StaticResource PrimaryButtonBrush}"/>
|
Background="{StaticResource PrimaryButtonBrush}"/>
|
||||||
|
|
||||||
|
<Button Content="▶ 停止测试" Command="{Binding StopTest}" Width="130" Height="36" Margin="8"
|
||||||
|
|
||||||
|
Background="{StaticResource PrimaryButtonBrush}"/>
|
||||||
|
|
||||||
|
|
||||||
<Button Content="⟳ 重置" Command="{Binding ResetCommand}" Width="100" Height="36" Margin="8"/>
|
<Button Content="⟳ 重置" Command="{Binding ResetCommand}" Width="100" Height="36" Margin="8"/>
|
||||||
<Button Content="📄 生成报告" Command="{Binding GenerateReportCommand}" Width="110" Height="36" Margin="8"/>
|
<Button Content="📄 生成报告" Command="{Binding GenerateReportCommand}" Width="110" Height="36" Margin="8"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"PlcConnection": {
|
"PlcConnection": {
|
||||||
"IpAddress": "127.0.0.1",
|
"IpAddress": "192.168.1.10",
|
||||||
"Port": 502,
|
"Port": 502,
|
||||||
"TimeoutMs": 5000,
|
"TimeoutMs": 5000,
|
||||||
"SlaveId": 1
|
"SlaveId": 1
|
||||||
@@ -14,8 +14,8 @@
|
|||||||
"ThermalConductivity": 40001,
|
"ThermalConductivity": 40001,
|
||||||
"ThermalDiffusivity": 40003,
|
"ThermalDiffusivity": 40003,
|
||||||
// 控制命令线圈(0x线圈)
|
// 控制命令线圈(0x线圈)
|
||||||
"StartCommand": 40010, // 启动测试(保持寄存器,非线圈,需特殊处理)
|
"StartCommand": 4, // 启动测试(保持寄存器,非线圈,需特殊处理)
|
||||||
"ResetCommand": 40011,
|
"ResetCommand": 4,
|
||||||
// 新增线圈地址(Modbus 0x 地址,注意与保持寄存器区分)
|
// 新增线圈地址(Modbus 0x 地址,注意与保持寄存器区分)
|
||||||
"PressureCalibrationCoil": 1300, // M1300 压力校准
|
"PressureCalibrationCoil": 1300, // M1300 压力校准
|
||||||
"ResistanceZeroCoil": 1301, // M1301 电阻归零
|
"ResistanceZeroCoil": 1301, // M1301 电阻归零
|
||||||
|
|||||||
Reference in New Issue
Block a user