Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

Are there any optimizations I can make to speed up writing data to DAQ?

Hello friends,

 

I need to be able to generate analog & digital waveforms, create & configure a task, and write the generated waveforms to a cDAQ within 165ms. I am using the WriteMultiSample(bool autoStart, double[,] data) function for analog output. I am using the WriteWaveform(bool autoStart, DigitalWaveform[] data) function for digital output. I am finding that these write functions typically take around 150ms to execute (measured using the System.Stopwatch class). This is making it difficult for me to meet the 165ms requirement.

 

How might I improve the performance of writing data?

 

0 Kudos
Message 1 of 5
(2,271 Views)

HI b!tmaster,

 

Are you ever specifying the sample clock rate or any other timing properties for your analog or digital output tasks? If so, how have you set up your timing properties?

 

Adena L.
Technical Support Engineer
National Instruments
0 Kudos
Message 2 of 5
(2,232 Views)

Also, what hardware are you using?

Adena L.
Technical Support Engineer
National Instruments
0 Kudos
Message 3 of 5
(2,231 Views)

Hey Adena,

 

I'll answer your second question first. The device I am using is a cDAQ-9174 with an analog output NI 9263 module and a NI 9401 digital I/O module.

 

As for your first question, I specify the sample clock rate and other timing properties when I create the NI tasks before I write any data to them. The following code includes the timing properties for my analog output task.

public void Configure()
{
    if (_task != null)
    {
        _task.Dispose();
        _task = null;
    }

    _task = new Task("AnalogOutputTask");
    _task.AOChannels.CreateVoltageChannel(_hardwareInfo.AnalogOutputModuleName + "/ao0", "ao0", -10, 10, AOVoltageUnits.Volts);
    _task.AOChannels.CreateVoltageChannel(_hardwareInfo.AnalogOutputModuleName + "/ao1", "ao1", -10, 10, AOVoltageUnits.Volts);
    _task.Timing.ConfigureSampleClock("", _hardwareInfo.AnalogOutputSamplingRate, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples, AnalogOutputSamples.GetLength(1));
    _task.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger("/" + _hardwareInfo.SecondDigitalIoModuleName + "/PFI0", DigitalEdgeStartTriggerEdge.Rising);
    _task.Control(TaskAction.Verify);
    _writer = new AnalogMultiChannelWriter(_task.Stream);
    _writer.WriteMultiSample(false, AnalogOutputSamples);
}

The following code includes the timing properties for my digital output task.

public void Configure()
{
    if (_task != null)
    {
        _task.Dispose();
        _task = null;
    }

    _task = new Task("DigitalOutputTask");
    _task.DOChannels.CreateChannel(_hardwareInfo.FirstDigitalIoModuleName + "/port0/line1", "do1", ChannelLineGrouping.OneChannelForEachLine);
    _task.DOChannels.CreateChannel(_hardwareInfo.FirstDigitalIoModuleName + "/port0/line2", "do2", ChannelLineGrouping.OneChannelForEachLine);
    _task.DOChannels.CreateChannel(_hardwareInfo.FirstDigitalIoModuleName + "/port0/line3", "do3", ChannelLineGrouping.OneChannelForEachLine);
    _task.DOChannels.CreateChannel(_hardwareInfo.FirstDigitalIoModuleName + "/port0/line4", "do4", ChannelLineGrouping.OneChannelForEachLine);
    _task.DOChannels.CreateChannel(_hardwareInfo.FirstDigitalIoModuleName + "/port0/line5", "do5", ChannelLineGrouping.OneChannelForEachLine);
    _task.DOChannels.CreateChannel(_hardwareInfo.FirstDigitalIoModuleName + "/port0/line6", "do6", ChannelLineGrouping.OneChannelForEachLine);
    _task.Timing.ConfigureSampleClock("/" + _hardwareInfo.DeviceName + "/ao/SampleClock", _hardwareInfo.AnalogOutputSamplingRate,
        SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples, DigitalWaveforms[0].Samples.Count);
    _task.Control(TaskAction.Verify);
    _writer = new DigitalMultiChannelWriter(_task.Stream);
    _task.Control(TaskAction.Reserve);
    _writer.WriteWaveform(false, DigitalWaveforms);
}

I am going to run some timing analysis and will follow up with the results.

0 Kudos
Message 4 of 5
(2,226 Views)

Alright my timing analysis is complete and I would like to share the results. I decided to whip up 2 sample applications that isolate and execute the Config functions provided in my previous reply. I took some timing measurements by modifying each Config function and utilizing the system stopwatch. I broke the measurement into 2 independent parts to get any idea of how long it is taking to configure a task and how long it is taking the write functions to complete. Below is what the analog output Config function looked like after adding the stopwatch.

 

