public void ConfigureMeasurementTest() { NIScope testScope = new NIScope("SIM", false, false, "Simulate = 1"); MeasurementConfiguration measConfig = MeasurementConfiguration.GetDefault(); ConfigureMeasurement(testScope, measConfig, "0"); //Validate basic property sets Assert.AreEqual(measConfig.SampleRate_Hz, testScope.Acquisition.SampleRateMin); Assert.AreEqual(measConfig.ScopeTriggerSource, testScope.Trigger.Source.ToString()); Assert.AreEqual(measConfig.TriggerEdge, testScope.Trigger.EdgeTrigger.Slope); Assert.AreEqual(measConfig.ScopeTriggerType, testScope.Trigger.Type); //Validate that the measurement time is properly calculated by teh code Assert.AreEqual(measConfig.MeasurementTime_s, testScope.Acquisition.TimePerRecord.TotalSeconds, 1e-6); //Validate that various trigges are setup correctly measConfig.ScopeTriggerType = ScopeTriggerType.Immediate; ConfigureMeasurement(testScope, measConfig, "0"); Assert.AreEqual(measConfig.ScopeTriggerType, testScope.Trigger.Type); measConfig.ScopeTriggerType = ScopeTriggerType.Software; ConfigureMeasurement(testScope, measConfig, "0"); Assert.AreEqual(measConfig.ScopeTriggerType, testScope.Trigger.Type); testScope.Close(); }
public static void ConfigureMeasurement(NIScope scope, MeasurementConfiguration measurementConfig, string channelNames = "0") { switch (measurementConfig.ScopeTriggerType) { case ScopeTriggerType.DigitalEdge: scope.Trigger.ConfigureTriggerDigital(ScopeTriggerSource.FromString(measurementConfig.ScopeTriggerSource), measurementConfig.TriggerEdge, PrecisionTimeSpan.Zero, PrecisionTimeSpan.Zero); break; case ScopeTriggerType.Immediate: scope.Trigger.ConfigureTriggerImmediate(); break; case ScopeTriggerType.Software: scope.Trigger.ConfigureTriggerSoftware(PrecisionTimeSpan.Zero, PrecisionTimeSpan.Zero); break; default: throw new System.NotImplementedException("The functionality for the requested NI-SCOPE trigger type has not been implemented."); } scope.Acquisition.SampleRateMin = measurementConfig.SampleRate_Hz; scope.Acquisition.NumberOfPointsMin = (long)Math.Round(scope.Acquisition.SampleRate * measurementConfig.MeasurementTime_s); scope.Timing.NumberOfRecordsToAcquire = 1; }
public bool TryStopTask() { //如果是主卡,判断是否有任何从卡没有完成,否则不能出来 if (_staticConfig.TriggerConfig.MasterOrSlave == AITriggerMasterOrSlave.Master) { bool canOut = false; while (!canOut) { canOut = true; lock (TClockDevice.Lock) { foreach (var s in TClockDevice.SlaveOver) { if (s.Value == false) { canOut = false; } } } } } //如果是从卡,设置让主卡可以出来 else if (_staticConfig.TriggerConfig.MasterOrSlave == AITriggerMasterOrSlave.Slave) { lock (TClockDevice.Lock) { TClockDevice.SlaveOver[_staticConfig.ResourceName] = true; } } lock (TClockDevice.Lock) { if (TClockDevice.SyncDevices != null && TClockDevice.SyncDevices.Contains(scopeSession)) { TClockDevice.SyncDevices.Remove(scopeSession); } } try { if (tClockSession != null) { tClockSession = null; } if (scopeSession != null) { scopeSession.Close(); scopeSession.Dispose(); scopeSession = null; } } catch (Exception e) { throw new Exception(e.ToString()); } AIState = Status.Idle; return(true); }
public static void ConfigureScope(NIScope scope, ScopeConfiguration scopeConfig, string channelNames = "0") { scope.Channels[channelNames].Coupling = scopeConfig.ScopeCouplingMode; scope.Channels[channelNames].InputImpedance = (double)scopeConfig.InputImpedance; scope.Channels[channelNames].Range = scopeConfig.VerticalRange_V; scope.Channels[channelNames].Offset = scopeConfig.VerticalOffset_V; scope.Channels[channelNames].ProbeAttenuation = scopeConfig.ProbeAttenuation; scope.Timing.ReferenceClockSource = ScopeInputClockSource.FromString(scopeConfig.ScopeClockSource); scope.Channels[channelNames].Enabled = true; }
/// <summary> /// 配置已经实例化的 scopeSession,包括通道设置、时钟设置以及触发设置 /// </summary> /// <param name="niTask"></param> /// <param name="channelConfiguration"></param> public static void MapAndConfigAll(NIScope scopeSession, NIScopeAIStaticConfig basicAIConifg, ref TClock tClockSession) { if (basicAIConifg.MoreRecordsThanMemoryAllowed == true) { throw new Exception("暂时不支持超内存采样!"); } scopeSession.Timing.MoreRecordsThanMemoryAllowed = basicAIConifg.MoreRecordsThanMemoryAllowed; MapAndConfigTrigger(scopeSession, basicAIConifg.TriggerConfig, ref tClockSession); MapAndConfigClock(scopeSession, basicAIConifg.ClockConfig); MapAndConfigChannel(scopeSession, basicAIConifg.ChannelConfig); }
public static MeasurementResults MeasureChannel(NIScope scope, string channelName = "0") { MeasurementResults results = new MeasurementResults(); scope.Measurement.Initiate(); AnalogWaveformCollection <double> resultWaveform = new AnalogWaveformCollection <double>(); resultWaveform = scope.Channels[channelName].Measurement.FetchDouble(PrecisionTimeSpan.FromSeconds(5), -1, null); results.ResultsTrace = resultWaveform[0].GetRawData(); results.AverageValue_V = scope.Channels[channelName].Measurement.FetchScalarMeasurement(PrecisionTimeSpan.FromSeconds(5), ScopeScalarMeasurementType.VoltageAverage)[0]; scope.Measurement.Abort(); return(results); }
public void StartAcquisition(string channelName, double sampleRate, double referencePosition, double range, int numberOfPoints, int numberOfRecords) { try { scopeDevices = new ModularInstrumentsSystem("NI-Scope"); scopeName = scopeDevices.DeviceCollection[0].Name; scopeSession = new NIScope(scopeName, false, true); scopeSession.DriverOperation.Warning += new EventHandler <ScopeWarningEventArgs>(DriverOperation_Warning); scopeSession.Channels[channelName].InputImpedance = 50; double offset = 0.0; ScopeVerticalCoupling coupling = ScopeVerticalCoupling.DC; double probeAttenuation = 1.0; scopeSession.Channels[channelName].Configure(range, offset, coupling, probeAttenuation, true); // scopeSession.Channels[channelName] bool enforceRealtime = true; scopeSession.Timing.ConfigureTiming (sampleRate, numberOfPoints, referencePosition, numberOfRecords, enforceRealtime); double triggerLevel = 1.6; ScopeTriggerSlope triggerSlope = ScopeTriggerSlope.Positive; ScopeTriggerCoupling triggerCoupling = ScopeTriggerCoupling.DC; PrecisionTimeSpan triggerHoldoff = PrecisionTimeSpan.Zero; PrecisionTimeSpan triggerDelay = PrecisionTimeSpan.Zero; ScopeTriggerSource triggerSource = ScopeTriggerSource.External; scopeSession.Trigger.EdgeTrigger.Configure (triggerSource, triggerLevel, triggerSlope, triggerCoupling, triggerHoldoff, triggerDelay); recordLength = scopeSession.Acquisition.RecordLength; sampleRate = scopeSession.Acquisition.SampleRate; this.channelName = channelName; scopeSession.Measurement.Initiate(); timeout = new PrecisionTimeSpan(5.0); } catch (Exception ex) { ShowError(ex); } }
static void Main() { NIScope myScope = new NIScope("5154", false, false); ScopeConfiguration scopeConfig = GetDefaultScopeConfiguration(); MeasurementConfiguration measConfig = GetDefaultMeasurementConfiguration(); ConfigureScope(myScope, scopeConfig, "0"); ConfigureMeasurement(myScope, measConfig, "0"); MeasurementResults myResults = MeasureChannel(myScope, "0"); Console.WriteLine(myResults.AverageValue_V); Console.ReadKey(); myScope.Close(); }
private static void MapAndConfigClock(NIScope scopeSession, AIClockConfiguration clockConfiguration) { //无时钟源设置 //采样数量,仅支持有限 switch (clockConfiguration.SampleQuantityMode) { case AISamplesMode.FiniteSamples: break; default: throw new Exception("采样数量 SampleQuantityMode 设置错误!仅支持有限采样(0)!"); } //无使能时钟沿 //配置采样率,采样总数,采样次数 int records = clockConfiguration.TotalSampleLengthPerChannel / clockConfiguration.ReadSamplePerTime; scopeSession.Timing.ConfigureTiming(clockConfiguration.SampleRate, clockConfiguration.TotalSampleLengthPerChannel, 0.0, records, true); }
public void ConfigureScopeTest() { NIScope testScope = new NIScope("SIM", false, false, "Simulate = 1"); ScopeConfiguration scopeConfig = ScopeConfiguration.GetDefault(); ConfigureScope(testScope, scopeConfig, "0"); //Check that all properties are properly applied to the scope session Assert.AreEqual((double)scopeConfig.InputImpedance, testScope.Channels["0"].InputImpedance, "Impedance"); Assert.AreEqual(scopeConfig.ScopeCouplingMode, testScope.Channels["0"].Coupling, "Coupling"); Assert.AreEqual(scopeConfig.VerticalOffset_V, testScope.Channels["0"].Offset, "Offset"); Assert.AreEqual(scopeConfig.VerticalRange_V, testScope.Channels["0"].Range, "Range"); Assert.AreEqual(scopeConfig.ProbeAttenuation, testScope.Channels["0"].ProbeAttenuation, "Probe Attenuation"); Assert.AreEqual(scopeConfig.ScopeClockSource, testScope.Timing.ReferenceClockSource.ToString(), "Clock Source"); testScope.Close(); }
private static void MapAndConfigChannel(NIScope scopeSession, AIChannelConfiguration channelConfiguration) { //todo:检查是否真的是0,1,2…… //var channels = ((JArray)channelConfiguration.ChannelName).ToObject<List<int>>(); 当ChannelName还是Object的时候 var channels = ChannelNameTranslator.StringToListInt(channelConfiguration.ChannelName); double range = channelConfiguration.MaximumValue - channelConfiguration.MinimumValue; foreach (var c in channels) { //Todo:信号输入方式无法配置 //配置信号输入方式 switch (channelConfiguration.TerminalConfigType) { //目前只支持差分 case AITerminalType.Differential: scopeSession.Channels[c.ToString()].Configure(range, 0, ScopeVerticalCoupling.DC, 1.0, true); break; default: throw new Exception("输入方式 AITerminalType 定义无效!"); } } }
//读数据 private void readData(NIScope scopeSession) { //var channels = ((JArray)_staticConfig.ChannelConfig.ChannelName).ToObject<List<int>>(); var channels = ChannelNameTranslator.StringToListInt(_staticConfig.ChannelConfig.ChannelName); //开新线程等待读数据 //await Task.Run(() => //{ int totalReadDataLength = 0; PrecisionTimeSpan timeout = new PrecisionTimeSpan(1000000); //无timeOut AnalogWaveformCollection <double> scopeWaveform = null; double[,] readData = new double[_staticConfig.ChannelCount, _staticConfig.ClockConfig.TotalSampleLengthPerChannel]; //生成 channels string channelScope = null; //var sChannels = ((JArray)_staticConfig.ChannelConfig.ChannelName).ToObject<List<int>>(); var sChannels = ChannelNameTranslator.StringToListInt(_staticConfig.ChannelConfig.ChannelName); foreach (var s in sChannels) { channelScope += s + ","; } channelScope = channelScope.Substring(0, channelScope.Length - 1); //一次采完 //经过测试,发现在默认设置(不设置其它)情况下: // 1、如果多次 FetchDouble,则每 2 次的数据不连续(中间断一截) // 2、如果设置多个 records,则每 2 个 record 之间的数据不连续(中间断一截) //因此暂时只允许一个 record scopeWaveform = scopeSession.Channels[channelScope].Measurement.FetchDouble(timeout, _staticConfig.ClockConfig.TotalSampleLengthPerChannel, scopeWaveform); //一旦上面这里获取到数据,则表示采集开始 AIState = Status.Running; // i 是读取次数 // j 是通道计数 // k 是每一波的每个点 double[] temp; AnalogWaveform <double> waveform; for (int i = 0; i < _staticConfig.ClockConfig.TotalSampleLengthPerChannel / _staticConfig.ClockConfig.ReadSamplePerTime; i++) { //将一个通道的数据拷贝到 data[,] 的一行 for (int j = 0; j < _staticConfig.ChannelCount; j++) { waveform = scopeWaveform[i, j]; temp = waveform.GetRawData(); for (int k = 0; k < _staticConfig.ClockConfig.ReadSamplePerTime; k++) { readData[j, i *_staticConfig.ClockConfig.ReadSamplePerTime + k] = temp[k]; } } totalReadDataLength += _staticConfig.ClockConfig.ReadSamplePerTime; } GC.Collect(); Thread.Sleep(2000); //发布数据到达事件 OnDataArrival(readData); //发布停止任务事件 OnAITaskStopped(); //等待,让外部保证获取到 Running 状态 Thread.Sleep(2000); //}); }
private void RealArm() { if (AIState != Status.Idle) { throw new Exception("If you want to arm, the AI state must be 'Idle'!"); } else { if (scopeSession == null) { try { //新建任务 scopeSession = new NIScope(_staticConfig.ResourceName, false, false); //配置任务 NIScopeAIConfigMapper.MapAndConfigAll(scopeSession, _staticConfig, ref tClockSession); //获取并设置通道数 _staticConfig.ChannelCount = scopeSession.Channels.Count; AIState = Status.Ready; if (_staticConfig.TriggerConfig.MasterOrSlave == AITriggerMasterOrSlave.NonSync) { scopeSession.Measurement.Initiate(); } // Master 连同所有 Slaves 只需要一个 tClockSession.Initiate() else if (_staticConfig.TriggerConfig.MasterOrSlave == AITriggerMasterOrSlave.Master) { tClockSession.Initiate(); TClockDevice.IsMasterReady = true; } //注意,这里从 Slave 是不会 Initiate 的,Slave 必须被 Master 带,也就是 Slave 需要等待 Master 准备就绪才能采集 else { while (!TClockDevice.IsSlaveCanAddIntoTDevice) { Thread.Sleep(300); } //等待主卡 Initiate while (!TClockDevice.IsMasterReady) { Thread.Sleep(200); } lock (TClockDevice.Lock) { //表示没有完成,主卡不能 Idle if (TClockDevice.SlaveOver.ContainsKey(_staticConfig.ResourceName)) { TClockDevice.SlaveOver[_staticConfig.ResourceName] = false; } else { TClockDevice.SlaveOver.Add(_staticConfig.ResourceName, false); } } } //开始读取数据 readData(scopeSession); } catch (Exception e) { TryStopTask(); Console.WriteLine("炸了"); throw new Exception("任务因错误终止!" + e.ToString()); } } } }
private static void MapAndConfigTrigger(NIScope scopeSession, AITriggerConfiguration triggerConfiguration, ref TClock tClockSession) { //配置触发沿 ScopeTriggerSlope triggerSlope; switch (triggerConfiguration.TriggerEdge) { case Edge.Rising: triggerSlope = ScopeTriggerSlope.Positive; break; case Edge.Falling: triggerSlope = ScopeTriggerSlope.Negative; break; default: throw new Exception("触发沿 TriggerEdge 设置错误!"); } //设置触发源 ScopeTriggerSource triggerSource = triggerConfiguration.TriggerSource.ToString(); //设置触发模式 switch (triggerConfiguration.TriggerType) { case AITriggerType.Immediate: scopeSession.Trigger.Type = ScopeTriggerType.Immediate; scopeSession.Trigger.ConfigureTriggerImmediate(); break; case AITriggerType.DigitalTrigger: scopeSession.Trigger.Type = ScopeTriggerType.DigitalEdge; scopeSession.Trigger.ConfigureTriggerDigital(triggerSource, triggerSlope, PrecisionTimeSpan.Zero, new PrecisionTimeSpan(triggerConfiguration.Delay)); break; case AITriggerType.AnalogTrigger: scopeSession.Trigger.Type = ScopeTriggerType.Edge; scopeSession.Trigger.EdgeTrigger.Configure(triggerSource, 2.5, triggerSlope, ScopeTriggerCoupling.DC, PrecisionTimeSpan.Zero, new PrecisionTimeSpan(triggerConfiguration.Delay)); break; default: throw new Exception("触发模式 TriggerType 设置错误!"); } //如果不是非同步 //加入到TClock中 if (triggerConfiguration.MasterOrSlave != AITriggerMasterOrSlave.NonSync) { lock (TClockDevice.Lock) { if (TClockDevice.SyncDevices == null) { TClockDevice.SyncDevices = new List <NIScope>(); } TClockDevice.SyncDevices.Add(scopeSession); } } //如果是主卡,则将所有的 SynchronizableDevices 实例化出来,这样写也就决定了只能有一个 Master( NI 机箱可级联支持双 Master) //这一行必须是在所有需要同步的卡 scopeSession 设置完毕之后 if (triggerConfiguration.MasterOrSlave == AITriggerMasterOrSlave.Master) { TClockDevice.IsMasterReady = false; TClockDevice.IsSlaveCanAddIntoTDevice = true; //因为主卡可能会和从卡同时被 Arm,因此先等待所有从卡设备加入 TClockDevice Thread.Sleep(1000); TClockDevice.IsSlaveCanAddIntoTDevice = false; ITClockSynchronizableDevice[] scopeSynchronizableDevices = new ITClockSynchronizableDevice[TClockDevice.SyncDevices.Count]; for (int i = 0; i < TClockDevice.SyncDevices.Count; i++) { scopeSynchronizableDevices[i] = TClockDevice.SyncDevices[i]; } tClockSession = new TClock(scopeSynchronizableDevices); tClockSession.ConfigureForHomogeneousTriggers(); tClockSession.Synchronize(); } }
private static void InitializeSession(string deviceName) { _scopeSession = new NIScope(deviceName, false, false); _scopeSession.DriverOperation.Warning += DriverOperation_Warning; }