using Common.Attributes; using DeviceCommand.Base; using Model.Models; using System; using System.Globalization; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; namespace DeviceCommand.Devices { /// /// 交流源 一拖三 (Chroma 61800系列) /// [ACPCommand] public class Chroma61800 : Tcp { // Chroma SCPI 默认使用 \n 作为结束符 private const string ScpiDelimiter = "\n"; public Chroma61800(TcpConfig config) : base(config) { } /// /// 从设备返回的 SCPI 响应字符串中提取数值部分并转换为 double。 /// 支持科学计数法(如 2.48E-03),结果保留两位小数。 /// /// 设备返回的原始字符串 /// 提取到的数值(保留两位小数),解析失败时返回 0 private static double ExtractDouble(string raw) { if (string.IsNullOrWhiteSpace(raw)) return 0; // 从响应中提取第一个数值(含正负号、小数点、科学计数法),可自动忽略单位后缀与命令头 var match = Regex.Match(raw, @"[+-]?(?:\d+\.?\d*|\.\d+)(?:[Ee][+-]?\d+)?"); return match.Success && double.TryParse(match.Value, NumberStyles.Float, CultureInfo.InvariantCulture, out double val) ? Math.Round(val, 2) : 0; } #region 1. 基础系统与公共指令 /// /// 清除错误队列 (*CLS) /// public virtual async Task 清除错误队列Async(CancellationToken ct = default) { await SendAsync($"*CLS{ScpiDelimiter}", ct); } /// /// 重设仪器为初始状态 (*RST) /// public virtual async Task 复位Async(CancellationToken ct = default) { await SendAsync($"*RST{ScpiDelimiter}", ct); } /// /// 查询仪器识别码 (*IDN?) /// public virtual async Task 查询设备信息Async(CancellationToken ct = default) { return await WriteReadAsync($"*IDN?{ScpiDelimiter}", ScpiDelimiter, ct); } #endregion #region 2. 基础输出与耦合控制 (OUTPut 子系统) /// /// 设置输出开关状态 (OUTP ON / OFF) /// /// true: 开启输出, false: 关闭输出 public virtual async Task 设置输出开关Async(bool isOn, CancellationToken ct = default) { string state = isOn ? "ON" : "OFF"; await SendAsync($"OUTP {state}{ScpiDelimiter}", ct); } /// /// 设置输出耦合模式 (OUTP:COUP AC | DC | ACDC) /// public virtual async Task 设置耦合模式Async(string couplingMode, CancellationToken ct = default) { // 有效参数: AC, DC, ACDC await SendAsync($"OUTP:COUP {couplingMode}{ScpiDelimiter}", ct); } /// /// 设置输出继电器状态 (OUTP:REL ON | OFF) /// public virtual async Task 设置输出继电器Async(bool isOn, CancellationToken ct = default) { string state = isOn ? "ON" : "OFF"; await SendAsync($"OUTP:REL {state}{ScpiDelimiter}", ct); } #endregion #region 3. 电源核心参数设置 (SOURCE 子系统) /// /// 设置交流电压 (VOLT:AC) /// /// 电压值 (0 ~ 300V 或高压选配范围) public virtual async Task 设置交流电压Async(double voltage, CancellationToken ct = default) { string valStr = voltage.ToString("0.###", CultureInfo.InvariantCulture); await SendAsync($"VOLT:AC {valStr}{ScpiDelimiter}", ct); } /// /// 设置直流电压 (VOLT:DC) /// public virtual async Task 设置直流电压Async(double voltage, CancellationToken ct = default) { string valStr = voltage.ToString("0.###", CultureInfo.InvariantCulture); await SendAsync($"VOLT:DC {valStr}{ScpiDelimiter}", ct); } /// /// 设置输出频率 (FREQ) /// /// 频率值 (Hz) public virtual async Task 设置频率Async(double frequency, CancellationToken ct = default) { string valStr = frequency.ToString("0.###", CultureInfo.InvariantCulture); await SendAsync($"FREQ {valStr}{ScpiDelimiter}", ct); } /// /// 设置波形选择 (FUNC:SHAP:A SINE / SQUA / CSIN 等) /// public virtual async Task 设置波形Async(string shape, CancellationToken ct = default) { await SendAsync($"FUNC:SHAP:A {shape}{ScpiDelimiter}", ct); } #endregion #region 4. 相位与多相模式控制 (INST & PHASE 子系统) /// /// 设置单/三相工作模式 (INST:PHAS THREE / SINGLE) /// /// true: 三相模式, false: 单相模式 public virtual async Task 设置单三相模式Async(bool isThreePhase, CancellationToken ct = default) { string mode = isThreePhase ? "THREE" : "SINGLE"; await SendAsync($"INST:PHAS {mode}{ScpiDelimiter}", ct); } /// /// 设置三相模式下的相互关系 (PHASE:THREE INDEPEND / SAMEFREQ / BALANCE) /// public virtual async Task 设置三相关系Async(string relation, CancellationToken ct = default) { // 有效参数: INDEPEND, SAMEFREQ, BALANCE await SendAsync($"PHASE:THREE {relation}{ScpiDelimiter}", ct); } /// /// 设置输出开启相位角 (PHASE:ON) /// public virtual async Task 设置开机角度Async(double degree, CancellationToken ct = default) { string valStr = degree.ToString("0.###", CultureInfo.InvariantCulture); await SendAsync($"PHASE:ON {valStr}{ScpiDelimiter}", ct); } /// /// 设置输出关闭相位角 (PHASE:OFF) /// public virtual async Task 设置关机角度Async(double degree, CancellationToken ct = default) { string valStr = degree.ToString("0.###", CultureInfo.InvariantCulture); await SendAsync($"PHASE:OFF {valStr}{ScpiDelimiter}", ct); } #endregion #region 5. 参数测量查询 (MEASure 子系统) /// /// 查询交流电压均方根值 (MEAS:VOLT:AC?) /// /// 取消令牌 /// 交流电压均方根值 (单位: V,保留两位小数) public virtual async Task 读取交流电压Async(CancellationToken ct = default) { string resp = await WriteReadAsync($"MEAS:VOLT:AC?{ScpiDelimiter}", ScpiDelimiter, ct); return ExtractDouble(resp); } /// /// 查询交流电流均方根值 (MEAS:CURR:AC?) /// /// 取消令牌 /// 交流电流均方根值 (单位: A,保留两位小数) public virtual async Task 读取交流电流Async(CancellationToken ct = default) { string resp = await WriteReadAsync($"MEAS:CURR:AC?{ScpiDelimiter}", ScpiDelimiter, ct); return ExtractDouble(resp); } /// /// 查询输出频率 (MEAS:FREQ?) /// /// 取消令牌 /// 输出频率值 (单位: Hz,保留两位小数) public virtual async Task 读取频率Async(CancellationToken ct = default) { string resp = await WriteReadAsync($"MEAS:FREQ?{ScpiDelimiter}", ScpiDelimiter, ct); return ExtractDouble(resp); } /// /// 查询真实输出功率 (MEAS:POW:AC?) /// /// 取消令牌 /// 真实输出功率值 (单位: W,保留两位小数) public virtual async Task 读取真实功率Async(CancellationToken ct = default) { string resp = await WriteReadAsync($"MEAS:POW:AC?{ScpiDelimiter}", ScpiDelimiter, ct); return ExtractDouble(resp); } #endregion #region 6. LIST 模式子系统 (LIST 子系统) /// /// 设定列表功能的模态 (SOUR:LIST:COUP) /// /// 耦合模态: ALL | NONE public virtual async Task 设置列表耦合模态Async(string coupling, CancellationToken ct = default) { await SendAsync($"SOUR:LIST:COUP {coupling}{ScpiDelimiter}", ct); } /// /// 设定列表功能的触发形态 (SOUR:LIST:TRIG) /// /// 触发形态: AUTO | MANUAL | EXCITE public virtual async Task 设置列表触发形态Async(string triggerMode, CancellationToken ct = default) { await SendAsync($"SOUR:LIST:TRIG {triggerMode}{ScpiDelimiter}", ct); } /// /// 查询列表功能的有效序列数 (SOUR:LIST:POIN?) /// /// 取消令牌 /// 有效序列数 (0 ~ 100) public virtual async Task 查询列表有效序列数Async(CancellationToken ct = default) { string resp = await WriteReadAsync($"SOUR:LIST:POIN?{ScpiDelimiter}", ScpiDelimiter, ct); return int.TryParse(resp.Trim(), out int val) ? val : 0; } /// /// 设定列表执行完成前的执行次数 (SOUR:LIST:COUN) /// /// 执行次数 (0 ~ 65535) public virtual async Task 设置列表执行次数Async(int count, CancellationToken ct = default) { await SendAsync($"SOUR:LIST:COUN {count}{ScpiDelimiter}", ct); } /// /// 设定列表点的静止时间顺序 (SOUR:LIST:DWEL) /// /// 静止时间序列 (单位: ms,每个值 0 ~ 99999999.9) public virtual async Task 设置列表静止时间顺序Async(double[] dwellTimes, CancellationToken ct = default) { string valStr = string.Join(",", Array.ConvertAll(dwellTimes, v => v.ToString("0.#", CultureInfo.InvariantCulture))); await SendAsync($"SOUR:LIST:DWEL {valStr}{ScpiDelimiter}", ct); } /// /// 设定波形缓冲区列表点数的顺序 (SOUR:LIST:SHAP) /// /// 波形缓冲区顺序,每个元素为 A 或 B public virtual async Task 设置列表波形顺序Async(string[] shapes, CancellationToken ct = default) { string valStr = string.Join(",", shapes); await SendAsync($"SOUR:LIST:SHAP {valStr}{ScpiDelimiter}", ct); } /// /// 设定列表的时间基础 (SOUR:LIST:BASE) /// /// 时间基础: TIME | CYCLE public virtual async Task 设置列表时间基础Async(string timeBase, CancellationToken ct = default) { await SendAsync($"SOUR:LIST:BASE {timeBase}{ScpiDelimiter}", ct); } /// /// 设定 AC 起始电压列表点数的顺序 (SOUR:LIST:VOLT:AC:STAR) /// /// AC 起始电压序列 (单位: V,每个值 0.0 ~ 300.0) public virtual async Task 设置列表AC起始电压顺序Async(double[] voltages, CancellationToken ct = default) { string valStr = string.Join(",", Array.ConvertAll(voltages, v => v.ToString("0.###", CultureInfo.InvariantCulture))); await SendAsync($"SOUR:LIST:VOLT:AC:STAR {valStr}{ScpiDelimiter}", ct); } /// /// 设定 AC 结束电压列表点数的顺序 (SOUR:LIST:VOLT:AC:END) /// /// AC 结束电压序列 (单位: V,每个值 0.0 ~ 300.0) public virtual async Task 设置列表AC结束电压顺序Async(double[] voltages, CancellationToken ct = default) { string valStr = string.Join(",", Array.ConvertAll(voltages, v => v.ToString("0.###", CultureInfo.InvariantCulture))); await SendAsync($"SOUR:LIST:VOLT:AC:END {valStr}{ScpiDelimiter}", ct); } /// /// 设定 DC 起始电压列表点数的顺序 (SOUR:LIST:VOLT:DC:STAR) /// /// DC 起始电压序列 (单位: V,每个值 -424.2 ~ 414.2) public virtual async Task 设置列表DC起始电压顺序Async(double[] voltages, CancellationToken ct = default) { string valStr = string.Join(",", Array.ConvertAll(voltages, v => v.ToString("0.###", CultureInfo.InvariantCulture))); await SendAsync($"SOUR:LIST:VOLT:DC:STAR {valStr}{ScpiDelimiter}", ct); } /// /// 设定 DC 结束电压列表点数的顺序 (SOUR:LIST:VOLT:DC:END) /// /// DC 结束电压序列 (单位: V,每个值 -424.2 ~ 414.2) public virtual async Task 设置列表DC结束电压顺序Async(double[] voltages, CancellationToken ct = default) { string valStr = string.Join(",", Array.ConvertAll(voltages, v => v.ToString("0.###", CultureInfo.InvariantCulture))); await SendAsync($"SOUR:LIST:VOLT:DC:END {valStr}{ScpiDelimiter}", ct); } /// /// 设定起始频率列表点数的顺序 (SOUR:LIST:FREQ:STAR) /// /// 起始频率序列 (单位: Hz,每个值 15.00 ~ 100.00) public virtual async Task 设置列表起始频率顺序Async(double[] frequencies, CancellationToken ct = default) { string valStr = string.Join(",", Array.ConvertAll(frequencies, v => v.ToString("0.##", CultureInfo.InvariantCulture))); await SendAsync($"SOUR:LIST:FREQ:STAR {valStr}{ScpiDelimiter}", ct); } /// /// 设定结束频率列表点数的顺序 (SOUR:LIST:FREQ:END) /// /// 结束频率序列 (单位: Hz,每个值 15.00 ~ 100.00) public virtual async Task 设置列表结束频率顺序Async(double[] frequencies, CancellationToken ct = default) { string valStr = string.Join(",", Array.ConvertAll(frequencies, v => v.ToString("0.##", CultureInfo.InvariantCulture))); await SendAsync($"SOUR:LIST:FREQ:END {valStr}{ScpiDelimiter}", ct); } /// /// 设定相位角度列表点数的顺序 (SOUR:LIST:DEGR) /// /// 相位角度序列 (单位: °,每个值 0.0 ~ 359.9) public virtual async Task 设置列表相位角度顺序Async(double[] degrees, CancellationToken ct = default) { string valStr = string.Join(",", Array.ConvertAll(degrees, v => v.ToString("0.#", CultureInfo.InvariantCulture))); await SendAsync($"SOUR:LIST:DEGR {valStr}{ScpiDelimiter}", ct); } /// /// 设定操作模态 (OUTP:MODE) /// /// 操作模态: FIXED | LIST | PULSE | STEP | SYNTH | INTERHAR public virtual async Task 设置操作模态Async(string mode, CancellationToken ct = default) { await SendAsync($"OUTP:MODE {mode}{ScpiDelimiter}", ct); } /// /// 在 LIST 模态下设定执行状态 (TRIG) /// 需先通过 将 OUTP:MODE 设为 LIST /// /// true: 开始执行 LIST, false: 停止 LIST public virtual async Task 触发列表执行Async(bool isOn, CancellationToken ct = default) { string state = isOn ? "ON" : "OFF"; await SendAsync($"TRIG {state}{ScpiDelimiter}", ct); } #endregion } }