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 模式初始化 /// /// 初始化 LIST 模式的三相独立编辑环境 /// /// 循环次数,0代表无限循环 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 步阶参数配置 (独立发送版 - 三参数固定版) /// /// 切换目标相位并设置波形为正弦波 /// 建议在发送具体 LIST 参数前调用一次即可 /// /// 相位 (1: L1, 2: L2, 3: L3) public virtual async Task 切换相位Async(int phase, 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); } /// /// 配置 LIST 各步起始角度 /// public virtual async Task 配置List起始角度Async(double step1, double step2, double step3, CancellationToken ct = default) { string strValues = JoinParameters(step1, step2, step3); await SendAsync($"LIST:DEGR {strValues}{ScpiDelimiter}", ct); } /// /// 配置 LIST 各步交流起始电压 /// public virtual async Task 配置List交流起始电压Async(double step1, double step2, double step3, CancellationToken ct = default) { string strValues = JoinParameters(step1, step2, step3); await SendAsync($"LIST:VOLT:AC:STAR {strValues}{ScpiDelimiter}", ct); } /// /// 配置 LIST 各步交流结束电压 /// public virtual async Task 配置List交流结束电压Async(double step1, double step2, double step3, CancellationToken ct = default) { string strValues = JoinParameters(step1, step2, step3); await SendAsync($"LIST:VOLT:AC:END {strValues}{ScpiDelimiter}", ct); } /// /// 配置 LIST 各步直流起始电压 /// public virtual async Task 配置List直流起始电压Async(double step1, double step2, double step3, CancellationToken ct = default) { string strValues = JoinParameters(step1, step2, step3); await SendAsync($"LIST:VOLT:DC:STAR {strValues}{ScpiDelimiter}", ct); } /// /// 配置 LIST 各步直流结束电压 /// public virtual async Task 配置List直流结束电压Async(double step1, double step2, double step3, CancellationToken ct = default) { string strValues = JoinParameters(step1, step2, step3); await SendAsync($"LIST:VOLT:DC:END {strValues}{ScpiDelimiter}", ct); } /// /// 配置 LIST 各步起始频率 /// public virtual async Task 配置List起始频率Async(double step1, double step2, double step3, CancellationToken ct = default) { string strValues = JoinParameters(step1, step2, step3); await SendAsync($"LIST:FREQ:STAR {strValues}{ScpiDelimiter}", ct); } /// /// 配置 LIST 各步结束频率 /// public virtual async Task 配置List结束频率Async(double step1, double step2, double step3, CancellationToken ct = default) { string strValues = JoinParameters(step1, step2, step3); await SendAsync($"LIST:FREQ:END {strValues}{ScpiDelimiter}", ct); } /// /// 配置 LIST 各步执行时间 (单位: 毫秒) /// public virtual async Task 配置List执行时间Async(double step1, double step2, double step3, CancellationToken ct = default) { string strValues = JoinParameters(step1, step2, step3); await SendAsync($"LIST:DWEL {strValues}{ScpiDelimiter}", ct); } /// /// 辅助方法:将三个 double 值转换为逗号分隔的字符串,确保小数点格式正确 /// private string JoinParameters(double val1, double val2, double val3) { return $"{val1.ToString("0.###", CultureInfo.InvariantCulture)}," + $"{val2.ToString("0.###", CultureInfo.InvariantCulture)}," + $"{val3.ToString("0.###", CultureInfo.InvariantCulture)}"; } #endregion #region 4. LIST 触发与状态监控 /// /// 切换到 LIST 模式并触发输出 /// public virtual async Task 启动List输出(CancellationToken ct = default) { await SendAsync($"OUTP:MODE LIST{ScpiDelimiter}", ct); await SendAsync($"TRIG ON{ScpiDelimiter}", ct); } /// /// 查询 LIST 序列是否正在运行 /// public virtual async Task 查询List是否运行中(CancellationToken ct = default) { string state = await WriteReadAsync($"TRIG:STATE?{ScpiDelimiter}", ScpiDelimiter, ct); state = state?.Trim().ToUpper(); return state == "ON" || state == "1"; } /// /// 阻塞异步等待直到 LIST 序列执行完毕 (带安全超时保护) /// /// 最大等待超时时间(建议比实际LIST总时长多5-10秒) 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 } }