diff --git a/DeviceCommand/Devices/Chroma61800.cs b/DeviceCommand/Devices/Chroma61800.cs index e68cb7c..9583c7a 100644 --- a/DeviceCommand/Devices/Chroma61800.cs +++ b/DeviceCommand/Devices/Chroma61800.cs @@ -88,17 +88,7 @@ namespace DeviceCommand.Devices return await WriteReadAsync($"*IDN?{ScpiDelimiter}", ScpiDelimiter, ct); } - /// - /// 命令流延时 (*D) - /// 在 SCPI 命令流中插入一段延时(单位: ms),常用于 LIST 参数下发完成后、切换 OUTP:MODE 之前等待仪器就绪 - /// - /// 延时时长 (ms) - public virtual async Task 延时Async(double milliseconds, CancellationToken ct = default) - { - string valStr = milliseconds.ToString("0.###", CultureInfo.InvariantCulture); - await SendAsync($"*D {valStr}{ScpiDelimiter}", ct); - } - + /// /// 退出远程状态、回到本地 (SYST:LOC,即 SYSTem:LOCal) /// 设定后仪器回到 LOCAL 状态,前面板恢复可用。手册注明本命令僅可用於 RS-232 控制之下, diff --git a/PowerAdaptabilityModule/ViewModels/PowerAdaptabilityViewModel.cs b/PowerAdaptabilityModule/ViewModels/PowerAdaptabilityViewModel.cs index a97f9c0..61331ba 100644 --- a/PowerAdaptabilityModule/ViewModels/PowerAdaptabilityViewModel.cs +++ b/PowerAdaptabilityModule/ViewModels/PowerAdaptabilityViewModel.cs @@ -266,17 +266,47 @@ namespace PowerAdaptabilityModule.ViewModels /// 叠加直流电压 (SYNT:DC, -495.0 ~ 495.0 V) public double SynthDc { get => _synthDc; set => SetProperty(ref _synthDc, value); } - private double _synthStartPhase; - /// 起始相位角 (SYNT:SPH, 0.0 ~ 359.9 °) - public double SynthStartPhase { get => _synthStartPhase; set => SetProperty(ref _synthStartPhase, value); } + // —— SYNTHESIS 三相独立编辑:每相持有各自的起始相位/谐波振幅/谐波相位(索引 0=A/Φ1, 1=B/Φ2, 2=C/Φ3),INST:EDIT EACH 逐相下发 —— + private readonly double[] _synthStartPhases = new double[3]; + private readonly string[] _synthAmplitudeTexts = new string[3]; + private readonly string[] _synthPhaseTexts = new string[3]; - private string _synthAmplitudeText = ""; - /// 各次谐波振幅序列文本 (SYNT:AMPL, 英文逗号分隔, 最多 50 阶) - public string SynthAmplitudeText { get => _synthAmplitudeText; set => SetProperty(ref _synthAmplitudeText, value); } + private int _synthEditPhaseIndex; + /// 当前正在编辑的相位索引 (0=A, 1=B, 2=C),切换时下方起始相位/谐波文本框自动刷新为该相内容 + public int SynthEditPhaseIndex + { + get => _synthEditPhaseIndex; + set + { + if (SetProperty(ref _synthEditPhaseIndex, value)) + { + RaisePropertyChanged(nameof(SynthStartPhase)); + RaisePropertyChanged(nameof(SynthAmplitudeText)); + RaisePropertyChanged(nameof(SynthPhaseText)); + } + } + } - private string _synthPhaseText = ""; - /// 各次谐波相位角序列文本 (SYNT:PHAS, 英文逗号分隔, 0~359.9°) - public string SynthPhaseText { get => _synthPhaseText; set => SetProperty(ref _synthPhaseText, value); } + /// 起始相位角 (SYNT:SPH, 0.0 ~ 359.9 °),作用于当前编辑相位;复制到三相时按 ±120° 偏移 + public double SynthStartPhase + { + get => _synthStartPhases[_synthEditPhaseIndex]; + set { _synthStartPhases[_synthEditPhaseIndex] = value; RaisePropertyChanged(); } + } + + /// 各次谐波振幅序列文本 (SYNT:AMPL, 英文逗号分隔, 首值对应 2 次谐波,2~50 次共 49 个值),作用于当前编辑相位 + public string SynthAmplitudeText + { + get => _synthAmplitudeTexts[_synthEditPhaseIndex]; + set { _synthAmplitudeTexts[_synthEditPhaseIndex] = value; RaisePropertyChanged(); } + } + + /// 各次谐波相位角序列文本 (SYNT:PHAS, 英文逗号分隔, 0~359.9°),作用于当前编辑相位 + public string SynthPhaseText + { + get => _synthPhaseTexts[_synthEditPhaseIndex]; + set { _synthPhaseTexts[_synthEditPhaseIndex] = value; RaisePropertyChanged(); } + } #endregion #region SYNTHESIS 波形预设(文件:D:\acp\源测试\合成波形,一键载入/保存自定义谐波波形) @@ -410,6 +440,7 @@ namespace PowerAdaptabilityModule.ViewModels public ICommand DownloadSynthesisCommand { get; } public ICommand SynthStopCommand { get; } public ICommand ResetSynthHarmonicsCommand { get; } +public ICommand CopySynthPhaseToThreeCommand { get; } public ICommand LoadSynthPresetCommand { get; } public ICommand SaveSynthPresetCommand { get; } public ICommand SaveSynthPresetAsCommand { get; } @@ -588,7 +619,6 @@ namespace PowerAdaptabilityModule.ViewModels await 下发单相序列Async(_phaseConfigs[p]); // LIST:xxx 序列 } - await _dev.延时Async(StartDelayMs, Ct()); // *D 200(等待仪器就绪) await _dev.设置操作模态Async("LIST", Ct()); // OUTP:MODE LIST // 回读校验:确认 COUN 真的写入(当前相位上下文=相3);读回 0 而设>0 即未生效 @@ -601,7 +631,8 @@ namespace PowerAdaptabilityModule.ViewModels ListStopCommand = new DelegateCommand(async () => await Exec(async () => { await _dev!.触发列表执行Async(false, Ct()); Log("LIST 已停止执行(TRIG OFF)"); })); - // 下发 SYNTHESIS 自定义谐波波形并启动:手册要求进入 SYNTH 前先离开输出,参数下发后 OUTP:MODE SYNTH → TRIG ON + // 下发 SYNTHESIS 自定义谐波波形并启动(三相独立):INST:EDIT EACH + NSEL 逐相下发, + // 谐波内容三相相同(复制到三相生成),仅起始相位按 ±120° 对称;手册要求进入 SYNTH 前先离开输出 DownloadSynthesisCommand = new DelegateCommand(async () => await Exec(async () => { // 先强制 TRIG OFF 停止连续执行模态并等状态回 OFF,再改写参数(执行中改写会被仪器忽略) @@ -610,41 +641,70 @@ namespace PowerAdaptabilityModule.ViewModels await _dev!.清除错误队列Async(Ct()); // *CLS await _dev.设置输出开关Async(false, Ct()); // OUTP OFF(进入 SYNTH 前先离开输出) await _dev.设置操作模态Async("FIXED", Ct()); // OUTP:MODE FIXED(清模态) - await _dev.设置合成数据格式Async(SynthCompose, Ct()); // SYNT:COMP - await _dev.设置合成基频Async(SynthFrequency, Ct()); // SYNT:FREQ - await _dev.设置合成基波电压Async(SynthFundamental, Ct()); // SYNT:FUND - await _dev.设置合成直流电压Async(SynthDc, Ct()); // SYNT:DC - await _dev.设置合成起始相位Async(SynthStartPhase, Ct()); // SYNT:SPH + await _dev.设置单三相模式Async(true, Ct()); // INST:PHAS THREE + await _dev.设置编辑方式Async("EACH", Ct()); // INST:EDIT EACH(逐相独立编辑,缺此步无法分相) - var ampl = ParseDoubles(SynthAmplitudeText); - if (ampl.Length > 0) await _dev.设置合成谐波振幅Async(ampl, Ct()); // SYNT:AMPL - var phas = ParseDoubles(SynthPhaseText); - if (phas.Length > 0) await _dev.设置合成谐波相位Async(phas, Ct()); // SYNT:PHAS + for (int p = 0; p < 3; p++) + { + await _dev.选择相位Async(p + 1, Ct()); // INST:NSEL 1|2|3 + await _dev.设置合成数据格式Async(SynthCompose, Ct()); // SYNT:COMP(EACH 模式随相位上下文生效,逐相各发一次) + await _dev.设置合成基频Async(SynthFrequency, Ct()); // SYNT:FREQ + await _dev.设置合成基波电压Async(SynthFundamental, Ct()); // SYNT:FUND + await _dev.设置合成直流电压Async(SynthDc, Ct()); // SYNT:DC + await _dev.设置合成起始相位Async(_synthStartPhases[p], Ct()); // SYNT:SPH(分相参数,三相 ±120° 对称) + var ampl = ParseDoubles(_synthAmplitudeTexts[p]); + if (ampl.Length > 0) await _dev.设置合成谐波振幅Async(ampl, Ct()); // SYNT:AMPL + var phas = ParseDoubles(_synthPhaseTexts[p]); + if (phas.Length > 0) await _dev.设置合成谐波相位Async(phas, Ct()); // SYNT:PHAS + } - // 回读校验:用仪器自己的回答确认参数是否真的写入(设定与回读不符=被拒绝或落到别的槽位) + // 回读校验:逐相回读起始相位确认 ±120° 偏移真实写入(读回与界面不符=被拒绝) string compBack = await _dev.查询合成数据格式Async(Ct()); double fundBack = await _dev.查询合成基波电压Async(Ct()); + var sphBack = new List(); + for (int p = 0; p < 3; p++) + { + await _dev.选择相位Async(p + 1, Ct()); // INST:NSEL + double sph = await _dev.查询合成起始相位Async(Ct()); + sphBack.Add($"{ListPhaseOptions[p].Substring(0, 1)}={sph:0.#}°"); + } double[] amplBack = await _dev.查询合成谐波振幅Async(Ct()); - Log($"回读校验:COMP 设={SynthCompose} 读={compBack};FUND 设={SynthFundamental} 读={fundBack};AMPL 读前6阶={string.Join(",", amplBack.Take(6))}"); + Log($"回读校验:COMP 设={SynthCompose} 读={compBack};FUND 设={SynthFundamental} 读={fundBack};SPH {string.Join(" ", sphBack)};AMPL 回读{amplBack.Length}阶(仪器实际保留的阶数,当前上下文=C相),前6阶={string.Join(",", amplBack.Take(6))}"); - await _dev.延时Async(StartDelayMs, Ct()); // *D 200(等待仪器就绪) await _dev.设置操作模态Async("SYNTH", Ct()); // OUTP:MODE SYNTH await _dev.触发列表执行Async(true, Ct()); // TRIG ON double vrms = await _dev.读取交流电压Async(Ct()); // MEAS:VOLT:AC? 实测输出 - Log($"SYNTHESIS 波形已下发并启动(格式={SynthCompose} 基频={SynthFrequency}Hz 基波={SynthFundamental}V 谐波阶数={ampl.Length})实测Vrms={vrms}"); + Log($"SYNTHESIS 三相波形已下发并启动(格式={SynthCompose} 基频={SynthFrequency}Hz 基波={SynthFundamental}V 谐波阶数={ParseDoubles(_synthAmplitudeTexts[_synthEditPhaseIndex]).Length})实测Vrms={vrms}"); })); SynthStopCommand = new DelegateCommand(async () => await Exec(async () => { await _dev!.触发列表执行Async(false, Ct()); Log("SYNTHESIS 已停止执行(TRIG OFF)"); })); - // 重置谐波:把振幅/相位两个序列框填成 50 个 0(仅改界面文本,需再点「下发并启动 SYNTH」才写入仪器) + // 重置谐波:SYNT 数组首值对应 2 次谐波,仪器谐波范围 2~50 阶共 49 个值(填 50 个则末值落到不存在的 51 阶,可能被拒或截断) + // (仅改界面文本,需再点「下发并启动 SYNTH」才写入仪器) ResetSynthHarmonicsCommand = new DelegateCommand(() => { - string zeros = string.Join(",", Enumerable.Repeat("0", 50)); + string zeros = string.Join(",", Enumerable.Repeat("0", 49)); SynthAmplitudeText = zeros; SynthPhaseText = zeros; - Log("SYNTHESIS 谐波已重置:振幅/相位两框均填入 50 个 0;点「下发并启动 SYNTH」写入仪器"); + Log("SYNTHESIS 谐波已重置:振幅/相位两框均填入 49 个 0(覆盖 2~50 阶);点「下发并启动 SYNTH」写入仪器"); + }); + + // 复制当前相到三相:谐波内容相同,起始相位按 ±120° 偏移生成对称三相(与 LIST 复制同机制,仅改界面数据) + CopySynthPhaseToThreeCommand = new DelegateCommand(() => + { + int src = _synthEditPhaseIndex; + for (int p = 0; p < 3; p++) + { + if (p == src) continue; + _synthAmplitudeTexts[p] = _synthAmplitudeTexts[src]; + _synthPhaseTexts[p] = _synthPhaseTexts[src]; + double d = (_synthStartPhases[src] + (p - src) * 120.0) % 360.0; + if (d < 0) d += 360.0; + _synthStartPhases[p] = d; + } + Log($"已将 [{ListPhaseOptions[src]}] 的 SYNTHESIS 参数复制到三相(起始相位自动 ±120° 偏移,谐波内容相同);点「下发并启动 SYNTH」写入仪器"); }); // 合成波形的载入 / 保存 / 另存为 / 删除(与 LIST 测试项同机制,文件存于 D:\acp\源测试\合成波形) diff --git a/PowerAdaptabilityModule/Views/PowerAdaptabilityView.xaml b/PowerAdaptabilityModule/Views/PowerAdaptabilityView.xaml index 22d93cc..3f62cb1 100644 --- a/PowerAdaptabilityModule/Views/PowerAdaptabilityView.xaml +++ b/PowerAdaptabilityModule/Views/PowerAdaptabilityView.xaml @@ -394,10 +394,21 @@ Text="{Binding SynthDc, UpdateSourceTrigger=PropertyChanged}" /> + + + +