Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

analog input task takes extra long to start and stop at certain settings

Solved!
Go to solution

I start a two channel analog input task with the code below.  The only input parameter is the period [seconds] that I would like to monitor.  I use settings between .2 seconds and .00001 seconds (20Hz - 10,000Hz).  For most of these settings, starting and stopping the monitor task takes between 23-154 ms, which is quite acceptable for my purposes.  However, for the one setting of .000133 seconds (7500Hz), the task takes more than 3 seconds to start and stop, which is unacceptable for my application.  I am using the USB6343 DAQ which has a 500kSample (2us) max sampling rate.  The math works out to 34 samples per channel at the problem setting and somewhere between 25-12,500 samples per channnel at the good settings. Any idea why it is so slow for this one case and not the others?

 

 

private static void StartOutputMonitor(double period /*seconds*/)
{
  m_monitor = new Task();
  m_monitor.AIChannels.CreateVoltageChannel(m_daq.AIPhysicalChannels[0], "monitorCurrent0",
        AITerminalConfiguration.Differential, -10, 10, AIVoltageUnits.Volts);
  m_monitor.AIChannels.CreateVoltageChannel(m_daq.AIPhysicalChannels[1], "monitorImpedance0",
        AITerminalConfiguration.Differential, -10, 10, AIVoltageUnits.Volts);
  var samplingRate = m_daq.AIMaximumMultiChannelRate / m_monitor.AIChannels.Count;
  m_monitor.Timing.ConfigureSampleClock("", samplingRate, SampleClockActiveEdge.Falling,

        SampleQuantityMode.FiniteSamples);
  m_monitor.Timing.SamplesPerChannel = (int) Math.Round(period * samplingRate);
  m_monitor.Control(TaskAction.Verify);
  m_monitor.Start();
  m_monitorReader = new AnalogMultiChannelReader(m_monitor.Stream)
        { SynchronizeCallbacks = false //allow waveform monitoring on a worker thread.};
  m_waveformMonitorData = new double[m_monitor.AIChannels.Count, m_monitor.Timing.SamplesPerChannel];
  m_monitorReader.BeginMemoryOptimizedReadMultiSample((int)m_monitor.Timing.SamplesPerChannel,

        MonitorCallback, m_monitor, m_waveformMonitorData);
}

0 Kudos
Message 1 of 6
(2,928 Views)

In order to clarify whether this is a problem with the device or the software, I would recommend using one of the shipping examples for analog inputs and test the device for the problem parameter of 7500Hz. Do you see the same behavior in this case?

 

Where to Find Examples for Measurement Studio

0 Kudos
Message 2 of 6
(2,884 Views)

I tried a couple of the examples and I don't see it.  Since my code works fine for me at all but this one setting I am assuming it is an obscure interaction in the driver.  There is a waveform generation task going on independently.  The signal I am monitoring is a current amplifier output that is driven by the generated waveform.

 

Typical parameter values are amplitude = .5, pulsewidth = 40, frequency = 20-10000 (problem at 7500)

 

public static void StartSingleStim(double amplitude /*Volts*/, int frequency /*Herz*/,

  double pulseWidth /*microseconds*/)
{
    StopStim(); //cease all existing stimulation
    var period = 1.0 / frequency; //desired period

    m_stim = new Task();
    m_gate = new Task();
    m_frequency = new Task();

    m_stim.AOChannels.CreateVoltageChannel(m_daq.AOPhysicalChannels[0], "stim0", -MaxOutputVoltage, MaxOutputVoltage, AOVoltageUnits.Volts);
    m_stim.Control(TaskAction.Verify);

    //to minimize timing error we need to make the pulse width an even multiple of the sampling clock time
    var n = (int) Math.Floor(8000 * pulseWidth * 1e-6 / period);
    //determine how many ticks are used to make the pulse width

    //If necessary, decrease the sampling multiple to to stay below the DAQ's maximum sampling rate
    var maxSamplingRate = m_daq.AIMaximumMultiChannelRate;
    n = Math.Min(n, (int) Math.Floor(maxSamplingRate * pulseWidth * 1e-6));

    var tickTime = pulseWidth * 1e-6 / n;
    var samplingRate = 1 / tickTime;

    m_stim.Timing.ConfigureSampleClock("", samplingRate, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples);

    tickTime = 1 / m_stim.Timing.SampleClockRate;
    var periodTicks = (int) Math.Round(period / tickTime);
    period = periodTicks * tickTime; //actual period given hardware limitations

    //DAQ can sometimes shutoff if the number of samples is too small.  This problem is PC dependent, not DAQ dependent.  
    //For frequencies above 4kHz we will define two or three complete periods instead of one to increase the sample count.
    var periodCount = (int) Math.Ceiling(.25e-3 / period);

    var pulseTicks = (int) Math.Round(pulseWidth * 1e-6 / tickTime);

    m_frequency.COChannels.CreatePulseChannelFrequency(m_daq.COPhysicalChannels[3], "stimFreq0", COPulseFrequencyUnits.Hertz,
    COPulseIdleState.Low, 0, (double) frequency / periodCount, 0.5);
    m_frequency.Control(TaskAction.Verify);
    m_frequency.Timing.ConfigureImplicit(SampleQuantityMode.ContinuousSamples, 100);

    var gapTicks = (periodTicks - 2 * pulseTicks) / 2;
    var leftoverTicks = periodTicks - pulseTicks * 2 - gapTicks - 3;
    var waveform = new double[periodTicks * periodCount - leftoverTicks];
    var i = 0;
    for (var cycle = 0; cycle < periodCount; cycle++)
    {
        for (var tick = 0; tick < pulseTicks; tick++)
          waveform[i++] = -amplitude;
        for (var tick = 0; tick < gapTicks; tick++)
          waveform[i++] = 0.0;
        for (var tick = 0; tick < pulseTicks; tick++)
          waveform[i++] = amplitude;
        while (i % periodTicks != 0 && i < waveform.Length)
          waveform[i++] = 0.0;
    }

    var writer = new AnalogSingleChannelWriter(m_stim.Stream);
    writer.WriteMultiSample(false, waveform);

    m_stim.Timing.SampleQuantityMode = SampleQuantityMode.FiniteSamples;
    m_stim.Timing.SamplesPerChannel = waveform.Length;
    m_stim.Triggers.StartTrigger.Type = StartTriggerType.DigitalEdge;
    m_stim.Triggers.StartTrigger.Retriggerable = true;
    m_stim.Triggers.StartTrigger.DigitalEdge.Edge = DigitalEdgeStartTriggerEdge.Rising;
    m_stim.Triggers.StartTrigger.DigitalEdge.Source = "/" + m_frequency.COChannels[0].PhysicalName + "InternalOutput";

    m_stim.Control(TaskAction.Verify);
    m_stim.Start();
    m_frequency.Start();
    StartOutputMonitor(period);
}

0 Kudos
Message 3 of 6
(2,881 Views)

Would it make a difference to commit the task to start and commit to stop? Perhaps allocating memory to the task will help.

0 Kudos
Message 4 of 6
(2,865 Views)

What seems to happen is that the commit takes about 2/3 of the time and the remaining third is taken by the start, but overall it is the same length of time to start the task.  As far as using commit to stop, that is not allowed while the task is running.

0 Kudos
Message 5 of 6
(2,856 Views)
Solution
Accepted by topic author drury

I found a workaround!  We have known that if the output buffer is too small the stimulation can arbitrarily shutoff.  I increased my minimum output buffer size from 250ms worth of samples to 330 ms worth of samples and everything works fine.  So, the problems with the analog input seems to have been some sort of bizarre interaction with the monitoring and whatever bugginess h happens when the output buffer is too small.

Message 6 of 6
(2,852 Views)