104 lines
4.7 KiB
C#
104 lines
4.7 KiB
C#
using Microsoft.Extensions.Options;
|
||
using SSPCTester.Devices.Config;
|
||
using SSPCTester.Devices.Interfaces;
|
||
using SSPCTester.Logic.Models;
|
||
|
||
namespace SSPCTester.Logic.Testing;
|
||
|
||
/// <summary>功率损耗:采集输入/输出两端数据并计算损耗与效率。</summary>
|
||
public sealed class PowerTestLegacy : ITestModule
|
||
{
|
||
private readonly IDaq _daq;
|
||
private readonly DaqOptions _daqOptions;
|
||
|
||
public PowerTestLegacy(IDaq daq, IOptions<DeviceOptions> options)
|
||
{
|
||
_daq = daq;
|
||
_daqOptions = options.Value.Daq;
|
||
}
|
||
|
||
public string Name => "功率损耗";
|
||
|
||
/// <summary>每路采集次数。</summary>
|
||
public int SamplesPerChannel { get; set; } = 5;
|
||
|
||
/// <summary>采样间隔(ms)。</summary>
|
||
public int IntervalMs { get; set; } = 100;
|
||
|
||
public async Task RunAsync(TestContext ctx, IProgress<TestProgress> progress, CancellationToken ct)
|
||
{
|
||
// 输入端电压由高速采集卡读取,输出端电压/电流由 Modbus 继电器端读取。
|
||
int daqVoltageChannel = ResolveDaqVoltageChannel(_daqOptions);
|
||
if (!_daq.IsConnected) await _daq.ConnectAsync(ct).ConfigureAwait(false);
|
||
if (!ctx.Sspc.IsConnected) await ctx.Sspc.ConnectAsync(ct).ConfigureAwait(false);
|
||
|
||
int n = ctx.Sspc.ChannelCount;
|
||
ctx.Project.PowerResults.Clear();
|
||
|
||
for (int ch = 1; ch <= n; ch++)
|
||
{
|
||
ct.ThrowIfCancellationRequested();
|
||
var row = new PowerLossRow { Channel = ch, Status = TestStatus.Running };
|
||
ctx.Project.PowerResults.Add(row);
|
||
progress.Report(new TestProgress { ModuleName = Name, Step = ch - 1, TotalSteps = n, Message = $"采集 CH{ch} 输入/输出两端数据" });
|
||
|
||
try
|
||
{
|
||
double sumVin = 0, sumVout = 0, sumI = 0;
|
||
for (int s = 0; s < SamplesPerChannel; s++)
|
||
{
|
||
// 输出端:Modbus 继电器端电压 + 通流电流(SSPC 为串联开关,Iin = Iout)。
|
||
var measurement = await ctx.Sspc.ReadMeasurementAsync(ch, ct).ConfigureAwait(false);
|
||
// 输入端:高速采集卡电压。
|
||
var daqValues = await _daq.ReadInstantAsync(new[] { daqVoltageChannel }, ct).ConfigureAwait(false);
|
||
double vin = daqValues.Length > 0 ? daqValues[0] : double.NaN;
|
||
double vout = measurement.Voltage;
|
||
double current = Math.Abs(measurement.Current);
|
||
if (!double.IsFinite(vin) || !double.IsFinite(vout) || !double.IsFinite(current))
|
||
throw new InvalidOperationException("功率损耗采样无效:请检查采集卡电压通道标定与 Modbus 连接。");
|
||
|
||
sumVin += vin;
|
||
sumVout += vout;
|
||
sumI += current;
|
||
await Task.Delay(IntervalMs, ct).ConfigureAwait(false);
|
||
}
|
||
|
||
row.Vin = sumVin / SamplesPerChannel;
|
||
row.Vout = sumVout / SamplesPerChannel;
|
||
row.Iin = sumI / SamplesPerChannel;
|
||
row.Iout = sumI / SamplesPerChannel;
|
||
row.Status = TestStatus.Measured;
|
||
}
|
||
catch
|
||
{
|
||
row.Status = TestStatus.Fail;
|
||
throw;
|
||
}
|
||
progress.Report(new TestProgress { ModuleName = Name, Step = ch, TotalSteps = n, StepStatus = row.Status, Message = $"CH{ch} 损耗={row.PowerLossW:F3}W 效率={row.EfficiencyPct:F3}%" });
|
||
}
|
||
}
|
||
|
||
/// <summary>解析用于输入端电压的高速采集卡通道(取已标定的电压通道,优先 OutputVoltage)。</summary>
|
||
internal static int ResolveDaqVoltageChannel(DaqOptions options)
|
||
{
|
||
if (options.Channels == null || options.Channels.Count == 0)
|
||
throw new InvalidOperationException("未配置采集卡通道,无法执行功率损耗测试。");
|
||
|
||
var candidates = options.Channels
|
||
.Where(x => x.PhysicalChannel >= 0 && x.PhysicalChannel < options.ChannelCount)
|
||
.Where(x => x.IsCalibrated)
|
||
.Where(x => IsVoltageRole(x.Role))
|
||
.ToArray();
|
||
|
||
var pick = candidates.FirstOrDefault(x => string.Equals(x.Role, nameof(DaqChannelRole.OutputVoltage), StringComparison.OrdinalIgnoreCase))
|
||
?? candidates.FirstOrDefault();
|
||
if (pick == null)
|
||
throw new InvalidOperationException("功率损耗测试需要一个已标定的采集卡电压通道(输入端电压),请在设置中配置并标定。");
|
||
return pick.PhysicalChannel;
|
||
}
|
||
|
||
private static bool IsVoltageRole(string? role) =>
|
||
Enum.TryParse<DaqChannelRole>(role, true, out var parsed)
|
||
&& parsed is DaqChannelRole.OutputVoltage or DaqChannelRole.InputVoltage;
|
||
}
|