public void Configure()
{
    var configStopwatch = new Stopwatch();
    configStopwatch.Start();

    if (_task != null)
    {
        _task.Dispose();
        _task = null;
    }

    _task = new Task("AnalogOutputTask");
    _task.AOChannels.CreateVoltageChannel(_hardwareInfo.AnalogOutputModuleName + "/ao0", "ao0", -10, 10, AOVoltageUnits.Volts);
    _task.AOChannels.CreateVoltageChannel(_hardwareInfo.AnalogOutputModuleName + "/ao1", "ao1", -10, 10, AOVoltageUnits.Volts);
    _task.Timing.ConfigureSampleClock("", _hardwareInfo.AnalogOutputSamplingRate, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples, AnalogOutputSamples.GetLength(1));
    _task.Triggers.StartTrigger.ConfigureDigitalEdgeTrigger("/" + _hardwareInfo.SecondDigitalIoModuleName + "/PFI0", DigitalEdgeStartTriggerEdge.Rising);
    _task.Control(TaskAction.Verify);
    _writer = new AnalogMultiChannelWriter(_task.Stream);
    configStopwatch.Stop();

    var writeStopwatch = new Stopwatch();
    writeStopwatch.Start();
    _writer.WriteMultiSample(false, AnalogOutputSamples);
    writeStopwatch.Stop();

    Debug.WriteLine(configStopwatch.ElapsedMilliseconds + "\t" + writeStopwatch.ElapsedMilliseconds);
}

It should be noted that AnalogOutputSamples was a 2 dimensional array of doubles where its first dimension is 2 (to represent to analog output channels) and its second dimension is 7000 samples in length. Below is what the digital output Config function looked like after adding the stopwatch. It should be noted that DigitalWaveforms was a single dimensional array of 6 DigitalWaveform objects, each with 7000 samples in them for the timing analysis.

 

 

public void Configure()
{
    var configStopwatch = new Stopwatch();
    configStopwatch.Start();

    if (_task != null)
    {
        _task.Dispose();
        _task = null;
    }

    _task = new Task("DigitalOutputTask");
    _task.DOChannels.CreateChannel(_hardwareInfo.FirstDigitalIoModuleName + "/port0/line1", "do1", ChannelLineGrouping.OneChannelForEachLine);
    _task.DOChannels.CreateChannel(_hardwareInfo.FirstDigitalIoModuleName + "/port0/line2", "do2", ChannelLineGrouping.OneChannelForEachLine);
    _task.DOChannels.CreateChannel(_hardwareInfo.FirstDigitalIoModuleName + "/port0/line3", "do3", ChannelLineGrouping.OneChannelForEachLine);
    _task.DOChannels.CreateChannel(_hardwareInfo.FirstDigitalIoModuleName + "/port0/line4", "do4", ChannelLineGrouping.OneChannelForEachLine);
    _task.DOChannels.CreateChannel(_hardwareInfo.FirstDigitalIoModuleName + "/port0/line5", "do5", ChannelLineGrouping.OneChannelForEachLine);
    _task.DOChannels.CreateChannel(_hardwareInfo.FirstDigitalIoModuleName + "/port0/line6", "do6", ChannelLineGrouping.OneChannelForEachLine);
    _task.Timing.ConfigureSampleClock("/" + _hardwareInfo.DeviceName + "/ao/SampleClock", _hardwareInfo.AnalogOutputSamplingRate,
        SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples, DigitalWaveforms[0].Samples.Count);
    _task.Control(TaskAction.Verify);
    _writer = new DigitalMultiChannelWriter(_task.Stream);
    _task.Control(TaskAction.Reserve);
    configStopwatch.Stop();

    var writeStopwatch = new Stopwatch();
    writeStopwatch.Start();
    _writer.WriteWaveform(false, DigitalWaveforms);
    writeStopwatch.Stop();

    Debug.WriteLine(configStopwatch.ElapsedMilliseconds + "\t" + writeStopwatch.ElapsedMilliseconds);
}

 

Below are my timing analysis results.

IsoStopwatchAnalysis.png

To summarize these results...

  • The average time it took to dispose of my analog output task and reconfigure it was approximately 48.9 ms
  • The average time it took me to write a [2, 7000] array to the analog output channels was approximately 85.1 ms
  • The average time it took to dispose of my digital output task and reconfigure it was approximately 58 ms
  • The average time it took me to write a [6, 7000] array to the digital output channels was approximately 62.4 ms

I hope these findings provide some insight into anything I may be doing wrong or anything I can do to improve the performance of this code.

0 Kudos
Message 5 of 5
(2,220 Views)