PSW250Controller.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. using System;
  2. using APS7100TestTool.Models;
  3. using APS7100TestTool.Services;
  4. namespace APS7100TestTool.Controllers
  5. {
  6. /// <summary>
  7. /// PSW250-4.5 DC 可编程电源控制器
  8. /// </summary>
  9. public class PSW250Controller : IPowerSupplyController
  10. {
  11. private readonly ScpiDevice _device;
  12. public DeviceType DeviceType => DeviceType.PSW250;
  13. public DeviceInfo DeviceInfo => DeviceInfo.GetDeviceInfo(DeviceType.PSW250);
  14. public PSW250Controller(ScpiDevice device)
  15. {
  16. _device = device ?? throw new ArgumentNullException(nameof(device));
  17. }
  18. #region 基本操作
  19. /// <summary>
  20. /// 获取设备识别信息
  21. /// </summary>
  22. public string GetIdentification()
  23. {
  24. return _device.Query("*IDN?");
  25. }
  26. /// <summary>
  27. /// 重置设备
  28. /// </summary>
  29. public void Reset()
  30. {
  31. _device.SendCommand("*RST");
  32. System.Threading.Thread.Sleep(1000);
  33. }
  34. /// <summary>
  35. /// 清除状态
  36. /// </summary>
  37. public void ClearStatus()
  38. {
  39. _device.SendCommand("*CLS");
  40. }
  41. #endregion
  42. #region 输出控制
  43. /// <summary>
  44. /// 设置输出开关
  45. /// </summary>
  46. public void SetOutput(bool enable)
  47. {
  48. _device.SendCommand(enable ? "OUTP ON" : "OUTP OFF");
  49. }
  50. /// <summary>
  51. /// 获取输出状态
  52. /// </summary>
  53. public bool GetOutputState()
  54. {
  55. string result = _device.Query("OUTP?");
  56. return result.Trim() == "1" || result.ToUpper().Contains("ON");
  57. }
  58. #endregion
  59. #region 电压控制
  60. /// <summary>
  61. /// 设置输出电压 (V)
  62. /// </summary>
  63. public void SetVoltage(double voltage)
  64. {
  65. _device.SendCommand($"SOUR:VOLT {voltage}");
  66. }
  67. /// <summary>
  68. /// 获取电压设定值 (V)
  69. /// </summary>
  70. public double GetVoltage()
  71. {
  72. string result = _device.Query("SOUR:VOLT?");
  73. return double.Parse(result);
  74. }
  75. #endregion
  76. #region 电流控制
  77. /// <summary>
  78. /// 设置输出电流 (A)
  79. /// </summary>
  80. public void SetCurrent(double current)
  81. {
  82. _device.SendCommand($"SOUR:CURR {current}");
  83. }
  84. /// <summary>
  85. /// 获取电流设定值 (A)
  86. /// </summary>
  87. public double GetCurrent()
  88. {
  89. string result = _device.Query("SOUR:CURR?");
  90. return double.Parse(result);
  91. }
  92. #endregion
  93. #region 测量
  94. /// <summary>
  95. /// 测量实际输出电压 (V)
  96. /// </summary>
  97. public double MeasureVoltage()
  98. {
  99. string result = _device.Query("MEAS:VOLT?");
  100. return double.Parse(result);
  101. }
  102. /// <summary>
  103. /// 测量实际输出电流 (A)
  104. /// </summary>
  105. public double MeasureCurrent()
  106. {
  107. string result = _device.Query("MEAS:CURR?");
  108. return double.Parse(result);
  109. }
  110. /// <summary>
  111. /// 测量输出功率 (W)
  112. /// </summary>
  113. public double MeasurePower()
  114. {
  115. string result = _device.Query("MEAS:POW?");
  116. return double.Parse(result);
  117. }
  118. #endregion
  119. #region AC电源独有功能(PSW不支持)
  120. /// <summary>
  121. /// 设置频率 - DC电源不支持
  122. /// </summary>
  123. public void SetFrequency(double frequency)
  124. {
  125. throw new NotSupportedException("DC 电源不支持频率设置");
  126. }
  127. /// <summary>
  128. /// 获取频率 - DC电源不支持
  129. /// </summary>
  130. public double GetFrequency()
  131. {
  132. throw new NotSupportedException("DC 电源不支持频率设置");
  133. }
  134. /// <summary>
  135. /// 测量频率 - DC电源不支持
  136. /// </summary>
  137. public double MeasureFrequency()
  138. {
  139. throw new NotSupportedException("DC 电源不支持频率测量");
  140. }
  141. /// <summary>
  142. /// 测量功率因数 - DC电源不支持
  143. /// </summary>
  144. public double MeasurePowerFactor()
  145. {
  146. throw new NotSupportedException("DC 电源不支持功率因数测量");
  147. }
  148. /// <summary>
  149. /// 设置波形 - DC电源不支持
  150. /// </summary>
  151. public void SetWaveform(Waveform waveform)
  152. {
  153. throw new NotSupportedException("DC 电源不支持波形设置");
  154. }
  155. /// <summary>
  156. /// 获取波形 - DC电源不支持
  157. /// </summary>
  158. public Waveform GetWaveform()
  159. {
  160. throw new NotSupportedException("DC 电源不支持波形设置");
  161. }
  162. /// <summary>
  163. /// 设置电压量程 - DC电源不支持(或命令不同)
  164. /// </summary>
  165. public void SetVoltageRange(VoltageRange range)
  166. {
  167. throw new NotSupportedException("DC 电源不支持该命令");
  168. }
  169. /// <summary>
  170. /// 获取电压量程 - DC电源不支持
  171. /// </summary>
  172. public VoltageRange GetVoltageRange()
  173. {
  174. throw new NotSupportedException("DC 电源不支持该命令");
  175. }
  176. #endregion
  177. #region PSW250 独有功能
  178. /// <summary>
  179. /// 设置输出控制优先级模式
  180. /// 注意:这不是切换 CV/CC 状态,而是设置控制优先级和动态响应策略
  181. /// CV/CC 是运行结果,取决于负载,不是手动切换的
  182. /// </summary>
  183. public void SetOutputMode(PSWOutputMode mode)
  184. {
  185. string modeStr = mode switch
  186. {
  187. PSWOutputMode.CVHS => "CVHS", // 恒压优先(高速响应)
  188. PSWOutputMode.CCHS => "CCHS", // 恒流优先(高速响应)
  189. PSWOutputMode.CVLS => "CVLS", // 恒压优先(斜率/平滑变化)
  190. PSWOutputMode.CCLS => "CCLS", // 恒流优先(斜率/平滑变化)
  191. _ => "CVHS"
  192. };
  193. _device.SendCommand($"OUTP:MODE {modeStr}");
  194. }
  195. /// <summary>
  196. /// 获取输出控制优先级模式
  197. /// </summary>
  198. public PSWOutputMode GetOutputMode()
  199. {
  200. string result = _device.Query("OUTP:MODE?").Trim().ToUpper();
  201. // 处理数字返回值 (0-3) 或字符串返回值
  202. return result switch
  203. {
  204. "0" or "CVHS" => PSWOutputMode.CVHS,
  205. "1" or "CCHS" => PSWOutputMode.CCHS,
  206. "2" or "CVLS" => PSWOutputMode.CVLS,
  207. "3" or "CCLS" => PSWOutputMode.CCLS,
  208. _ => PSWOutputMode.CVHS
  209. };
  210. }
  211. /// <summary>
  212. /// 判断当前运行状态是否为 CC(恒流)模式
  213. /// 注意:CV/CC 是运行结果,取决于负载
  214. /// 通过比较实际电流和设定电流来判断
  215. /// </summary>
  216. public bool IsInCCMode()
  217. {
  218. try
  219. {
  220. double setCurrent = GetCurrent(); // 设定电流(限制值)
  221. double actualCurrent = MeasureCurrent(); // 实际电流
  222. // 如果实际电流 >= 设定电流的 98%,认为处于 CC 模式
  223. return setCurrent > 0.01 && actualCurrent >= setCurrent * 0.98;
  224. }
  225. catch
  226. {
  227. return false;
  228. }
  229. }
  230. // 保留旧方法以兼容(标记为过时)
  231. [Obsolete("请使用 SetOutputMode 和 GetOutputMode,CV/CC 是运行结果不是可切换模式")]
  232. public void SetMode(PSWMode mode) { }
  233. [Obsolete("请使用 IsInCCMode() 判断运行状态,或使用 GetOutputMode() 获取控制优先级")]
  234. public PSWMode GetMode() => PSWMode.ConstantVoltage;
  235. /// <summary>
  236. /// 设置过压保护值 (V)
  237. /// </summary>
  238. public void SetOVP(double voltage)
  239. {
  240. _device.SendCommand($"SOUR:VOLT:PROT {voltage}");
  241. }
  242. /// <summary>
  243. /// 获取过压保护值 (V)
  244. /// </summary>
  245. public double GetOVP()
  246. {
  247. string result = _device.Query("SOUR:VOLT:PROT?");
  248. return double.Parse(result);
  249. }
  250. /// <summary>
  251. /// 设置过流保护值 (A)
  252. /// </summary>
  253. public void SetOCP(double current)
  254. {
  255. _device.SendCommand($"SOUR:CURR:PROT {current}");
  256. }
  257. /// <summary>
  258. /// 获取过流保护值 (A)
  259. /// </summary>
  260. public double GetOCP()
  261. {
  262. string result = _device.Query("SOUR:CURR:PROT?");
  263. return double.Parse(result);
  264. }
  265. #endregion
  266. #region 远程控制模式
  267. /// <summary>
  268. /// 进入远程控制模式
  269. /// </summary>
  270. public void SetRemoteMode()
  271. {
  272. _device.SendCommand("SYST:REM");
  273. }
  274. /// <summary>
  275. /// 返回本地控制模式
  276. /// </summary>
  277. public void SetLocalMode()
  278. {
  279. _device.SendCommand("SYST:COMM:RLST LOCAL");
  280. }
  281. /// <summary>
  282. /// 锁定/解锁前面板按键 - PSW250 不支持此功能
  283. /// </summary>
  284. /// <remarks>
  285. /// PSW250 不支持面板锁定命令,此方法仅保持接口兼容
  286. /// </remarks>
  287. public void SetPanelLock(bool locked)
  288. {
  289. // PSW250 不支持 SYST:RWLOCK 命令,忽略此操作
  290. // 如需严格检查,可以抛出 NotSupportedException
  291. }
  292. /// <summary>
  293. /// 查询当前是否为远程模式
  294. /// </summary>
  295. public bool IsRemoteMode()
  296. {
  297. try
  298. {
  299. string result = _device.Query("SYST:REM?");
  300. return result.Trim() == "1" || result.ToUpper().Contains("ON") || result.ToUpper().Contains("REM");
  301. }
  302. catch
  303. {
  304. return true;
  305. }
  306. }
  307. #endregion
  308. #region 自定义命令
  309. /// <summary>
  310. /// 发送自定义 SCPI 命令
  311. /// </summary>
  312. public void SendCustomCommand(string command)
  313. {
  314. _device.SendCommand(command);
  315. }
  316. /// <summary>
  317. /// 发送自定义 SCPI 查询
  318. /// </summary>
  319. public string SendCustomQuery(string command)
  320. {
  321. return _device.Query(command);
  322. }
  323. #endregion
  324. }
  325. /// <summary>
  326. /// PSW250 工作模式(已废弃,保留兼容)
  327. /// </summary>
  328. [Obsolete("CV/CC 是运行结果,请使用 PSWOutputMode 设置控制优先级")]
  329. public enum PSWMode
  330. {
  331. ConstantVoltage, // 恒压模式
  332. ConstantCurrent // 恒流模式
  333. }
  334. /// <summary>
  335. /// PSW250 输出控制优先级模式
  336. /// 注意:这是控制优先级和动态响应策略,不是 CV/CC 运行状态
  337. /// </summary>
  338. public enum PSWOutputMode
  339. {
  340. /// <summary>恒压优先(高速响应)</summary>
  341. CVHS,
  342. /// <summary>恒流优先(高速响应)</summary>
  343. CCHS,
  344. /// <summary>恒压优先(斜率/平滑变化)</summary>
  345. CVLS,
  346. /// <summary>恒流优先(斜率/平滑变化)</summary>
  347. CCLS
  348. }
  349. }