chroma61800设备添加

This commit is contained in:
“hsc”
2026-07-31 17:28:47 +08:00
parent e90dc805fc
commit ceae6e3421

View File

@@ -0,0 +1,166 @@
using Common.Attributes;
using DeviceCommand.Base;
using Model.Models;
using System;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace DeviceCommand.Devices
{
[ACPCommand]
public class Chroma61800 : Tcp
{
// Chroma SCPI 默认使用 \n 作为结束符
private const string ScpiDelimiter = "\n";
public Chroma61800(TcpConfig config) : base(config)
{
}
#region 1.
public virtual async Task (CancellationToken ct = default)
{
await SendAsync($"*CLS{ScpiDelimiter}", ct);
}
#endregion
#region 2. LIST
/// <summary>
/// 初始化 LIST 模式的三相独立编辑环境
/// </summary>
/// <param name="loopCount">循环次数0代表无限循环</param>
public virtual async Task List模式(int loopCount = 0, CancellationToken ct = default)
{
await SendAsync($"INST:PHAS THRE{ScpiDelimiter}", ct); // 选择三相模式
await SendAsync($"INST:EDIT EACH{ScpiDelimiter}", ct); // 选择编辑电压方式为分别编辑
await SendAsync($"LIST:COUN {loopCount}{ScpiDelimiter}", ct); // 循环次数设定
await SendAsync($"LIST:TRIG AUTO{ScpiDelimiter}", ct); // 设定触发方式
await SendAsync($"LIST:BASE TIME{ScpiDelimiter}", ct); // 选择执行时间类别
}
#endregion
#region 3. LIST
/// <summary>
/// 配置单相的 LIST 序列参数
/// 传入的数组长度必须保持一致,代表 LIST 的每个 StepSEQ
/// </summary>
/// <param name="phase">相位 (1: L1, 2: L2, 3: L3)</param>
/// <param name="degrees">各步起始角度 (如 [0, 0, 0])</param>
/// <param name="vacStart">各步交流起始电压 (如 [230, 11.5, 230])</param>
/// <param name="vacEnd">各步交流结束电压 (如 [230, 11.5, 230])</param>
/// <param name="vdcStart">各步直流起始电压</param>
/// <param name="vdcEnd">各步直流结束电压</param>
/// <param name="freqStart">各步起始频率</param>
/// <param name="freqEnd">各步结束频率</param>
/// <param name="dwellTimeMs">各步执行时间(单位: 毫秒)</param>
public virtual async Task List序列(
int phase,
double[] degrees,
double[] vacStart, double[] vacEnd,
double[] vdcStart, double[] vdcEnd,
double[] freqStart, double[] freqEnd,
double[] dwellTimeMs,
CancellationToken ct = default)
{
if (phase < 1 || phase > 3) throw new ArgumentOutOfRangeException(nameof(phase), "相位必须为 1, 2, 或 3");
// 选择相位并设置为正弦波
await SendAsync($"INST:NSEL {phase}{ScpiDelimiter}", ct);
await SendAsync($"FUNC:SHAP:A SINE{ScpiDelimiter}", ct);
// 转换数组为 SCPI 需要的逗号分隔字符串
string strDegrees = JoinParameters(degrees);
string strVacStart = JoinParameters(vacStart);
string strVacEnd = JoinParameters(vacEnd);
string strVdcStart = JoinParameters(vdcStart);
string strVdcEnd = JoinParameters(vdcEnd);
string strFreqStart = JoinParameters(freqStart);
string strFreqEnd = JoinParameters(freqEnd);
string strDwell = JoinParameters(dwellTimeMs);
// 下发序列参数
// 注意 Chroma 部分指令是 DEGR部分固件版本是 DEGRee这里统一使用简写 DEGR兼容性最好
await SendAsync($"LIST:DEGR {strDegrees}{ScpiDelimiter}", ct);
await SendAsync($"LIST:VOLT:AC:STAR {strVacStart}{ScpiDelimiter}", ct);
await SendAsync($"LIST:VOLT:AC:END {strVacEnd}{ScpiDelimiter}", ct);
await SendAsync($"LIST:VOLT:DC:STAR {strVdcStart}{ScpiDelimiter}", ct);
await SendAsync($"LIST:VOLT:DC:END {strVdcEnd}{ScpiDelimiter}", ct);
await SendAsync($"LIST:FREQ:STAR {strFreqStart}{ScpiDelimiter}", ct);
await SendAsync($"LIST:FREQ:END {strFreqEnd}{ScpiDelimiter}", ct);
await SendAsync($"LIST:DWEL {strDwell}{ScpiDelimiter}", ct);
}
/// <summary>
/// 辅助方法:将 double 数组转换为逗号分隔的字符串,确保小数点格式正确
/// </summary>
private string JoinParameters(double[] values)
{
return string.Join(",", values.Select(v => v.ToString("0.###", CultureInfo.InvariantCulture)));
}
#endregion
#region 4. LIST
/// <summary>
/// 切换到 LIST 模式并触发输出
/// </summary>
public virtual async Task List输出(CancellationToken ct = default)
{
await SendAsync($"OUTP:MODE LIST{ScpiDelimiter}", ct);
await SendAsync($"TRIG ON{ScpiDelimiter}", ct);
}
/// <summary>
/// 查询 LIST 序列是否正在运行
/// </summary>
public virtual async Task<bool> List是否运行中(CancellationToken ct = default)
{
string state = await WriteReadAsync($"TRIG:STATE?{ScpiDelimiter}", ScpiDelimiter, ct);
state = state?.Trim().ToUpper();
return state == "ON" || state == "1";
}
/// <summary>
/// 阻塞异步等待直到 LIST 序列执行完毕 (带安全超时保护)
/// </summary>
/// <param name="timeoutMs">最大等待超时时间建议比实际LIST总时长多5-10秒</param>
public virtual async Task List执行结束(int timeoutMs = 60000, CancellationToken ct = default)
{
// 给仪器留出响应触发的时间
await Task.Delay(500, ct);
Stopwatch sw = Stopwatch.StartNew();
bool isRunning = true;
while (isRunning)
{
ct.ThrowIfCancellationRequested();
if (sw.ElapsedMilliseconds > timeoutMs)
{
throw new TimeoutException($"等待 LIST 执行结束超时 ({timeoutMs} ms)。");
}
// 读取当前状态
isRunning = await List是否运行中(ct);
if (isRunning)
{
// 还在运行,适当休眠后继续轮询,避免总线阻塞
await Task.Delay(500, ct);
}
}
}
#endregion
}
}