命令树优化,测试编辑区域优化
This commit is contained in:
@@ -3,6 +3,7 @@ using DeviceCommand.Base;
|
||||
using Model.Models;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -45,33 +46,74 @@ namespace DeviceCommand.Devices
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 信号发生器 (DG1000Z 系列) 一拖三,支持波形输出与频率计测量
|
||||
/// </summary>
|
||||
[ACPCommand]
|
||||
public class DG1000Z : Tcp
|
||||
{
|
||||
// 使用换行符 \n (ASCII 0x0A) 作为 SCPI 结束符
|
||||
private const string ScpiDelimiter = "\n";
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数:传入 <see cref="TcpConfig"/> 一次性初始化信号发生器通信参数
|
||||
/// </summary>
|
||||
public DG1000Z(TcpConfig config) : base(config)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从设备返回的 SCPI 响应字符串中提取数值部分并转换为 double。
|
||||
/// 支持科学计数法(如 2.48E-03),结果保留两位小数。
|
||||
/// </summary>
|
||||
/// <param name="raw">设备返回的原始字符串</param>
|
||||
/// <returns>提取到的数值(保留两位小数),解析失败时返回 0</returns>
|
||||
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. IEEE 488.2 公共命令
|
||||
|
||||
/// <summary>
|
||||
/// 清除标准事件状态寄存器和错误队列 (*CLS)
|
||||
/// </summary>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
public virtual async Task 清除状态寄存器(CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync($"*CLS{ScpiDelimiter}", ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询设备识别信息 (*IDN? 指令)
|
||||
/// </summary>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
/// <returns>设备标识字符串 (制造商, 型号, 序列号, 固件版本)</returns>
|
||||
public virtual async Task<string> 查询设备标识(CancellationToken ct = default)
|
||||
{
|
||||
return await WriteReadAsync($"*IDN?{ScpiDelimiter}", ScpiDelimiter, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重设仪器为初始状态 (*RST)
|
||||
/// </summary>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
public virtual async Task 重置设备(CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync($"*RST{ScpiDelimiter}", ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询仪器支持的 SCPI 版本 (SYSTem:VERSion? 指令)
|
||||
/// </summary>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
/// <returns>SCPI 版本号字符串</returns>
|
||||
public virtual async Task<string> 查询系统SCPI版本(CancellationToken ct = default)
|
||||
{
|
||||
return await WriteReadAsync($":SYSTem:VERSion?{ScpiDelimiter}", ScpiDelimiter, ct);
|
||||
@@ -82,16 +124,23 @@ namespace DeviceCommand.Devices
|
||||
#region 2. 通道输出控制 (CH1 / CH2)
|
||||
|
||||
/// <summary>
|
||||
/// 打开或关闭指定通道的输出
|
||||
/// 打开或关闭指定通道的输出 (OUTPut 指令)
|
||||
/// </summary>
|
||||
/// <param name="通道号">通道 1 或 2,默认 1</param>
|
||||
/// <param name="开启">true为开启,false为关闭</param>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
public virtual async Task 设置通道输出状态(int 通道号 = 1, bool 开启 = true, CancellationToken ct = default)
|
||||
{
|
||||
string 参数 = 开启 ? "ON" : "OFF";
|
||||
await SendAsync($":OUTPut{通道号}:STATe {参数}{ScpiDelimiter}", ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询指定通道的输出开关状态 (OUTPut:STATe? 指令)
|
||||
/// </summary>
|
||||
/// <param name="通道号">通道 1 或 2,默认 1</param>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
/// <returns>通道输出状态字符串 (ON / OFF)</returns>
|
||||
public virtual async Task<string> 查询通道输出状态(int 通道号 = 1, CancellationToken ct = default)
|
||||
{
|
||||
return await WriteReadAsync($":OUTPut{通道号}:STATe?{ScpiDelimiter}", ScpiDelimiter, ct);
|
||||
@@ -104,51 +153,84 @@ namespace DeviceCommand.Devices
|
||||
/// <summary>
|
||||
/// 设置指定通道的波形类型 (如正弦波、方波等)
|
||||
/// </summary>
|
||||
/// <param name="通道号">通道 1 或 2,默认 1</param>
|
||||
/// <param name="波形">波形类型枚举,默认正弦波</param>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
public virtual async Task 设置波形类型(int 通道号 = 1, SignalWaveform 波形 = SignalWaveform.SINusoid, CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync($":SOURce{通道号}:FUNCtion:SHAPe {波形}{ScpiDelimiter}", ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置指定通道的输出频率 (单位: Hz)
|
||||
/// 设置指定通道的输出频率 (SOURce:FREQuency 指令)
|
||||
/// </summary>
|
||||
/// <param name="通道号">通道 1 或 2,默认 1</param>
|
||||
/// <param name="频率Hz">输出频率值 (单位: Hz),默认 1000</param>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
public virtual async Task 设置频率(int 通道号 = 1, double 频率Hz = 1000, CancellationToken ct = default)
|
||||
{
|
||||
string cmd = string.Format(CultureInfo.InvariantCulture, ":SOURce{0}:FREQuency {1:F2}{2}", 通道号, 频率Hz, ScpiDelimiter);
|
||||
await SendAsync(cmd, ct);
|
||||
}
|
||||
|
||||
public virtual async Task<string> 查询频率(int 通道号 = 1, CancellationToken ct = default)
|
||||
/// <summary>
|
||||
/// 查询指定通道的当前输出频率 (SOURce:FREQuency? 指令)
|
||||
/// </summary>
|
||||
/// <param name="通道号">通道 1 或 2,默认 1</param>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
/// <returns>输出频率值 (单位: Hz,保留两位小数)</returns>
|
||||
public virtual async Task<double> 查询频率(int 通道号 = 1, CancellationToken ct = default)
|
||||
{
|
||||
return await WriteReadAsync($":SOURce{通道号}:FREQuency?{ScpiDelimiter}", ScpiDelimiter, ct);
|
||||
string resp = await WriteReadAsync($":SOURce{通道号}:FREQuency?{ScpiDelimiter}", ScpiDelimiter, ct);
|
||||
return ExtractDouble(resp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置指定通道的输出幅度 (单位: Vpp,峰峰值)
|
||||
/// 设置指定通道的输出幅度 (SOURce:VOLTage:AMPLitude 指令)
|
||||
/// </summary>
|
||||
/// <param name="通道号">通道 1 或 2,默认 1</param>
|
||||
/// <param name="幅度Vpp">输出幅度 (单位: Vpp 峰峰值),默认 5</param>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
public virtual async Task 设置幅度(int 通道号 = 1, double 幅度Vpp = 5, CancellationToken ct = default)
|
||||
{
|
||||
string cmd = string.Format(CultureInfo.InvariantCulture, ":SOURce{0}:VOLTage:AMPLitude {1:F2}{2}", 通道号, 幅度Vpp, ScpiDelimiter);
|
||||
await SendAsync(cmd, ct);
|
||||
}
|
||||
|
||||
public virtual async Task<string> 查询幅度(int 通道号 = 1, CancellationToken ct = default)
|
||||
/// <summary>
|
||||
/// 查询指定通道的当前输出幅度 (SOURce:VOLTage:AMPLitude? 指令)
|
||||
/// </summary>
|
||||
/// <param name="通道号">通道 1 或 2,默认 1</param>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
/// <returns>输出幅度 (单位: Vpp,保留两位小数)</returns>
|
||||
public virtual async Task<double> 查询幅度(int 通道号 = 1, CancellationToken ct = default)
|
||||
{
|
||||
return await WriteReadAsync($":SOURce{通道号}:VOLTage:AMPLitude?{ScpiDelimiter}", ScpiDelimiter, ct);
|
||||
string resp = await WriteReadAsync($":SOURce{通道号}:VOLTage:AMPLitude?{ScpiDelimiter}", ScpiDelimiter, ct);
|
||||
return ExtractDouble(resp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置指定通道的直流偏移电压 (单位: Vdc)
|
||||
/// 设置指定通道的直流偏移电压 (SOURce:VOLTage:OFFSet 指令)
|
||||
/// </summary>
|
||||
/// <param name="通道号">通道 1 或 2,默认 1</param>
|
||||
/// <param name="偏移Vdc">直流偏移电压 (单位: Vdc),默认 0</param>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
public virtual async Task 设置偏移电压(int 通道号 = 1, double 偏移Vdc = 0, CancellationToken ct = default)
|
||||
{
|
||||
string cmd = string.Format(CultureInfo.InvariantCulture, ":SOURce{0}:VOLTage:OFFSet {1:F2}{2}", 通道号, 偏移Vdc, ScpiDelimiter);
|
||||
await SendAsync(cmd, ct);
|
||||
}
|
||||
|
||||
public virtual async Task<string> 查询偏移电压(int 通道号 = 1, CancellationToken ct = default)
|
||||
/// <summary>
|
||||
/// 查询指定通道的当前直流偏移电压 (SOURce:VOLTage:OFFSet? 指令)
|
||||
/// </summary>
|
||||
/// <param name="通道号">通道 1 或 2,默认 1</param>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
/// <returns>直流偏移电压 (单位: Vdc,保留两位小数)</returns>
|
||||
public virtual async Task<double> 查询偏移电压(int 通道号 = 1, CancellationToken ct = default)
|
||||
{
|
||||
return await WriteReadAsync($":SOURce{通道号}:VOLTage:OFFSet?{ScpiDelimiter}", ScpiDelimiter, ct);
|
||||
string resp = await WriteReadAsync($":SOURce{通道号}:VOLTage:OFFSet?{ScpiDelimiter}", ScpiDelimiter, ct);
|
||||
return ExtractDouble(resp);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -156,8 +238,11 @@ namespace DeviceCommand.Devices
|
||||
#region 4. 方波 / 脉冲波占空比设置 (重点用于CP信号模拟)
|
||||
|
||||
/// <summary>
|
||||
/// 设置方波信号的占空比 (0.01% ~ 99.99%)[cite: 1]
|
||||
/// 设置方波信号的占空比 (0.01% ~ 99.99%)
|
||||
/// </summary>
|
||||
/// <param name="通道号">通道 1 或 2,默认 1</param>
|
||||
/// <param name="占空比">方波占空比百分比,默认 50.0</param>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
public virtual async Task 设置方波占空比(int 通道号 = 1, double 占空比 = 50.0, CancellationToken ct = default)
|
||||
{
|
||||
string cmd = string.Format(CultureInfo.InvariantCulture, ":SOURce{0}:FUNCtion:SQUare:DCYCle {1:F2}{2}", 通道号, 占空比, ScpiDelimiter);
|
||||
@@ -165,9 +250,12 @@ namespace DeviceCommand.Devices
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置脉冲波信号的占空比 (0.01% ~ 99.99%)[cite: 1]
|
||||
/// 设置脉冲波信号的占空比 (0.01% ~ 99.99%)。
|
||||
/// 注意:使用此命令前必须先设置为 PULSe 波形类型
|
||||
/// </summary>
|
||||
/// <param name="通道号">通道 1 或 2,默认 1</param>
|
||||
/// <param name="占空比">脉冲波占空比百分比,默认 50.0</param>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
public virtual async Task 设置脉冲波占空比(int 通道号 = 1, double 占空比 = 50.0, CancellationToken ct = default)
|
||||
{
|
||||
string cmd = string.Format(CultureInfo.InvariantCulture, ":SOURce{0}:FUNCtion:PULSe:DCYCle {1:F2}{2}", 通道号, 占空比, ScpiDelimiter);
|
||||
@@ -179,47 +267,68 @@ namespace DeviceCommand.Devices
|
||||
#region 5. 频率计测量功能 (高频数据轮询核心)
|
||||
|
||||
/// <summary>
|
||||
/// 打开或关闭内置频率计功能
|
||||
/// 打开或关闭内置频率计功能 (COUNter:STATe 指令)
|
||||
/// </summary>
|
||||
/// <param name="开启">true: 开启频率计, false: 关闭频率计</param>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
public virtual async Task 设置频率计开关(bool 开启 = true, CancellationToken ct = default)
|
||||
{
|
||||
string 参数 = 开启 ? "ON" : "OFF";
|
||||
await SendAsync($":COUNter:STATe {参数}{ScpiDelimiter}", ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询内置频率计的开关状态 (COUNter:STATe? 指令)
|
||||
/// </summary>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
/// <returns>频率计开关状态字符串 (ON / OFF)</returns>
|
||||
public virtual async Task<string> 查询频率计开关状态(CancellationToken ct = default)
|
||||
{
|
||||
return await WriteReadAsync($":COUNter:STATe?{ScpiDelimiter}", ScpiDelimiter, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置频率计输入信号的耦合方式
|
||||
/// 设置频率计输入信号的耦合方式 (COUNter:COUPling 指令)
|
||||
/// </summary>
|
||||
/// <param name="耦合">耦合方式枚举 (AC 交流 / DC 直流),默认 AC</param>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
public virtual async Task 设置频率计耦合方式(CounterCoupling 耦合 = CounterCoupling.AC, CancellationToken ct = default)
|
||||
{
|
||||
await SendAsync($":COUNter:COUPling {耦合}{ScpiDelimiter}", ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置频率计的触发电平 (单位: V)
|
||||
/// 设置频率计的触发电平 (COUNter:LEVel 指令)
|
||||
/// </summary>
|
||||
/// <param name="电平V">触发电平值 (单位: V),默认 0.1</param>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
public virtual async Task 设置频率计触发电平(double 电平V = 0.1, CancellationToken ct = default)
|
||||
{
|
||||
string cmd = string.Format(CultureInfo.InvariantCulture, ":COUNter:LEVel {0:F2}{1}", 电平V, ScpiDelimiter);
|
||||
await SendAsync(cmd, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询频率计测量值 (COUNter:MEASure? 指令)。
|
||||
/// 响应格式为 "频率, 周期, 占空比, 正脉宽, 负脉宽",此方法提取第一项频率值
|
||||
/// </summary>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
/// <returns>频率计测得的频率值 (单位: Hz,保留两位小数)</returns>
|
||||
[Monitorable("信号发生器频率计测量值")]
|
||||
public virtual async Task<string> 查询频率计测量值(CancellationToken ct = default)
|
||||
public virtual async Task<double> 查询频率计测量值(CancellationToken ct = default)
|
||||
{
|
||||
// 返回格式: 频率, 周期, 占空比, 正脉宽, 负脉宽
|
||||
return await WriteReadAsync($":COUNter:MEASure?{ScpiDelimiter}", ScpiDelimiter, ct);
|
||||
string resp = await WriteReadAsync($":COUNter:MEASure?{ScpiDelimiter}", ScpiDelimiter, ct);
|
||||
return ExtractDouble(resp);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 6. 系统维护与远程控制扩展命令
|
||||
|
||||
/// <summary>
|
||||
/// 切换远程控制模式。信号发生器通过 LAN/USB 通信即自动进入远程模式
|
||||
/// </summary>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
public virtual async Task 切换远程控制模式(CancellationToken ct = default)
|
||||
{
|
||||
// 信号发生器通常通过 LAN/USB 和 VISA 通信即自动进入远程控制,
|
||||
@@ -227,12 +336,21 @@ namespace DeviceCommand.Devices
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 切换本地控制模式。通常通过前面板按键退出远程
|
||||
/// </summary>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
public virtual async Task 切换本地控制模式(CancellationToken ct = default)
|
||||
{
|
||||
// 通常通过前面板按键退出远程。不过可提供 SCPI 关闭屏幕保护等。
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询系统错误信息 (SYSTem:ERRor? 指令)
|
||||
/// </summary>
|
||||
/// <param name="ct">取消令牌</param>
|
||||
/// <returns>错误代码和描述信息</returns>
|
||||
public virtual async Task<string> 查询错误信息(CancellationToken ct = default)
|
||||
{
|
||||
return await WriteReadAsync($":SYSTem:ERRor?{ScpiDelimiter}", ScpiDelimiter, ct);
|
||||
@@ -240,4 +358,4 @@ namespace DeviceCommand.Devices
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user