From b38765789d9eb2bf8be562b9fd5726b4e22f6695 Mon Sep 17 00:00:00 2001 From: Duc Date: Sat, 4 Jan 2025 18:41:54 -0700 Subject: [PATCH] Monitor power supply data for fault conditions --- .../Keysight67XX/KeysightN67xxPowerModule.cs | 11 +- .../Keysight67XX/KeysightN67xxPowerSupply.cs | 12 +- .../PowerSupplySim/PowerSupplyModuleSim.cs | 15 +-- .../PowerSupplySim/PowerSupplySim.cs | 12 +- Source/Interfaces/PowerSupply/PowerSupply.cs | 10 ++ .../PowerSupply/PowerSupplyModule.cs | 4 +- .../PowerSupply/PowerSupplyModuleInfo.cs | 24 ++-- .../PowerModuleMeasurementManager.cs | 34 ++--- .../PowerSupplyMeasurementManager .cs | 15 ++- Source/Program/Program.cs | 14 +- .../Program/Threads/FailureMonitorThread.cs | 2 + .../Threads/PassthroughDataGuiUpdateThread.cs | 16 +++ .../Threads/PowerSupplyGuiUpdateThread.cs | 16 +++ .../Program/Threads/PowerSupplyReadThread.cs | 127 ++++++++++++++++-- 14 files changed, 242 insertions(+), 70 deletions(-) diff --git a/Source/Instruments/PowerSupplies/Keysight67XX/KeysightN67xxPowerModule.cs b/Source/Instruments/PowerSupplies/Keysight67XX/KeysightN67xxPowerModule.cs index 91a647e..752b47c 100644 --- a/Source/Instruments/PowerSupplies/Keysight67XX/KeysightN67xxPowerModule.cs +++ b/Source/Instruments/PowerSupplies/Keysight67XX/KeysightN67xxPowerModule.cs @@ -57,7 +57,7 @@ namespace Raytheon.Instruments.PowerSupplies 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 powerModules = moduleDef.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries).ToList(); + PowerModules = moduleDef.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries).ToList(); _coupledModules = coupledModules.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries).ToList(); _groupedModules = groupedModules.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries).ToList(); @@ -81,9 +81,9 @@ namespace Raytheon.Instruments.PowerSupplies if (_groupedModules.Count() > 1) { - powerModules.Clear(); + PowerModules.Clear(); // since modules are grouped, we pick the first module as the representative module - powerModules.Add(_groupedModules[0]); + PowerModules.Add(_groupedModules[0]); } // build the power module map @@ -98,9 +98,9 @@ namespace Raytheon.Instruments.PowerSupplies double minCurrent = 0.0; double maxCurrent = 0.0; - for (int i = 0; i < powerModules.Count(); i++) + for (int i = 0; i < PowerModules.Count(); i++) { - string moduleName = powerModules[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); @@ -143,7 +143,6 @@ namespace Raytheon.Instruments.PowerSupplies /// public override bool FrontPanelEnabled { - get { SemObj?.Release(); throw new NotImplementedException(); } set { string command; diff --git a/Source/Instruments/PowerSupplies/Keysight67XX/KeysightN67xxPowerSupply.cs b/Source/Instruments/PowerSupplies/Keysight67XX/KeysightN67xxPowerSupply.cs index bb39909..7a4b607 100644 --- a/Source/Instruments/PowerSupplies/Keysight67XX/KeysightN67xxPowerSupply.cs +++ b/Source/Instruments/PowerSupplies/Keysight67XX/KeysightN67xxPowerSupply.cs @@ -97,15 +97,21 @@ namespace Raytheon.Instruments.PowerSupplies { get { - if (!(powerDeviceId == null || powerDeviceId.GetType().IsEnum)) + string powerDeviceName = String.Empty; + + if (powerDeviceId != null && (powerDeviceId.GetType().IsEnum || powerDeviceId is string)) { - throw new ArgumentException($"{nameof(powerDeviceId)} must be an enumerated type or null"); + powerDeviceName = powerDeviceId.ToString(); + } + else if (powerDeviceId != null) + { + throw new ArgumentException($"{nameof(powerDeviceId)} must be null or enumerated or string type"); } _powerSupplyModule.GetSemphamore().WaitOne(); if (powerDeviceId != null) - _powerSupplyModule.SetActivePowerModule(powerDeviceId.ToString()); + _powerSupplyModule.SetActivePowerModule(powerDeviceName); return _powerSupplyModule; } diff --git a/Source/Instruments/PowerSupplies/PowerSupplySim/PowerSupplyModuleSim.cs b/Source/Instruments/PowerSupplies/PowerSupplySim/PowerSupplyModuleSim.cs index 61e9a33..595ea3f 100644 --- a/Source/Instruments/PowerSupplies/PowerSupplySim/PowerSupplyModuleSim.cs +++ b/Source/Instruments/PowerSupplies/PowerSupplySim/PowerSupplyModuleSim.cs @@ -51,15 +51,15 @@ namespace Raytheon.Instruments.PowerSupplies 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 powerModules = moduleDef.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries).ToList(); + PowerModules = moduleDef.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries).ToList(); _coupledModules = coupledModules.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries).ToList(); _groupedModules = groupedModules.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries).ToList(); if (_groupedModules.Count() > 1) { - powerModules.Clear(); + PowerModules.Clear(); // since modules are grouped, we pick the first module as the representative module - powerModules.Add(_groupedModules[0]); + PowerModules.Add(_groupedModules[0]); } // build the power module map @@ -74,9 +74,9 @@ namespace Raytheon.Instruments.PowerSupplies double minCurrent = 0.0; double maxCurrent = 0.0; - for (int i = 0; i < powerModules.Count(); i++) + for (int i = 0; i < PowerModules.Count(); i++) { - string moduleName = powerModules[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); @@ -109,8 +109,7 @@ namespace Raytheon.Instruments.PowerSupplies /// public override bool FrontPanelEnabled { - get { SemObj?.Release(); throw new NotImplementedException(); } - set { _frontPanelEnabled = value; SemObj?.Release(); } + set {_frontPanelEnabled = value; SemObj?.Release(); } } /// @@ -216,7 +215,7 @@ namespace Raytheon.Instruments.PowerSupplies lock (SyncObj) { if (PowerModuleInfoDict[ActivePowerModule].isOn_) - val = (PowerModuleInfoDict[ActivePowerModule].lowerCurrentLimit_ + PowerModuleInfoDict[ActivePowerModule].upperCurrentLimit_) / 2.0; + val = (PowerModuleInfoDict[ActivePowerModule].currentLowerLimit_ + PowerModuleInfoDict[ActivePowerModule].currentUpperLimit_) / 2.0; } return val; diff --git a/Source/Instruments/PowerSupplies/PowerSupplySim/PowerSupplySim.cs b/Source/Instruments/PowerSupplies/PowerSupplySim/PowerSupplySim.cs index cccd885..5504d21 100644 --- a/Source/Instruments/PowerSupplies/PowerSupplySim/PowerSupplySim.cs +++ b/Source/Instruments/PowerSupplies/PowerSupplySim/PowerSupplySim.cs @@ -102,15 +102,21 @@ namespace Raytheon.Instruments.PowerSupplies { get { - if (!(powerDeviceId == null || powerDeviceId.GetType().IsEnum)) + string powerDeviceName = String.Empty; + + if (powerDeviceId != null && (powerDeviceId.GetType().IsEnum || powerDeviceId is string)) { - throw new ArgumentException($"{nameof(powerDeviceId)} must be an enumerated type or null"); + powerDeviceName = powerDeviceId.ToString(); + } + else if (powerDeviceId != null) + { + throw new ArgumentException($"{nameof(powerDeviceId)} must be null or enumerated or string type"); } _powerSupplyModule.GetSemphamore().WaitOne(); if (powerDeviceId != null) - _powerSupplyModule.SetActivePowerModule(powerDeviceId.ToString()); + _powerSupplyModule.SetActivePowerModule(powerDeviceName); return _powerSupplyModule; } diff --git a/Source/Interfaces/PowerSupply/PowerSupply.cs b/Source/Interfaces/PowerSupply/PowerSupply.cs index d197945..960964b 100644 --- a/Source/Interfaces/PowerSupply/PowerSupply.cs +++ b/Source/Interfaces/PowerSupply/PowerSupply.cs @@ -49,5 +49,15 @@ namespace Raytheon.Instruments { return _powerSupplyModule.PowerModuleInfoDict; } + + /// + /// Get power supply module names + /// + /// + /// + public List GetPowerSupplyModuleNames() + { + return _powerSupplyModule.PowerModules; + } } } diff --git a/Source/Interfaces/PowerSupply/PowerSupplyModule.cs b/Source/Interfaces/PowerSupply/PowerSupplyModule.cs index 71a8ef1..178fbd8 100644 --- a/Source/Interfaces/PowerSupply/PowerSupplyModule.cs +++ b/Source/Interfaces/PowerSupply/PowerSupplyModule.cs @@ -34,6 +34,8 @@ namespace Raytheon.Instruments protected Semaphore SemObj = new System.Threading.Semaphore(initialCount: 1, maximumCount: 1); protected object SyncObj = new object(); protected string ActivePowerModule; + + public List PowerModules { get; protected set; } public Dictionary PowerModuleInfoDict { get; protected set; } @@ -63,7 +65,7 @@ namespace Raytheon.Instruments /// public virtual bool FrontPanelEnabled { - get; + private get; set; } diff --git a/Source/Interfaces/PowerSupply/PowerSupplyModuleInfo.cs b/Source/Interfaces/PowerSupply/PowerSupplyModuleInfo.cs index 492a90e..443722f 100644 --- a/Source/Interfaces/PowerSupply/PowerSupplyModuleInfo.cs +++ b/Source/Interfaces/PowerSupply/PowerSupplyModuleInfo.cs @@ -31,10 +31,10 @@ namespace Raytheon.Instruments.PowerSupplies overVoltageProtection_ = -1.0; voltageSetpoint_ = -1.0; voltageSlewRate_ = -1.0; - lowerVoltageLimit_ = -1.0; - upperVoltageLimit_ = -1.0; - lowerCurrentLimit_ = -1.0; - upperCurrentLimit_ = -1.0; + voltageLowerLimit_ = -1.0; + voltageUpperLimit_ = -1.0; + currentLowerLimit_ = -1.0; + currentUpperLimit_ = -1.0; isOn_ = false; faultStatus = -1; } @@ -45,10 +45,10 @@ namespace Raytheon.Instruments.PowerSupplies overVoltageProtection_ = overVoltageProtection; voltageSetpoint_ = voltageSetpoint; voltageSlewRate_ = voltageSlewRate; - lowerVoltageLimit_ = minVoltage; - upperVoltageLimit_ = maxVoltage; - lowerCurrentLimit_ = minCurrent; - upperCurrentLimit_ = maxCurrent; + voltageLowerLimit_ = minVoltage; + voltageUpperLimit_ = maxVoltage; + currentLowerLimit_ = minCurrent; + currentUpperLimit_ = maxCurrent; isOn_ = false; faultStatus = -1; @@ -58,10 +58,10 @@ namespace Raytheon.Instruments.PowerSupplies public string moduleNameFormat; public double overCurrentProtection_; public double overVoltageProtection_; - public double lowerVoltageLimit_; - public double upperVoltageLimit_; - public double lowerCurrentLimit_; - public double upperCurrentLimit_; + public double voltageLowerLimit_; + public double voltageUpperLimit_; + public double currentLowerLimit_; + public double currentUpperLimit_; public double voltageSetpoint_; public double voltageSlewRate_; public bool isOn_; diff --git a/Source/MeasurementManagers/PowerSupplyMeasurementManager/PowerModuleMeasurementManager.cs b/Source/MeasurementManagers/PowerSupplyMeasurementManager/PowerModuleMeasurementManager.cs index 0583c29..1636769 100644 --- a/Source/MeasurementManagers/PowerSupplyMeasurementManager/PowerModuleMeasurementManager.cs +++ b/Source/MeasurementManagers/PowerSupplyMeasurementManager/PowerModuleMeasurementManager.cs @@ -15,14 +15,11 @@ GOVERNMENT. UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. -------------------------------------------------------------------------*/ -using NLog; using Raytheon.Common; using Raytheon.Instruments; using System; using System.Collections.Generic; -using System.Drawing; -using System.Threading; -using System.Threading.Tasks; +using NLog; namespace Raytheon { @@ -45,16 +42,7 @@ namespace Raytheon public bool FrontPanelEnabled { - get - { - if (_powerSupply != null) - { - return _powerSupply[null].FrontPanelEnabled; - } - else - return true; - } - + private get { return false; } set { if (_powerSupply != null) @@ -67,7 +55,7 @@ namespace Raytheon /// /// constructor /// - /// the name specified in the Instruments.xml file + /// public PowerModuleMeasurementManager(PowerSupply powerSupply, IConfigurationFile powerOffAndSelfTestConfig) { _logger = LogManager.GetCurrentClassLogger(); @@ -109,6 +97,22 @@ namespace Raytheon _powerSupply[module].ReadPowerSupplyData(out voltage, out current, out voltageSetPoint, out isOn, out faultStatus); } + /// + /// Get all the names of modules in the power system + /// + public List GetModuleNames() + { + return _powerSupply.GetPowerSupplyModuleNames(); + } + + /// + /// Get all the configuration information for each module + /// + public Dictionary GetPowerSupplyModuleInfoDict() + { + return _powerSupply.GetPowerSupplyModuleInfoDict(); + } + /// /// Enable the output of the power supply. /// diff --git a/Source/MeasurementManagers/PowerSupplyMeasurementManager/PowerSupplyMeasurementManager .cs b/Source/MeasurementManagers/PowerSupplyMeasurementManager/PowerSupplyMeasurementManager .cs index cf4484e..b4e5869 100644 --- a/Source/MeasurementManagers/PowerSupplyMeasurementManager/PowerSupplyMeasurementManager .cs +++ b/Source/MeasurementManagers/PowerSupplyMeasurementManager/PowerSupplyMeasurementManager .cs @@ -76,17 +76,22 @@ namespace Raytheon { get { - if (!powerSystemId.GetType().IsEnum) + string powerSystemName; + if (powerSystemId.GetType().IsEnum || powerSystemId is string) { - throw new ArgumentException($"{nameof(powerSystemId)} must be an enumerated type"); + powerSystemName = powerSystemId.ToString(); + } + else + { + throw new ArgumentException($"{nameof(powerSystemId)} must be an enumerated or string type"); } - if (!_powerSystemNameToPowerModuleMeasurementManagerDict.ContainsKey(powerSystemId.ToString())) + if (!_powerSystemNameToPowerModuleMeasurementManagerDict.ContainsKey(powerSystemName)) { - throw new Exception($"Invalid power supply system: {powerSystemId.ToString()}"); + throw new Exception($"Invalid power supply system: {powerSystemName}"); } - return _powerSystemNameToPowerModuleMeasurementManagerDict[powerSystemId.ToString()]; + return _powerSystemNameToPowerModuleMeasurementManagerDict[powerSystemName]; } } diff --git a/Source/Program/Program.cs b/Source/Program/Program.cs index 71183e6..0888324 100644 --- a/Source/Program/Program.cs +++ b/Source/Program/Program.cs @@ -55,8 +55,8 @@ namespace ProgramLib private ILogger _logger; - private object _fatalErrorMsgFromThreadSyncObj = new object(); - private string _fatalErrorMsgFromThread; + private object _fatalErrorMsgFromSupportThreadSyncObj = new object(); + private string _fatalErrorMsgFromSupportThread; #endregion @@ -249,7 +249,7 @@ namespace ProgramLib if (!_terminateTestInitiated) { // tells teststand there's a exception occurred and give it the error message - _testStandSeqContext.SequenceErrorMessage = _fatalErrorMsgFromThread + " "; + _testStandSeqContext.SequenceErrorMessage = _fatalErrorMsgFromSupportThread + " "; _testStandSeqContext.SequenceErrorOccurred = true; // tells TestStand to go to clean up @@ -267,13 +267,13 @@ namespace ProgramLib /// /// /// - internal void SetFatalErrorMsgFromThread(string errorMsg) + internal void SetFatalErrorMsgFromSupportThread(string errorMsg) { - lock(_fatalErrorMsgFromThreadSyncObj) + lock(_fatalErrorMsgFromSupportThreadSyncObj) { - if (String.IsNullOrEmpty(_fatalErrorMsgFromThread)) + if (String.IsNullOrEmpty(_fatalErrorMsgFromSupportThread)) { - _fatalErrorMsgFromThread = errorMsg; + _fatalErrorMsgFromSupportThread = errorMsg; } } } diff --git a/Source/Program/Threads/FailureMonitorThread.cs b/Source/Program/Threads/FailureMonitorThread.cs index 8b8a8a3..09317fa 100644 --- a/Source/Program/Threads/FailureMonitorThread.cs +++ b/Source/Program/Threads/FailureMonitorThread.cs @@ -81,6 +81,8 @@ namespace ProgramLib if (id == Events.FATAL_FAILURE) { + Program.Instance()._eventManager[EventManager.Events.GLOBAL_QUIT].Set(); + UutPowerAction uutPowerAction = new UutPowerAction(); uutPowerAction.UutPowerOff(); diff --git a/Source/Program/Threads/PassthroughDataGuiUpdateThread.cs b/Source/Program/Threads/PassthroughDataGuiUpdateThread.cs index bcf09be..aeac74f 100644 --- a/Source/Program/Threads/PassthroughDataGuiUpdateThread.cs +++ b/Source/Program/Threads/PassthroughDataGuiUpdateThread.cs @@ -29,6 +29,9 @@ using System.Threading.Tasks; namespace ProgramLib { + /// + /// Class to spawn thread to update passthrough data on GUI + /// internal class PassthroughDataGuiUpdateThread : BasicThread { private enum Events @@ -46,6 +49,9 @@ namespace ProgramLib private MainWindow _mainWindow; private PassthroughData _passthroughData = null; + /// + /// Constructor + /// public PassthroughDataGuiUpdateThread() { _logger = LogManager.GetCurrentClassLogger(); @@ -65,6 +71,11 @@ namespace ProgramLib _logger?.Debug($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() ..."); } + /// + /// Method that executes on the thread. + /// + /// + /// protected override void DoWork() { _logger?.Debug($"{this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() is running..."); @@ -99,6 +110,11 @@ namespace ProgramLib } + /// + /// Update GUI with data + /// + /// + /// private void UpdatePassthroughDataGui() { int pollRateMs = 1000; diff --git a/Source/Program/Threads/PowerSupplyGuiUpdateThread.cs b/Source/Program/Threads/PowerSupplyGuiUpdateThread.cs index 239aa40..366e7a9 100644 --- a/Source/Program/Threads/PowerSupplyGuiUpdateThread.cs +++ b/Source/Program/Threads/PowerSupplyGuiUpdateThread.cs @@ -29,6 +29,9 @@ using System.Threading.Tasks; namespace ProgramLib { + /// + /// Class to spawn thread to update power supply data on GUI + /// internal class PowerSupplyGuiUpdateThread : BasicThread { private enum Events @@ -47,6 +50,9 @@ namespace ProgramLib private Dictionary _powerModuleToPowerDataModelDict = new Dictionary(); + /// + /// Constructor + /// public PowerSupplyGuiUpdateThread() { _logger = LogManager.GetCurrentClassLogger(); @@ -67,6 +73,11 @@ namespace ProgramLib _logger?.Debug($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() ..."); } + /// + /// Method that executes on the thread. + /// + /// + /// protected override void DoWork() { _logger?.Debug($"{this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() is running..."); @@ -101,6 +112,11 @@ namespace ProgramLib } + /// + /// Update GUI with data + /// + /// + /// private void UpdatePowerSupplyGui() { int pollRateMs = 1000; diff --git a/Source/Program/Threads/PowerSupplyReadThread.cs b/Source/Program/Threads/PowerSupplyReadThread.cs index 9516aea..2d686d2 100644 --- a/Source/Program/Threads/PowerSupplyReadThread.cs +++ b/Source/Program/Threads/PowerSupplyReadThread.cs @@ -15,20 +15,17 @@ GOVERNMENT. UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY. -------------------------------------------------------------------------*/ -using NLog; -using ProgramGui; -using ProgramGui.Model; -using ProgramGui.ViewModel; -using ProgramLib; using System; +using System.Collections; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading; -using System.Threading.Tasks; +using NLog; namespace ProgramLib { + /// + /// Class to spawn thread to read power supply data + /// internal class PowerSupplyReadThread : BasicThread { private enum Events @@ -46,7 +43,12 @@ namespace ProgramLib private string _powerSupplySystemName; + private List _powerModuleNameList; + Dictionary _powerSupplyModuleInfoDict; + /// + /// Constructor + /// public PowerSupplyReadThread(string powerSupplySystemName) { _logger = LogManager.GetCurrentClassLogger(); @@ -60,6 +62,11 @@ namespace ProgramLib _logger?.Debug($"Entering {this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() ..."); } + /// + /// Method that executes on the thread. + /// + /// + /// protected override void DoWork() { _logger?.Debug($"{this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() for {_powerSupplySystemName} is running..."); @@ -73,6 +80,9 @@ namespace ProgramLib EventGroup eventGroup = new EventGroup(eventDict); + _powerModuleNameList = Program.Instance().GetPowerSupplyMeasurementManager()[_powerSupplySystemName].GetModuleNames(); + _powerSupplyModuleInfoDict = Program.Instance().GetPowerSupplyMeasurementManager()[_powerSupplySystemName].GetPowerSupplyModuleInfoDict(); + while (true) { Events id = eventGroup.WaitAny(); @@ -94,6 +104,11 @@ namespace ProgramLib } + /// + /// Read power supply data and check for faults + /// + /// + /// private void ReadPowerSupplyData() { int pollRateMs = 1000; @@ -108,15 +123,53 @@ namespace ProgramLib EventGroup eventGroup = new EventGroup(eventDict); - Random rnd = new Random(); + double voltage; + double current; + double voltageSetPoint; + bool isOn; + int faultStatus; + while (true) { Events id = eventGroup.WaitAny(pollRateMs); if (id == Events.EVENT_TIMED_OUT) { - Thread.Sleep(100); + foreach (string moduleName in _powerModuleNameList) + { + Program.Instance().GetPowerSupplyMeasurementManager()[_powerSupplySystemName].ReadPowerSupplyData(moduleName, out voltage, out current, out voltageSetPoint, out isOn, out faultStatus); + BitArray statusReg = new BitArray(new int[] { faultStatus }); + + bool ovpTriggeredInPowerSupply = statusReg[0]; + bool ocpTriggeredInPowerSupply = statusReg[1]; + + if (!ovpTriggeredInPowerSupply && !ocpTriggeredInPowerSupply) + { + if (IsCurrentWithinLimits(moduleName, current)) + break; + + if (IsVoltageWithinLimits(moduleName, voltage)) + break; + } + else + { + string errorMsg = String.Empty; + + if (ovpTriggeredInPowerSupply) + { + errorMsg = moduleName + "'s OVP circuitry has tripped"; + } + else if (ocpTriggeredInPowerSupply) + { + errorMsg = moduleName + "'s OCP circuitry has tripped"; + } + + HandleOutOfToleranceCondition(errorMsg); + + break; + } + } } else break; @@ -130,5 +183,59 @@ namespace ProgramLib _logger?.Debug($"{this.GetType().Name}::{System.Reflection.MethodBase.GetCurrentMethod().Name}() for {_powerSupplySystemName} is exiting..."); } + /// + /// Check for current's upper limit + /// + /// + /// + private bool IsCurrentWithinLimits(string moduleName, double current) + { + bool outOfLimits = false; + Raytheon.Instruments.PowerSupplies.PowerSupplyModuleInfo powerSupplyModuleInfo = _powerSupplyModuleInfoDict[moduleName]; + + if ((current < powerSupplyModuleInfo.currentLowerLimit_ || current > powerSupplyModuleInfo.currentUpperLimit_) && powerSupplyModuleInfo.isOn_) + { + outOfLimits = true; + string errorMsg = moduleName + "'s current is out of limits (" + powerSupplyModuleInfo.currentLowerLimit_.ToString("0.00") + "," + powerSupplyModuleInfo.currentUpperLimit_.ToString("0.00") + "). Current reading: " + current.ToString("0.00"); + HandleOutOfToleranceCondition(errorMsg); + } + + return outOfLimits; + } + + /// + /// Check for voltage's limit exceedence + /// + /// + /// + private bool IsVoltageWithinLimits(string moduleName, double voltage) + { + bool outOfLimits = false; + Raytheon.Instruments.PowerSupplies.PowerSupplyModuleInfo powerSupplyModuleInfo = _powerSupplyModuleInfoDict[moduleName]; + + if ((voltage < powerSupplyModuleInfo.voltageLowerLimit_ || voltage > powerSupplyModuleInfo.voltageUpperLimit_) && powerSupplyModuleInfo.isOn_) + { + outOfLimits = true; + string errorMsg = moduleName + "'s voltage is out of limits (" + powerSupplyModuleInfo.voltageLowerLimit_.ToString("0.00") + "," + powerSupplyModuleInfo.voltageUpperLimit_.ToString("0.00") + "). Voltage reading: " + voltage.ToString("0.00"); + HandleOutOfToleranceCondition(errorMsg); + } + + return outOfLimits; + } + + /// + /// Handle power fault conditions + /// + /// + /// + private void HandleOutOfToleranceCondition(string errorMsg) + { + if (!Program.Instance()._eventManager[EventManager.Events.FATAL_FAILURE].WaitOne(0)) + { + Program.Instance().SetFatalErrorMsgFromSupportThread(errorMsg); + Program.Instance()._eventManager[EventManager.Events.FATAL_FAILURE].Set(); + } + } + } }