// 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.Threading; using NLog; using Raytheon.Common; using Raytheon.Instruments; using Raytheon.Instruments.Dmm; using Raytheon.Units; namespace MeasurementManagerLib { /// /// The interface to the instruments contained in the vsu test station. /// This class reads in test station configuration ini file that contains: /// - DMM measurement definitions /// The host of this class can invoke those measurements by commanding the this class with the ini file string names /// which insulates the caller from having to know the details of that measurement /// public class SwitchMeasurementManager : IDisposable { #region PublicMembers /// /// Type of DMM Resistance Measurements /// public enum DMMResistanceType { TWO, FOUR, }; public enum DMMVoltageType { DC, AC, }; public Dictionary _dmmResistancePseudoTypeToTrueTypeMap = new Dictionary() { { DMMResistanceType.TWO, MeasurementFunction.TwoWireResistance } , { DMMResistanceType.FOUR, MeasurementFunction.FourWireResistance } }; /// /// Struct for holding on to DMM measurement definitions /// public struct DMMFrequencyMeasurementFields { public readonly double _range; public readonly double _resolution; public readonly double _scaleFactor; public readonly int _delay; public List _relays; public readonly double _voltRange; public readonly double _numReads; public DMMFrequencyMeasurementFields(double range, double resolution, int delay, double scaleFactor, List relays, double voltRange, double numReads) { _range = range; _resolution = resolution; _delay = delay; _scaleFactor = scaleFactor; _relays = relays; _voltRange = voltRange; _numReads = numReads; } } /// /// Struct for holding on to DMM measurement definitions /// public struct DMMVoltageMeasurementFields { public readonly double _range; public readonly double _resolution; public readonly double _scaleFactor; public readonly int _delay; public List _relays; public DMMVoltageType _voltageType; public DMMVoltageMeasurementFields(double range, double resolution, int delay, double scaleFactor, List relays, DMMVoltageType voltageType) { _range = range; _resolution = resolution; _delay = delay; _scaleFactor = scaleFactor; _relays = relays; _voltageType = voltageType; } } /// /// Struct for holding on to DMM measurement definitions /// public struct DMMResistanceMeasurementFields { public readonly string _pcode; public readonly double _range; public readonly double _resolution; public readonly double _scaleFactor; public readonly int _minDelay; public readonly int _maxDelay; public string _relayPath; public Raytheon.Instruments.Dmm.MeasurementFunction _dmmResistanceType; public readonly string _cableAndPinId; public readonly double _lowerLimit; public readonly double _upperLimit; public DMMResistanceMeasurementFields(string pcode, double range, double resolution, int minDelay, int maxDelay, double scaleFactor, string relayPath, Raytheon.Instruments.Dmm.MeasurementFunction type, string cableAndPinId, double lowerLimit, double upperLimit) { _pcode = pcode; _range = range; _resolution = resolution; _minDelay = minDelay; _maxDelay = maxDelay; _scaleFactor = scaleFactor; _relayPath = relayPath; _dmmResistanceType = type; _cableAndPinId = cableAndPinId; _lowerLimit = lowerLimit; _upperLimit = upperLimit; } } /// /// State for a trigger edge. /// public enum ScopeEdge { FALLING = 0, RISING, HOLDING }; public readonly struct ScopePulseWidthMeasurementFields { public readonly List _relays; public readonly int _channelNumber; public readonly ScopeEdge _edge; public readonly double _timePerDivision; public readonly double _timeOffset; public readonly double _triggerLevel; public readonly double _voltageOffset; public readonly double _voltageScale; public readonly string _inputImpedance; //public readonly double m_measurementTime; public readonly int _delay; public readonly bool _shallWeSaveImage; public readonly int _maxTriggerWaitTime; public ScopePulseWidthMeasurementFields(List relays, int channelNumber, ScopeEdge edge, double timePerDivision, double timeOffset, double triggerLevel, double voltageOffset, double voltageScale, string inputImpedance, int delay, bool shallWeSaveImage, int maxTriggerWaitTime) { _relays = relays; _channelNumber = channelNumber; _edge = edge; _inputImpedance = inputImpedance; _timePerDivision = timePerDivision; _timeOffset = timeOffset; _triggerLevel = triggerLevel; _voltageOffset = voltageOffset; _voltageScale = voltageScale; _delay = delay; _shallWeSaveImage = shallWeSaveImage; _maxTriggerWaitTime = maxTriggerWaitTime; } } public readonly struct ScopeFrequencyMeasurementFields { public readonly List _relays; public readonly int _channelNumber; public readonly ScopeEdge _edge; public readonly double _timePerDivision; public readonly double _timeOffset; public readonly double _triggerLevel; public readonly double _voltageOffset; public readonly double _voltageScale; public readonly string _inputImpedance; //public readonly double m_measurementTime; public readonly int _delay; public readonly bool _shallWeSaveImage; public readonly int _maxTriggerWaitTime; public ScopeFrequencyMeasurementFields(List relays, int channelNumber, ScopeEdge edge, double timePerDivision, double timeOffset, double triggerLevel, double voltageOffset, double voltageScale, string inputImpedance, int delay, bool shallWeSaveImage, int maxTriggerWaitTime) { _relays = relays; _channelNumber = channelNumber; _edge = edge; _inputImpedance = inputImpedance; _timePerDivision = timePerDivision; _timeOffset = timeOffset; _triggerLevel = triggerLevel; _voltageOffset = voltageOffset; _voltageScale = voltageScale; _delay = delay; _shallWeSaveImage = shallWeSaveImage; _maxTriggerWaitTime = maxTriggerWaitTime; } } public Dictionary DmmFrequencyMeasurements { get; private set; } public Dictionary DmmResistanceMeasurements { get; private set; } public Dictionary DmmVoltageMeasurements { get; private set; } public Dictionary ScopeFreqMeasurements { get; private set; } public Dictionary ScopePulseWidthMeasurements { get; private set; } public Dictionary RelayMap { get; private set; } #endregion #region PrivateClassMembers /// /// private class members /// private readonly IDmm _dmm; private readonly IOscilloScope _scope; private readonly Dictionary _switchCards; private static readonly object _syncObj = new Object(); private static NLog.ILogger _logger; #endregion #region PrivateFunctions /// /// The Finalizer /// ~SwitchMeasurementManager() { } /// /// Check configuration information is correct /// private void CheckForDmmResistanceConfigValidity() { foreach (KeyValuePair entry in DmmResistanceMeasurements) { string[] relayInfo = entry.Value._relayPath.Split(':'); if (relayInfo.Length != 2) { throw new Exception("Relay format is not correct: " + relayInfo[0]); } if (_switchCards.ContainsKey(relayInfo[0].ToUpper()) == false) { throw new Exception("Switch card does not exist: " + relayInfo[0]); } } } /// /// Check configuration information is correct /// private void CheckForDmmFrequencyConfigValidity() { foreach (KeyValuePair entry in DmmFrequencyMeasurements) { string[] relayInfo = entry.Value._relays[0].Split(':'); if (relayInfo.Length != 2) { throw new Exception("Relay format is not correct: " + relayInfo[0]); } if (_switchCards.ContainsKey(relayInfo[0].ToUpper()) == false) { throw new Exception("Switch card does not exist: " + relayInfo[0]); } } } /// /// Check configuration information is correct /// private void CheckForDmmVoltageConfigValidity() { foreach (KeyValuePair entry in DmmVoltageMeasurements) { string[] relayInfo = entry.Value._relays[0].Split(':'); if (relayInfo.Length != 2) { throw new Exception("Relay format is not correct: " + relayInfo[0]); } if (_switchCards.ContainsKey(relayInfo[0].ToUpper()) == false) { throw new Exception("Switch card does not exist: " + relayInfo[0]); } } } /// /// Check configuration information is correct /// private void CheckForScopeFrequencyConfigValidity() { foreach (KeyValuePair entry in ScopeFreqMeasurements) { string[] relayInfo = entry.Value._relays[0].Split(':'); if (relayInfo.Length != 2) { throw new Exception("Relay format is not correct: " + relayInfo[0]); } if (_switchCards.ContainsKey(relayInfo[0].ToUpper()) == false) { throw new Exception("Switch card does not exist: " + relayInfo[0]); } } } /// /// Check configuration information is correct /// private void CheckForScopePulseWidthConfigValidity() { foreach (KeyValuePair entry in ScopePulseWidthMeasurements) { string[] relayInfo = entry.Value._relays[0].Split(':'); if (relayInfo.Length != 2) { throw new Exception("Relay format is not correct: " + relayInfo[0]); } if (_switchCards.ContainsKey(relayInfo[0].ToUpper()) == false) { throw new Exception("Switch card does not exist: " + relayInfo[0]); } } } /// /// Dispose of this objects resources /// /// protected virtual void Dispose(bool disposing) { if (disposing) { if (_dmm != null) { _dmm.Shutdown(); } if (_switchCards != null) { foreach (KeyValuePair switchCard in _switchCards) { if (_switchCards[switchCard.Key] != null) { _switchCards[switchCard.Key].Shutdown(); } } } if (_scope != null) { _scope.Shutdown(); } } } /// /// Will command the switch cards close a specified list of relays /// /// public void SwitchRelayClose(List relayList) { string cardName = String.Empty; string path = String.Empty; foreach (string item in relayList) { //break out the card and relay if (item.Contains(":")) { string[] itemArray = item.Split(':'); cardName = itemArray[0].Trim(); path = itemArray[1].Trim(); } else path = item.Trim(); if (!String.IsNullOrEmpty(cardName)) { //close the relays _switchCards[cardName.ToUpper()].Connect(path); } } } /// /// Will command the switch cards close a specified list of relays /// /// public void SwitchRelayClose(string relayPath) { string cardName = String.Empty; string path = String.Empty; string[] itemArray = relayPath.Split(':'); //break out the card and relay if (itemArray.Length == 2) { cardName = itemArray[0].Trim(); path = itemArray[1].Trim(); } else { throw new Exception($"Invalid relay path: {relayPath}. Expected format: [Switch_Instance_Name]:[RelayPath]"); } if (!String.IsNullOrEmpty(cardName)) { //close the relays _switchCards[cardName.ToUpper()].Connect(path); } } /// /// Will command the switch card open all relays or the specified list of relays /// /// Optional list of relays to open public void SwitchRelayOpen(List relayList) { string cardName = String.Empty; string path = String.Empty; foreach (string item in relayList) { //break out the card and relay if (item.Contains(":")) { string[] itemArray = item.Split(':'); cardName = itemArray[0].Trim(); path = itemArray[1].Trim(); } else path = item.Trim(); if (!String.IsNullOrEmpty(cardName)) { //close the relays _switchCards[cardName.ToUpper()].Disconnect(path); } } } /// /// Will command the switch cards close a specified list of relays /// /// public void SwitchRelayOpen(string relayPath) { string cardName = String.Empty; string path = String.Empty; string[] itemArray = relayPath.Split(':'); //break out the card and relay if (itemArray.Length == 2) { cardName = itemArray[0].Trim(); path = itemArray[1].Trim(); } else { throw new Exception($"Invalid relay path: {relayPath}. Expected format: [Switch_Instance_Name]:[RelayPath]"); } if (!String.IsNullOrEmpty(cardName)) { //close the relays _switchCards[cardName.ToUpper()].Disconnect(path); } } /// /// Opens all relays on all switch cards /// private void SwitchRelayOpenAll() { foreach (KeyValuePair switchCard in _switchCards) { _switchCards[switchCard.Key].DisconnectAll(); } } #endregion #region PublicFunctions /// /// constructor that uses instrument manager for creating an instrument /// /// /// /// Skip DMM initialzation, since we want to initialize it separately like the SquibMeter public SwitchMeasurementManager(IInstrumentManager instrumentManager, string switchMeasurementManagerConfigFullPath, bool skipDmmInitialization = false) { _logger = LogManager.GetCurrentClassLogger(); _switchCards = new Dictionary(); ICollection switchCardList = instrumentManager.GetInstruments(typeof(ISwitch)); foreach (ISwitch switchCard in switchCardList) { _switchCards[switchCard.Name] = switchCard; _switchCards[switchCard.Name]?.Initialize(); } ICollection dmmList = instrumentManager.GetInstruments(typeof(IDmm)); if (dmmList.Count > 0) { _dmm = (IDmm)dmmList.First(); if (!skipDmmInitialization) _dmm.Initialize(); } ICollection scopeList = instrumentManager.GetInstruments(typeof(IOscilloScope)); if (scopeList.Count > 0) { _scope = (IOscilloScope)dmmList.First(); _scope.Initialize(); } if (switchCardList.Count == 0) { throw new Exception("Please add a Switch instrument. Switch manager needs one inder to work properly."); } if (dmmList.Count == 0 && scopeList.Count == 0) { throw new Exception("Please add a DMM or Scope instrument. Switch manager needs one of these instruments to inder to work properly."); } RelayMap = new Dictionary(); DmmFrequencyMeasurements = new Dictionary(); DmmResistanceMeasurements = new Dictionary(); DmmVoltageMeasurements = new Dictionary(); ScopeFreqMeasurements = new Dictionary(); ScopePulseWidthMeasurements = new Dictionary(); ConfigurationFile configurationFile = new ConfigurationFile(switchMeasurementManagerConfigFullPath); ParseRelayListDef(configurationFile); ParseDmmFrequencyMeasurementDef(configurationFile); CheckForDmmFrequencyConfigValidity(); ParseDmmResistanceMeasurementDef(configurationFile); CheckForDmmResistanceConfigValidity(); ParseDmmVoltageMeasurementDef(configurationFile); CheckForDmmVoltageConfigValidity(); ParseScopeFrequencyMeasurementDef(configurationFile); CheckForScopeFrequencyConfigValidity(); ParseScopePulseWidthMeasurementDef(configurationFile); CheckForScopePulseWidthConfigValidity(); } /// /// Parse Relay list defintions from config file /// private void ParseRelayListDef(ConfigurationFile configurationFile) { const string RELAY_EXCLUSION_SECTION_NAME = "RELAYS"; List keys = configurationFile.ReadAllKeys(RELAY_EXCLUSION_SECTION_NAME); foreach (string key in keys) { RelayMap[key] = configurationFile.ReadValue(RELAY_EXCLUSION_SECTION_NAME, key); } } /// /// Parse DMM Resistance measurement defintions from config file /// private void ParseDmmResistanceMeasurementDef(ConfigurationFile configurationFile) { const string DMM_RESISTANCE_SECTION_NAME = "DmmReadResistance"; List keys = configurationFile.ReadAllKeys(DMM_RESISTANCE_SECTION_NAME); foreach (string key in keys) { List valueList = configurationFile.ReadList(DMM_RESISTANCE_SECTION_NAME, key); int index = 0; string pcode = valueList[index++]; double range = Convert.ToDouble(valueList[index++]); double res = Convert.ToDouble(valueList[index++]); int minDelay = Convert.ToInt32(valueList[index++]); int maxDelay = Convert.ToInt32(valueList[index++]); double scaleFactor = Convert.ToDouble(valueList[index++]); string relayPath = valueList[index++]; string resistanceTypeStr = valueList[index++].Trim(); DMMResistanceType type = (DMMResistanceType)Enum.Parse(typeof(DMMResistanceType), resistanceTypeStr, true); string cableAndPinId = valueList[index++]; double lowerLimit = Convert.ToDouble(valueList[index++]); double upperLimit = Convert.ToDouble(valueList[index++]); DmmResistanceMeasurements.Add(key.ToUpper(), new DMMResistanceMeasurementFields(pcode, range, res, minDelay, maxDelay, scaleFactor, relayPath, _dmmResistancePseudoTypeToTrueTypeMap[type], cableAndPinId, lowerLimit, upperLimit)); } } /// /// Parse DMM Frequency measurement defintions from config file /// private void ParseDmmFrequencyMeasurementDef(ConfigurationFile configurationFile) { const string DMM_FREQUENCY_SECTION_NAME = "DmmReadFrequency"; const char BAR_DELIM = '|'; const char COMMA_DELIM = ','; List keys = configurationFile.ReadAllKeys(DMM_FREQUENCY_SECTION_NAME); foreach (string key in keys) { string value = configurationFile.ReadValue(DMM_FREQUENCY_SECTION_NAME, key); string[] valueList = value.Split(BAR_DELIM); int index = 0; double range = Convert.ToDouble(valueList[index++]); double res = Convert.ToDouble(valueList[index++]); int delay = Convert.ToInt32(valueList[index++]); double scaleFactor = Convert.ToDouble(valueList[index++]); List relayList = valueList[index++].Split(COMMA_DELIM).ToList(); for (int i = 0; i < relayList.Count; ++i) { relayList[i] = relayList[i].Trim(); } double voltRange = Convert.ToDouble(valueList[index++]); double numReads = Convert.ToDouble(valueList[index++]); DmmFrequencyMeasurements.Add(key.ToUpper(), new DMMFrequencyMeasurementFields(range, res, delay, scaleFactor, relayList, voltRange, numReads)); } } /// /// Parse DMM voltage measurement defintions from config file /// private void ParseDmmVoltageMeasurementDef(ConfigurationFile configurationFile) { const string DMM_VOLTAGE_SECTION_NAME = "DmmReadVoltage"; const char BAR_DELIM = '|'; const char COMMA_DELIM = ','; List keys = configurationFile.ReadAllKeys(DMM_VOLTAGE_SECTION_NAME); foreach (string key in keys) { string value = configurationFile.ReadValue(DMM_VOLTAGE_SECTION_NAME, key); string[] valueList = value.Split(BAR_DELIM); int index = 0; double range = Convert.ToDouble(valueList[index++]); double res = Convert.ToDouble(valueList[index++]); int delay = Convert.ToInt32(valueList[index++]); double scaleFactor = Convert.ToDouble(valueList[index++]); List relayList = valueList[index++].Split(COMMA_DELIM).ToList(); for (int i = 0; i < relayList.Count; ++i) { relayList[i] = relayList[i].Trim(); } string voltTypeStr = valueList[index++].Trim(); DMMVoltageType type = (DMMVoltageType)Enum.Parse(typeof(DMMVoltageType), voltTypeStr, true); DmmVoltageMeasurements.Add(key.ToUpper(), new DMMVoltageMeasurementFields(range, res, delay, scaleFactor, relayList, type)); } } /// /// Parse Scope frequency measurement defintions from config file /// private void ParseScopeFrequencyMeasurementDef(ConfigurationFile configurationFile) { const string SCOPE_FREQUENCY_SECTION_NAME = "ScopeReadFrequency"; const char BAR_DELIM = '|'; const char COMMA_DELIM = ','; List keys = configurationFile.ReadAllKeys(SCOPE_FREQUENCY_SECTION_NAME); foreach (string key in keys) { string value = configurationFile.ReadValue(SCOPE_FREQUENCY_SECTION_NAME, key); string[] valueList = value.Split(BAR_DELIM); int index = 0; // support for no relays (direct connect to scope) List relayList = new List(); if (valueList[index].Trim() == "") { // no relays, nothing to do } else { relayList = valueList[index].Split(COMMA_DELIM).ToList(); } index++; for (int i = 0; i < relayList.Count; ++i) { relayList[i] = relayList[i].Trim(); } int channel = Convert.ToInt32(valueList[index++]); string edgeStr = valueList[index++].Trim(); ScopeEdge edge = (ScopeEdge)Enum.Parse(typeof(ScopeEdge), edgeStr, true); double timePerDivision = Convert.ToDouble(valueList[index++]); double timeoffset = Convert.ToDouble(valueList[index++]); double timetriggerLevel = Convert.ToDouble(valueList[index++]); double voltageOffset = Convert.ToDouble(valueList[index++]); double voltageScale = Convert.ToDouble(valueList[index++]); string inputImpedance = valueList[index++]; int delay = Convert.ToInt32(valueList[index++]); bool shallWeSaveImage = Convert.ToBoolean(valueList[index++]); int maxTriggerWaitTime = Convert.ToInt32(valueList[index++]); ScopeFreqMeasurements.Add(key.ToUpper(), new ScopeFrequencyMeasurementFields(relayList, channel, edge, timePerDivision, timeoffset, timetriggerLevel, voltageOffset, voltageScale, inputImpedance, delay, shallWeSaveImage, maxTriggerWaitTime)); } } /// /// Parse Scope pulse width measurement defintions from config file /// private void ParseScopePulseWidthMeasurementDef(ConfigurationFile configurationFile) { const string SCOPE_PULSE_WIDTH_SECTION_NAME = "ScopeReadPulseWidth"; const char BAR_DELIM = '|'; const char COMMA_DELIM = ','; List keys = configurationFile.ReadAllKeys(SCOPE_PULSE_WIDTH_SECTION_NAME); foreach (string key in keys) { string value = configurationFile.ReadValue(SCOPE_PULSE_WIDTH_SECTION_NAME, key); string[] valueList = value.Split(BAR_DELIM); int index = 0; // support for no relays (direct connect to scope) List relayList = new List(); if (valueList[index].Trim() == "") { // no relays, nothing to do } else { relayList = valueList[index].Split(COMMA_DELIM).ToList(); } index++; for (int i = 0; i < relayList.Count; ++i) { relayList[i] = relayList[i].Trim(); } int channel = Convert.ToInt32(valueList[index++]); string edgeStr = valueList[index++].Trim(); ScopeEdge edge = (ScopeEdge)Enum.Parse(typeof(ScopeEdge), edgeStr, true); double timePerDivision = Convert.ToDouble(valueList[index++]); double timeoffset = Convert.ToDouble(valueList[index++]); double timetriggerLevel = Convert.ToDouble(valueList[index++]); double voltageOffset = Convert.ToDouble(valueList[index++]); double voltageScale = Convert.ToDouble(valueList[index++]); string inputImpedance = valueList[index++]; int delay = Convert.ToInt32(valueList[index++]); bool shallWeSaveImage = Convert.ToBoolean(valueList[index++]); int maxTriggerWaitTime = Convert.ToInt32(valueList[index++]); ScopePulseWidthMeasurements.Add(key.ToUpper(), new ScopePulseWidthMeasurementFields(relayList, channel, edge, timePerDivision, timeoffset, timetriggerLevel, voltageOffset, voltageScale, inputImpedance, delay, shallWeSaveImage, maxTriggerWaitTime)); } } /// /// Dispose of this objects resources /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly")] public void Dispose() { try { lock (_syncObj) { Dispose(true); GC.SuppressFinalize(this); } } catch (Exception err) { try { _logger?.Error(err.Message + "\r\n" + err.StackTrace); } catch (Exception) { //Do not rethrow. Exception from error logger that has already been garbage collected } } } /// /// Make a DMM frequency measurement /// /// frequency measurement to make (the name from the input def file) /// The measured frequency public double DmmReadFrequency(string measurementName) { // hold onto the relays for the catch List measurementRelays = null; try { lock (_syncObj) { if (DmmFrequencyMeasurements.ContainsKey(measurementName.ToUpper()) == false) { throw new Exception("could not find measurement: " + measurementName); } // grab the measurement params DMMFrequencyMeasurementFields measurement = DmmFrequencyMeasurements[measurementName.ToUpper()]; measurementRelays = measurement._relays; // close the relays SwitchRelayClose(measurementRelays); // wait a bit Thread.Sleep(measurement._delay); // make the measurement _dmm.ConfigureFrequencyMeasurement(Raytheon.Instruments.Dmm.MeasurementFunction.Frequency, Frequency.FromHertz(measurement._voltRange), Frequency.FromHertz(measurement._resolution)); double returnValue = _dmm.MeasureFrequency(100).Hertz; // Multiply by the scale factor returnValue = returnValue * measurement._scaleFactor; // return the measurement return returnValue; } } catch (Exception) { throw; } finally { // open the relays if (measurementRelays != null) { SwitchRelayOpen(measurementRelays); } } } /// /// Make a DMM resistance measurement /// /// The resistance measurement to make (the name from the input def file) /// The measured resistance public double DmmReadResistance(string measurementName) { if (DmmResistanceMeasurements.ContainsKey(measurementName.ToUpper()) == false) { throw new Exception("Could not find DMM resistance measurement: " + measurementName); } DMMResistanceMeasurementFields measurement = DmmResistanceMeasurements[measurementName.ToUpper()]; try { lock (_syncObj) { SwitchRelayClose(measurement._relayPath); double returnValue = 0.0; int durationMs = 0; do { if (measurement._minDelay > 0) Thread.Sleep(measurement._minDelay); // make the measurement _dmm.ConfigureResistanceMeasurement(measurement._dmmResistanceType, Resistance.FromOhms(measurement._range), Resistance.FromOhms(measurement._resolution)); returnValue = _dmm.MeasureResistance(100).Ohms; // Multiply by the scale factor returnValue *= measurement._scaleFactor; if (measurement._minDelay <= 0) break; durationMs += measurement._minDelay; } while (!(returnValue >= measurement._lowerLimit && returnValue <= measurement._upperLimit) && durationMs < measurement._maxDelay); // return the measurement return returnValue; } } catch (Exception) { throw; } finally { SwitchRelayOpen(measurement._relayPath); } } /// /// make a DMM voltage measurement /// /// The measurement to make(the name from the input def file) /// The measured voltage public double DmmReadVoltage(string measurementName) { // hold onto the relays for the catch List measurementRelays = null; try { lock (_syncObj) { if (DmmVoltageMeasurements.ContainsKey(measurementName.ToUpper()) == false) { throw new Exception("could not find measurement: " + measurementName); } DMMVoltageMeasurementFields measurement = DmmVoltageMeasurements[measurementName.ToUpper()]; measurementRelays = measurement._relays; //Select DMM Resistance Measurement Type byte desiredMeasurementType = (byte)measurement._voltageType; // close the relays SwitchRelayClose(measurementRelays); // wait a bit Thread.Sleep(measurement._delay); // make the measurement _dmm.ConfigureVoltageMeasurement(Raytheon.Instruments.Dmm.MeasurementFunction.DCVolts, Voltage.FromVolts(measurement._range), Voltage.FromVolts(measurement._resolution)); double returnVal = _dmm.MeasureVoltage(100).Volts; // Multiply by the scale factor returnVal = returnVal * measurement._scaleFactor; // return the measurement return returnVal; } } catch (Exception) { throw; } finally { // open the relays if (measurementRelays != null) { SwitchRelayOpen(measurementRelays); } } } /// /// Make a fall time measurement with the scope /// /// The measurement to make(the name from the input def file) /// public double ScopeReadFallTime(string measurementName) { // hold onto the relays for the catch List measurementRelays = null; try { lock (_syncObj) { //@@@ port over from RKV throw new NotImplementedException(); } } catch (Exception) { throw; } finally { // open the relays if (measurementRelays != null) { SwitchRelayOpen(measurementRelays); } } } /// /// Make a frequency measurement with the scope /// /// The measurement to make(the name from the input def file) /// public double ScopeReadFrequency(string measurementName) { // hold onto the relays for the catch List measurementRelays = null; try { lock (_syncObj) { if (ScopeFreqMeasurements.ContainsKey(measurementName.ToUpper()) == false) { throw new Exception("could not find measurement: " + measurementName); } ScopeFrequencyMeasurementFields measurement = ScopeFreqMeasurements[measurementName.ToUpper()]; measurementRelays = measurement._relays; // close the relays SwitchRelayClose(measurementRelays); // wait a bit Thread.Sleep(measurement._delay); // setup channel _scope.ConfigureChannel(measurement._channelNumber, measurement._timePerDivision, measurement._timeOffset, measurement._voltageOffset, measurement._voltageScale, measurement._inputImpedance); //Set-up trigger bool useRisingEdge = true; if (measurement._edge != ScopeEdge.RISING) { useRisingEdge = false; } _scope.SetupTrigger(useRisingEdge, measurement._channelNumber, measurement._triggerLevel); bool hasScopeTriggered = false; // look for trigger up to the timeout time DateTime delayEndTime = DateTime.Now.AddMilliseconds(measurement._maxTriggerWaitTime); while (hasScopeTriggered == false && DateTime.Now < delayEndTime) { // wait a bit and check the trigger again Thread.Sleep(100); hasScopeTriggered = _scope.HasItTriggered(); } // Check if scope is triggered. if (hasScopeTriggered == false) { throw new Exception("The scope trigger operation is not completed."); } double freq = _scope.MeasureFrequency(measurement._channelNumber); // save the image if (measurement._shallWeSaveImage == true) { _scope.SaveImage(measurementName); } return freq; } } catch (Exception) { throw; } finally { // open the relays if (measurementRelays != null) { SwitchRelayOpen(measurementRelays); } } } /// /// Make a max voltage measurement with the scope /// /// The measurement to make(the name from the input def file) /// public double ScopeReadMaxVoltage(string measurementName) { // hold onto the relays for the catch List measurementRelays = null; try { lock (_syncObj) { //@@@ port over from RKV throw new NotImplementedException(); } } catch (Exception) { throw; } finally { // open the relays if (measurementRelays != null) { SwitchRelayOpen(measurementRelays); } } } /// /// Make a min voltage measurement with the scope /// /// The measurement to make(the name from the input def file) /// public double ScopeReadMinVoltage(string measurementName) { // hold onto the relays for the catch List measurementRelays = null; try { lock (_syncObj) { //@@@ port over from RKV throw new NotImplementedException(); } } catch (Exception) { throw; } finally { // open the relays if (measurementRelays != null) { SwitchRelayOpen(measurementRelays); } } } /// /// make a pulse width measurement with the scope /// /// The measurement to make(the name from the input def file) /// public double ScopeReadPulseWidth(string measurementName) { // hold onto the relays for the catch List measurementRelays = null; try { lock (_syncObj) { if (ScopePulseWidthMeasurements.ContainsKey(measurementName.ToUpper()) == false) { throw new Exception("could not find measurement: " + measurementName); } ScopePulseWidthMeasurementFields measurement = ScopePulseWidthMeasurements[measurementName.ToUpper()]; measurementRelays = measurement._relays; // close the relays SwitchRelayClose(measurementRelays); // wait a bit Thread.Sleep(measurement._delay); // setup channel _scope.ConfigureChannel(measurement._channelNumber, measurement._timePerDivision, measurement._timeOffset, measurement._voltageOffset, measurement._voltageScale, measurement._inputImpedance); //Set-up trigger bool useRisingEdge = true; if (measurement._edge != ScopeEdge.RISING) { useRisingEdge = false; } _scope.SetupTrigger(useRisingEdge, measurement._channelNumber, measurement._triggerLevel); bool hasScopeTriggered = false; // look for trigger up to the timeout time DateTime delayEndTime = DateTime.Now.AddMilliseconds(measurement._maxTriggerWaitTime); while (hasScopeTriggered == false && DateTime.Now < delayEndTime) { // wait a bit and check the trigger again Thread.Sleep(100); hasScopeTriggered = _scope.HasItTriggered(); } // Check if scope is triggered. if (hasScopeTriggered == false) { throw new Exception("The scope trigger operation is not completed."); } double pulseWidth = _scope.MeasurePulseWidth(measurement._channelNumber); // save the image if (measurement._shallWeSaveImage == true) { _scope.SaveImage(measurementName); } return pulseWidth; } } catch (Exception) { throw; } finally { // open the relays if (measurementRelays != null) { SwitchRelayOpen(measurementRelays); } } } /// /// Make a rise time measurement with the scope /// /// The measurement to make(the name from the input def file) /// public double ScopeReadRiseTime(string measurementName) { // hold onto the relays for the catch List measurementRelays = null; try { lock (_syncObj) { //@@@ port over from RKV throw new NotImplementedException(); } } catch (Exception) { throw; } finally { // open the relays if (measurementRelays != null) { SwitchRelayOpen(measurementRelays); } } } /// /// Make a voltage level measurement with the scope /// /// The measurement to make(the name from the input def file) /// public double ScopeReadVoltageLevel(string measurementName) { // hold onto the relays for the catch List measurementRelays = null; try { lock (_syncObj) { //@@@ port over from RKV throw new NotImplementedException(); } } catch (Exception) { throw; } finally { // open the relays if (measurementRelays != null) { SwitchRelayOpen(measurementRelays); } } } /// /// /// public void ScopeSelfTest() { lock (_syncObj) { SelfTestResult res = _scope.PerformSelfTest(); if (res != SelfTestResult.Pass) { throw new Exception("did not pass, the result was: " + res.ToString()); } } } /// /// Sends a SCPI command to the scope and reads the response /// /// The SCPI command to send /// public string ScopeIOQuery(string command) { lock (_syncObj) { return _scope.IOQuery(command); } } /// /// Sends a SCPI command to the scope /// /// The SCPI command to send public void ScopeIOWrite(string command) { lock (_syncObj) { _scope.IOWrite(command); } } #endregion } }