Initial check-in
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Import Project="$(SolutionDir)Program.props" />
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<OutputType>Library</OutputType>
|
||||
<AssemblyName>Raytheon.Instruments.PowerSupplies.Keysight67XX</AssemblyName>
|
||||
<RootNamespace>Raytheon.Instruments</RootNamespace>
|
||||
<Product>Keysight 67XX Series Power Supply</Product>
|
||||
<Description>Keysight 67XX Series Power Supply</Description>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||
<Company>Raytheon Technologies</Company>
|
||||
<Authors>TEEC</Authors>
|
||||
<Copyright>Copyright © Raytheon Technologies $(Year)</Copyright>
|
||||
|
||||
<!-- Dynamic Versioning (Suitable for Release) -->
|
||||
<!-- <Version>$(Version)$(Suffix)</Version> -->
|
||||
|
||||
<!-- Static Versioning (Suitable for Development) -->
|
||||
<Version>1.0.0</Version>
|
||||
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
<PackageReference Include="NLog" Version="5.0.0" />
|
||||
<PackageReference Include="Raytheon.Configuration" Version="2.6.1" />
|
||||
<PackageReference Include="Raytheon.Configuration.Contracts" Version="2.3.0" />
|
||||
|
||||
<!--
|
||||
<PackageReference Include="Raytheon.Instruments.PowerSupply.Contracts" Version="1.1.0" />
|
||||
<PackageReference Include="Raytheon.Instruments.PowerSupplies.Simulation" Version="1.0.0" />
|
||||
-->
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Interfaces\PowerSupply\PowerSupply.Contracts.csproj" />
|
||||
<ProjectReference Include="..\..\EthernetSockets\CommDeviceTcpClient\TcpClient.csproj" />
|
||||
<ProjectReference Include="..\PowerSupplySim\PowerSupplySim.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,117 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
// UNCLASSIFIED
|
||||
/*-------------------------------------------------------------------------
|
||||
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
|
||||
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
|
||||
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
|
||||
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
|
||||
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
|
||||
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
|
||||
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
|
||||
COMPANY.
|
||||
|
||||
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
|
||||
GOVERNMENT.
|
||||
|
||||
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Raytheon.Instruments.PowerSupplies
|
||||
{
|
||||
[ExportInstrumentFactory(ModelNumber = "PowerSupplyKeysightN67xxFactory")]
|
||||
public class KeysightN67xxPowerFactory : IInstrumentFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The supported interfaces
|
||||
/// </summary>
|
||||
private readonly List<Type> _supportedInterfaces = new List<Type>();
|
||||
private static ILogger _logger;
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private const string DefaultConfigPath = @"C:\ProgramData\Raytheon\InstrumentManagerService";
|
||||
private static string DefaultPath;
|
||||
|
||||
public KeysightN67xxPowerFactory(string defaultConfigPath = DefaultConfigPath)
|
||||
: this(null, defaultConfigPath)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// COECommDeviceInstrumentFactory injection constructor
|
||||
/// </summary>
|
||||
/// <param name="configManager"></param>
|
||||
/// <param name="simEngine"></param>
|
||||
/// <param name="logger"></param>
|
||||
[ImportingConstructor]
|
||||
public KeysightN67xxPowerFactory([Import(AllowDefault = false)] IConfigurationManager configManager,
|
||||
[Import(AllowDefault = true)] string defaultConfigPath = null)
|
||||
{
|
||||
DefaultPath = defaultConfigPath;
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
if (NLog.LogManager.Configuration == null)
|
||||
{
|
||||
var assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
NLog.LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(assemblyFolder + "\\nlog.config");
|
||||
}
|
||||
|
||||
_configurationManager = configManager ?? GetConfigurationManager();
|
||||
_supportedInterfaces.Add(typeof(PowerSupply));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public IInstrument GetInstrument(string name)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the instrument
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public object GetInstrument(string name, bool simulateHw)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (simulateHw)
|
||||
return new PowerSupplySim(name, _configurationManager, _logger);
|
||||
else
|
||||
return new KeysightN67xxPowerSupply(name, _configurationManager, _logger);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, $"Unable to construct {name} instrument instance");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets supported interfaces
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ICollection<Type> GetSupportedInterfaces()
|
||||
{
|
||||
return _supportedInterfaces.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns confiuration based on the predefined path or default path c:/ProgramData/Raytheon/InstrumentManagerService
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IConfigurationManager GetConfigurationManager()
|
||||
{
|
||||
return string.IsNullOrEmpty(DefaultPath) ? new RaytheonConfigurationManager() : new RaytheonConfigurationManager(DefaultPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,663 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
// UNCLASSIFIED
|
||||
/*-------------------------------------------------------------------------
|
||||
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
|
||||
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
|
||||
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
|
||||
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
|
||||
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
|
||||
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
|
||||
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
|
||||
COMPANY.
|
||||
|
||||
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
|
||||
GOVERNMENT.
|
||||
|
||||
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Raytheon.Instruments.PowerSupplies
|
||||
{
|
||||
/// <summary>
|
||||
/// Class to simulate any power supply module
|
||||
/// </summary>
|
||||
class KeysightN67xxPowerModule : PowerSupplyModule
|
||||
{
|
||||
private List<string> _groupedModules;
|
||||
private List<string> _coupledModules;
|
||||
private string _powerSupplySystemName;
|
||||
private EthernetSockets.TcpClient _tcpClient;
|
||||
IConfigurationFile _config;
|
||||
|
||||
private ILogger _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public KeysightN67xxPowerModule(string iniFilePath, string powerSupplySystemName)
|
||||
{
|
||||
_logger = LogManager.GetCurrentClassLogger();
|
||||
_powerSupplySystemName = powerSupplySystemName;
|
||||
|
||||
_config = new ConfigurationFile(iniFilePath);
|
||||
|
||||
string ipAddress = _config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.ETHERNET_ADDRESS.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue);
|
||||
int port = 0;
|
||||
Int32.TryParse(_config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.ETHERNET_PORT.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out port);
|
||||
string moduleDef = _config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.MODULE_DEFINITION.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue);
|
||||
string coupledModules = _config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.COUPLED_MODULES.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue);
|
||||
string groupedModules = _config.ReadValue(PowerSupplyConfigIni.GENERAL.ToString(), PowerSupplyConfigIni.GROUPED_MODULES.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue);
|
||||
|
||||
List<string> powerModules = moduleDef.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||
_coupledModules = coupledModules.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||
_groupedModules = groupedModules.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||
|
||||
_tcpClient = new EthernetSockets.TcpClient(ipAddress, port);
|
||||
_tcpClient.Initialize();
|
||||
_tcpClient.Connect();
|
||||
|
||||
ResetPowerSupplySystem();
|
||||
|
||||
bool systemRebooted = false;
|
||||
if (_groupedModules.Count() > 1)
|
||||
GroupModules(_groupedModules, out systemRebooted);
|
||||
else if (_coupledModules.Count() > 1)
|
||||
CoupleModules(_coupledModules);
|
||||
|
||||
if (systemRebooted)
|
||||
{
|
||||
_tcpClient.Disconnect();
|
||||
_tcpClient.Connect();
|
||||
}
|
||||
|
||||
if (_groupedModules.Count() > 1)
|
||||
{
|
||||
powerModules.Clear();
|
||||
// since modules are grouped, we pick the first module as the representative module
|
||||
powerModules.Add(_groupedModules[0]);
|
||||
}
|
||||
|
||||
// build the power module map
|
||||
string moduleIndex = "";
|
||||
double ovp = 0.0;
|
||||
double ocp = 0.0;
|
||||
double voltageSetPoint = 0.0;
|
||||
double voltageSlewRate = -1.0;
|
||||
|
||||
double minVoltage = 0.0;
|
||||
double maxVoltage = 0.0;
|
||||
double minCurrent = 0.0;
|
||||
double maxCurrent = 0.0;
|
||||
|
||||
for (int i = 0; i < powerModules.Count(); i++)
|
||||
{
|
||||
string moduleName = powerModules[i];
|
||||
|
||||
moduleIndex = _config.ReadValue(moduleName, PowerSupplyConfigIni.INDEX.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue);
|
||||
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.OCP.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out ocp);
|
||||
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.OVP.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out ovp);
|
||||
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.VOLTAGE_SETPOINT.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out voltageSetPoint);
|
||||
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.VOLTAGE_SLEW_RATE.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out voltageSlewRate);
|
||||
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.MIN_VOLTAGE.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out minVoltage);
|
||||
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.MAX_VOLTAGE.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out maxVoltage);
|
||||
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.MIN_CURRENT.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out minCurrent);
|
||||
Double.TryParse(_config.ReadValue(moduleName, PowerSupplyConfigIni.MAX_CURRENT.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue), out maxCurrent);
|
||||
|
||||
PowerModuleInfoDict[moduleName] = new Raytheon.Instruments.PowerSupplies.PowerSupplyModuleInfo(moduleIndex, ocp, ovp, voltageSetPoint, voltageSlewRate, minVoltage, maxVoltage, minCurrent, maxCurrent);
|
||||
|
||||
ActivePowerModule = moduleName;
|
||||
SetConstantVoltageMode();
|
||||
SetAndConfirmOvp();
|
||||
SetAndConfirmOcp();
|
||||
SetAndConfirmVoltageSetpoint();
|
||||
SetAndConfirmVoltageSlewRate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable or Disable Front Panel
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public override bool DisplayEnabled
|
||||
{
|
||||
set
|
||||
{
|
||||
SemObj?.Release();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable or disable Front Panel
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public override bool FrontPanelEnabled
|
||||
{
|
||||
get { SemObj?.Release(); throw new NotImplementedException(); }
|
||||
set
|
||||
{
|
||||
string command;
|
||||
|
||||
try
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
if (value)
|
||||
command = KeysightPowerSupplyScpiCommands.SET_FRONTPANEL_ENABLE_CMD + "\n";
|
||||
else
|
||||
command = KeysightPowerSupplyScpiCommands.SET_FRONTPANEL_DISABLE_CMD + "\n";
|
||||
|
||||
SendCommand(command);
|
||||
}
|
||||
}
|
||||
finally { SemObj?.Release(); }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Turn on power module's output
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public override void On()
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
CheckActivePowerModuleValidity();
|
||||
|
||||
string command = KeysightPowerSupplyScpiCommands.SET_OUTPUT_ENABLE_CMD + "," + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
SendCommand(command);
|
||||
}
|
||||
}
|
||||
finally { SemObj?.Release(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Turn off power module's output
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public override void Off()
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
CheckActivePowerModuleValidity();
|
||||
|
||||
string command = KeysightPowerSupplyScpiCommands.SET_OUTPUT_DISABLE_CMD + "," + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
SendCommand(command);
|
||||
}
|
||||
}
|
||||
finally { SemObj?.Release(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform self test
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
public override SelfTestResult PerformSelfTest()
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.SELFTEST_CMD + "\n";
|
||||
|
||||
string rsp = SendCommandAndGetResponse(command);
|
||||
|
||||
string[] stringVec = rsp.Split(',');
|
||||
|
||||
int status = -1;
|
||||
Int32.TryParse(stringVec[0], out status);
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
SelfTestResult = SelfTestResult.Fail;
|
||||
throw new Exception($"{_powerSupplySystemName}'s self-test failed with error code: {status}");
|
||||
}
|
||||
else
|
||||
SelfTestResult = SelfTestResult.Pass;
|
||||
}
|
||||
}
|
||||
finally { SemObj?.Release(); }
|
||||
|
||||
return SelfTestResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set constant voltage mode
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
private void SetConstantVoltageMode()
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.SET_CONSTANT_VOLTAGE_CMD + "," + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
SendCommand(command);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set and Confirm OVP
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
private void SetAndConfirmOvp()
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.SET_OVP_CMD + " " + PowerModuleInfoDict[ActivePowerModule].overVoltageProtection_ + "," + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
SendCommand(command);
|
||||
|
||||
command = KeysightPowerSupplyScpiCommands.READ_OVP_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
string rsp = SendCommandAndGetResponse(command);
|
||||
double ovp = 0.0;
|
||||
|
||||
Double.TryParse(rsp, out ovp);
|
||||
|
||||
if (ovp != PowerModuleInfoDict[ActivePowerModule].overVoltageProtection_)
|
||||
throw new Exception($"Unable to set OVP. Expected OVP: {PowerModuleInfoDict[ActivePowerModule].overVoltageProtection_}. Actual: {ovp}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set and Confirm OCP
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
private void SetAndConfirmOcp()
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.SET_OCP_CMD + " " + PowerModuleInfoDict[ActivePowerModule].overVoltageProtection_ + "," + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
SendCommand(command);
|
||||
|
||||
command = KeysightPowerSupplyScpiCommands.READ_OCP_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
string rsp = SendCommandAndGetResponse(command);
|
||||
double ocp = 0.0;
|
||||
|
||||
Double.TryParse(rsp, out ocp);
|
||||
|
||||
if (ocp != PowerModuleInfoDict[ActivePowerModule].overVoltageProtection_)
|
||||
throw new Exception($"Unable to set OCP. Expected OCP: {PowerModuleInfoDict[ActivePowerModule].overVoltageProtection_}. Actual: {ocp}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set and Confirm Voltage Setpoint
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
private void SetAndConfirmVoltageSetpoint()
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.SET_VOLTAGE_SETPOINT_CMD + " " + PowerModuleInfoDict[ActivePowerModule].voltageSetpoint_ + "," + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
SendCommand(command);
|
||||
|
||||
command = KeysightPowerSupplyScpiCommands.READ_VOLTAGE_SETPOINT_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
string rsp = SendCommandAndGetResponse(command);
|
||||
double voltage = 0.0;
|
||||
|
||||
Double.TryParse(rsp, out voltage);
|
||||
|
||||
if (voltage != PowerModuleInfoDict[ActivePowerModule].voltageSetpoint_)
|
||||
throw new Exception($"Unable to set Voltage Setpoint. Expected Voltage Setpoint: {PowerModuleInfoDict[ActivePowerModule].voltageSetpoint_}. Actual: {voltage}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set and Confirm Slew Rate
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
private void SetAndConfirmVoltageSlewRate()
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
if (PowerModuleInfoDict[ActivePowerModule].voltageSlewRate_ > 0.0)
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.SET_VOLTAGE_SLEW_RATE_CMD + " " + PowerModuleInfoDict[ActivePowerModule].voltageSlewRate_ + "," + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
SendCommand(command);
|
||||
|
||||
command = KeysightPowerSupplyScpiCommands.READ_VOLTAGE_SLEW_RATE_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
string rsp = SendCommandAndGetResponse(command);
|
||||
double voltageSlewRate = 0.0;
|
||||
|
||||
Double.TryParse(rsp, out voltageSlewRate);
|
||||
|
||||
if (voltageSlewRate != PowerModuleInfoDict[ActivePowerModule].voltageSlewRate_)
|
||||
throw new Exception($"Unable to set Voltage Slew Rate. Expected Voltage Slew Rate: {PowerModuleInfoDict[ActivePowerModule].voltageSlewRate_}. Actual: {voltageSlewRate}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get error code
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
protected override string GetErrorCode(out int errorCode)
|
||||
{
|
||||
errorCode = 0;
|
||||
string rtn = "";
|
||||
|
||||
lock (SyncObj)
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.READ_ERROR_CODE_CMD + "\n";
|
||||
|
||||
string rsp = SendCommandAndGetResponse(command);
|
||||
|
||||
string[] stringVec = rsp.Split(',');
|
||||
|
||||
Int32.TryParse(stringVec[0], out errorCode);
|
||||
|
||||
if (stringVec.Length > 1)
|
||||
{
|
||||
rtn = stringVec[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read voltage
|
||||
/// </summary>
|
||||
/// <param></param>
|
||||
/// <returns></returns>
|
||||
protected override double ReadVoltage()
|
||||
{
|
||||
double val = 0.0;
|
||||
|
||||
lock (SyncObj)
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.READ_VOLTAGE_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
string rsp = SendCommandAndGetResponse(command);
|
||||
|
||||
Double.TryParse(rsp, out val);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read current
|
||||
/// </summary>
|
||||
/// <param></param>
|
||||
/// <returns></returns>
|
||||
protected override double ReadCurrent()
|
||||
{
|
||||
double val = 0.0;
|
||||
|
||||
lock (SyncObj)
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.READ_CURRENT_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
string rsp = SendCommandAndGetResponse(command);
|
||||
|
||||
Double.TryParse(rsp, out val);
|
||||
}
|
||||
|
||||
return val;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read protection status
|
||||
/// </summary>
|
||||
/// <param></param>
|
||||
/// <returns></returns>
|
||||
protected override int ReadProtectionStatus()
|
||||
{
|
||||
int val = -1;
|
||||
|
||||
lock (SyncObj)
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.READ_PROTECTION_STATUS_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
string rsp = SendCommandAndGetResponse(command);
|
||||
|
||||
Int32.TryParse(rsp, out val);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine if module's output is on
|
||||
/// </summary>
|
||||
/// <param></param>
|
||||
/// <returns></returns>
|
||||
protected override bool IsOutputOn()
|
||||
{
|
||||
bool isOn = false;
|
||||
|
||||
lock (SyncObj)
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.READ_OUTPUT_STATUS_CMD + " " + PowerModuleInfoDict[ActivePowerModule].moduleNameFormat + "\n";
|
||||
|
||||
string rsp = SendCommandAndGetResponse(command);
|
||||
|
||||
int status = -1;
|
||||
|
||||
Int32.TryParse(rsp, out status);
|
||||
|
||||
if (status == 1)
|
||||
{
|
||||
isOn = true;
|
||||
}
|
||||
}
|
||||
|
||||
return isOn;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When modules are grouped, they act as one module
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
private void GroupModules(List<string> moduleList, out bool systemRebooted)
|
||||
{
|
||||
// 1. Group the channels
|
||||
string groupListToDefine = "(@";
|
||||
string groupListToQuery = "";
|
||||
string moduleNumber = "";
|
||||
|
||||
systemRebooted = false;
|
||||
|
||||
for (int i = 0; i < moduleList.Count; i++)
|
||||
{
|
||||
moduleNumber = _config.ReadValue(moduleList[i], PowerSupplyConfigIni.INDEX.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue);
|
||||
|
||||
groupListToDefine += moduleNumber;
|
||||
groupListToQuery += moduleNumber;
|
||||
|
||||
// add a ',' if this is not the final element in the list
|
||||
if (i < moduleList.Count() - 1)
|
||||
{
|
||||
groupListToDefine += ",";
|
||||
groupListToQuery += ",";
|
||||
}
|
||||
else
|
||||
{
|
||||
groupListToDefine += ")";
|
||||
}
|
||||
}
|
||||
|
||||
groupListToQuery = "\"" + groupListToQuery + "\"\n";
|
||||
|
||||
// see if channels are grouped
|
||||
string queryGroupCommand = KeysightPowerSupplyScpiCommands.QUERY_GROUP_CHANNELS + "\n";
|
||||
|
||||
for (int i = 1; i <= 2; i++)
|
||||
{
|
||||
string respStr = SendCommandAndGetResponse(queryGroupCommand);
|
||||
|
||||
// if modules are not grouped
|
||||
if (respStr != groupListToQuery)
|
||||
{
|
||||
groupListToDefine += "\n";
|
||||
|
||||
string groupCommand = KeysightPowerSupplyScpiCommands.SET_GROUP_DEFINE_CMD + " " + groupListToDefine;
|
||||
|
||||
SendCommand(groupCommand);
|
||||
}
|
||||
else if (i == 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
string command = KeysightPowerSupplyScpiCommands.REBOOT_CMD + "\n";
|
||||
// after grouping the modules, need to reboot system for it to take effect
|
||||
SendCommand(command);
|
||||
|
||||
// wait 20 seconds for reboot
|
||||
Thread.Sleep(20000);
|
||||
|
||||
systemRebooted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When modules are coupled, they turned on and off in unison
|
||||
/// i.e turn on/off one module, all other coupled modules will automatically turn on/off
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
private void CoupleModules(List<string> moduleList)
|
||||
{
|
||||
string coupleListToDefine = "";
|
||||
string moduleNumber = "";
|
||||
|
||||
for (int i = 0; i < moduleList.Count(); i++)
|
||||
{
|
||||
moduleNumber = _config.ReadValue(moduleList[i], PowerSupplyConfigIni.INDEX.ToString(), Raytheon.Common.GeneralConstants.DefaultConfigValue);
|
||||
|
||||
coupleListToDefine += moduleNumber;
|
||||
|
||||
// add a ',' if this is not the final element in the list
|
||||
if (i < moduleList.Count() - 1)
|
||||
{
|
||||
coupleListToDefine += ",";
|
||||
}
|
||||
}
|
||||
|
||||
coupleListToDefine += "\n";
|
||||
|
||||
// see if channels are grouped
|
||||
string queryCoupleChannelCommand = KeysightPowerSupplyScpiCommands.QUERY_COUPLE_CHANNELS + "\n";
|
||||
|
||||
for (int i = 1; i <= 2; i++)
|
||||
{
|
||||
string respStr = SendCommandAndGetResponse(queryCoupleChannelCommand);
|
||||
|
||||
string queryCoupleStateCommand = KeysightPowerSupplyScpiCommands.QUERY_COUPLE_STATE + "\n";
|
||||
string respStr2 = SendCommandAndGetResponse(queryCoupleStateCommand);
|
||||
|
||||
if (coupleListToDefine != respStr || respStr2 == "0\n")
|
||||
{
|
||||
// send command to couple modules
|
||||
string command = KeysightPowerSupplyScpiCommands.SET_COUPLE_CHANNELS_CMD + " " + coupleListToDefine;
|
||||
SendCommand(command);
|
||||
|
||||
// turn coupling on
|
||||
command = KeysightPowerSupplyScpiCommands.SET_COUPLE_ON_CMD + "\n";
|
||||
SendCommand(command);
|
||||
|
||||
// output protection on
|
||||
command = KeysightPowerSupplyScpiCommands.SET_COUPLE_OUTPUT_PROTECT_ON_CMD + "\n";
|
||||
SendCommand(command);
|
||||
}
|
||||
else if (i == 1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset Power Supply System
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
private void ResetPowerSupplySystem()
|
||||
{
|
||||
// send the command
|
||||
string command = KeysightPowerSupplyScpiCommands.RESET_CMD + "\n";
|
||||
SendCommand(command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send command
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
private void SendCommand(string command)
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
byte[] msg = Encoding.ASCII.GetBytes(command);
|
||||
|
||||
_tcpClient.Write(msg, (uint)msg.Length);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send command and get response
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
private string SendCommandAndGetResponse(string command)
|
||||
{
|
||||
lock (SyncObj)
|
||||
{
|
||||
byte[] readBuf = new byte[100];
|
||||
_tcpClient.SetReadTimeout(2000);
|
||||
|
||||
int bytesRec = 0;
|
||||
|
||||
SendCommand(command);
|
||||
|
||||
try
|
||||
{
|
||||
bytesRec = (int)_tcpClient.Read(ref readBuf);
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
throw new Exception("SocketException Error Code: " + ex.ErrorCode + $" ({((SocketError)ex.ErrorCode).ToString()})");
|
||||
}
|
||||
|
||||
return Encoding.ASCII.GetString(readBuf, 0, bytesRec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
// UNCLASSIFIED
|
||||
/*-------------------------------------------------------------------------
|
||||
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
|
||||
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
|
||||
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
|
||||
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
|
||||
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
|
||||
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
|
||||
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
|
||||
COMPANY.
|
||||
|
||||
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
|
||||
GOVERNMENT.
|
||||
|
||||
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
|
||||
using NLog;
|
||||
using Raytheon.Common;
|
||||
using Raytheon.Instruments.EthernetSockets;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Raytheon.Instruments.PowerSupplies
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for controlling a Keysightt N6700 Series Power Supply System
|
||||
/// </summary>
|
||||
public class KeysightN67xxPowerSupply : PowerSupply
|
||||
{
|
||||
private string _iniFilePath;
|
||||
|
||||
private static ILogger _logger;
|
||||
private readonly IConfigurationManager _configurationManager;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public KeysightN67xxPowerSupply(string deviceInstanceName, IConfigurationManager configurationManager, ILogger logger)
|
||||
{
|
||||
Name = deviceInstanceName;
|
||||
_logger = logger;
|
||||
_configurationManager = configurationManager;
|
||||
|
||||
// configuration obtained from [deviceInstanceName].xml file
|
||||
_configuration = _configurationManager.GetConfiguration(Name);
|
||||
|
||||
string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||
_iniFilePath = Path.Combine(assemblyFolder, _configuration.GetConfigurationValue(deviceInstanceName, PowerSupplyConfigXml.INI_FILE_PATH.ToString(), $".\\{Raytheon.Common.GeneralConstants.InstrumentConfigFolder}\\{deviceInstanceName}.ini"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform shutdown
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
public override void Shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform reset
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
public override void Reset()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear errors
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
public override bool ClearErrors()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implement Indexer in order to access a specific power module
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
public override PowerSupplyModule this[object powerDeviceId]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!(powerDeviceId == null || powerDeviceId.GetType().IsEnum))
|
||||
{
|
||||
throw new ArgumentException($"{nameof(powerDeviceId)} must be an enumerated type or null");
|
||||
}
|
||||
|
||||
_powerSupplyModule.GetSemphamore().WaitOne();
|
||||
|
||||
if (powerDeviceId != null)
|
||||
_powerSupplyModule.SetActivePowerModule(powerDeviceId.ToString());
|
||||
|
||||
return _powerSupplyModule;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Group or couple modules as specified in config file
|
||||
/// Gather information for each power module from config file
|
||||
/// </summary>
|
||||
/// <param name=""></param>
|
||||
/// <returns></returns>
|
||||
public override void Initialize()
|
||||
{
|
||||
_powerSupplyModule = new KeysightN67xxPowerModule(_iniFilePath, Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
// UNCLASSIFIED
|
||||
/*-------------------------------------------------------------------------
|
||||
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
|
||||
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
|
||||
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
|
||||
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
|
||||
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
|
||||
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
|
||||
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
|
||||
COMPANY.
|
||||
|
||||
THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
|
||||
GOVERNMENT.
|
||||
|
||||
UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
|
||||
-------------------------------------------------------------------------*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Raytheon.Instruments.PowerSupplies
|
||||
{
|
||||
public static class KeysightPowerSupplyScpiCommands
|
||||
{
|
||||
public static string CLEAR_CMD = "*CLS";
|
||||
public static string RESET_CMD = "*RST";
|
||||
public static string SELFTEST_CMD = "*TST?";
|
||||
public static string READ_ERROR_CODE_CMD = "SYST:ERR?";
|
||||
public static string REBOOT_CMD = "SYST:REB";
|
||||
|
||||
// panel disable/enable commands
|
||||
public static string SET_FRONTPANEL_DISABLE_CMD = "SYST:COMM:RLST RWL";
|
||||
public static string SET_FRONTPANEL_ENABLE_CMD = "SYST:COMM:RLST REM";
|
||||
|
||||
// watchdog commands
|
||||
public static string SET_WATCHDOGDELAY_CMD = "OUTP:PROT:WDOG:DEL";
|
||||
public static string SET_WATCHDOGON_CMD = "OUTP:PROT:WDOG ON";
|
||||
public static string SET_WATCHDOGOFF_CMD = "OUTP:PROT:WDOG OFF";
|
||||
|
||||
// coupling commands
|
||||
public static string SET_COUPLE_CHANNELS_CMD = "OUTP:COUP:CHAN";
|
||||
public static string SET_COUPLE_ON_CMD = "OUTP:COUP ON";
|
||||
public static string SET_COUPLE_OUTPUT_PROTECT_ON_CMD = "OUTP:PROT:COUP ON";
|
||||
public static string QUERY_COUPLE_CHANNELS = "OUTP:COUP:CHAN?";
|
||||
public static string QUERY_COUPLE_STATE = "OUTP:COUP?";
|
||||
|
||||
// Grouping Commands
|
||||
public static string SET_GROUP_DEFINE_CMD = "SYST:GRO:DEF";
|
||||
public static string UNGROUP_ALL_CHANNELS_CMD = "SYST:GRO:DEL:ALL";
|
||||
public static string QUERY_GROUP_CHANNELS = "SYST:GRO:CAT?";
|
||||
|
||||
// current commands
|
||||
public static string SET_OCP_CMD = "CURR:LEV";
|
||||
public static string SET_OCP_ON_CMD = "CURR:PROT:STAT ON";
|
||||
public static string READ_CURRENT_CMD = "MEAS:CURR?";
|
||||
public static string READ_OCP_CMD = "CURR:LEV?";
|
||||
|
||||
// voltage commands
|
||||
public static string SET_OVP_CMD = "VOLT:PROT";
|
||||
public static string SET_VOLTAGE_SLEW_RATE_CMD = "VOLT:SLEW";
|
||||
public static string SET_VOLTAGE_SETPOINT_CMD = "VOLT:LEV";
|
||||
public static string SET_CONSTANT_VOLTAGE_CMD = "STAT:OPER:ENAB 1";
|
||||
public static string READ_VOLTAGE_CMD = "MEAS:VOLT?";
|
||||
public static string READ_VOLTAGE_SETPOINT_CMD = "VOLT?";
|
||||
public static string READ_OVP_CMD = "VOLT:PROT?";
|
||||
public static string READ_VOLTAGE_SLEW_RATE_CMD = "VOLT:SLEW?";
|
||||
|
||||
// set output commands
|
||||
public static string SET_OUTPUT_DISABLE_CMD = "OUTP OFF";
|
||||
public static string SET_OUTPUT_ENABLE_CMD = "OUTP ON";
|
||||
|
||||
//query status
|
||||
public static string READ_OUTPUT_STATUS_CMD = "OUTP?";
|
||||
public static string READ_ERROR_STATUS_CMD = "SYST:ERR?";
|
||||
public static string READ_PROTECTION_STATUS_CMD = "STAT:QUES:COND?";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user