11-16-2022 10:41 AM
Working with the PXIe-6361 Multifunction I/O DAQ card, I am trying to generate a number of digital waveforms one after the other using the NI-DAQmx .net libraries in visual studio.
At the moment I am able to do this but its terribly inefficient in its current state as it takes on average 15ms every time the task is executed.
The flow of the task is as follows. Create the Task, set up the digital output and timers, creating the digital multichannel writer, and setting up the async callbacks. Then I call BeginWriteWaveform and once the task has been completed I dispose of the task.
I have tried creating the task and the writers and then reusing them but unfortunately I do not seem to be seeing anything on the output yet I do not see any errors or exceptions generated in the code. Is there a way of improving the speed from 15ms down to the hundreds microseconds as the project it is being used on requires such speeds.
11-16-2022 10:54 AM
What you do is called software-timed IO, which means the execution speed is determined by the software. As you realized, it is inefficient because a lot of things go on the driver layers to get the data from your code to the hardware and to the front end.
To speed things up, you can use Hardware-timed IO where you pass on a larger waveform (array of data) to the driver and the hardware will start generating those data at a defined speed (sampling clock).
A more detailed description of your application and some sample code of how you do stuff will help us guide you better.
11-16-2022 11:09 AM
Although it is software-timed, I would have thought that I could initialise the task and the writer with a finite sample length and it should allow me to send another set of data using the same task. If this was the case the code would be very fast as the majority of the 15ms is actually caused by disposing the task.
See really rough functions below. These are the functions derived from example code produced by NI.
public void InitialiseTask()
{
var lines = "NiDaq/port0/line0:1";
var sampleCount = 80;
try
{
digitalStreamTask = new NiTask();
digitalStreamTask.DOChannels.CreateChannel(lines, "DigitalOutputTask", ChannelLineGrouping.OneChannelForEachLine);
digitalStreamTask.Timing.ConfigureSampleClock(string.Empty, 1000000, SampleClockActiveEdge.Rising, SampleQuantityMode.FiniteSamples, sampleCount);
digitalStreamTask.Control(TaskAction.Verify);
digitalStreamRunningTask = digitalStreamTask;
multiWriter = new DigitalMultiChannelWriter(digitalStreamTask.Stream);
digitalStreamTask.SynchronizeCallbacks = true;
digitalCallback = new AsyncCallback(DigitalWaveformsCallback);
}
catch (Exception ex)
{
digitalStreamRunningTask = null;
digitalStreamTask.Dispose();
_logger.Error(ex.Message);
throw ex;
}
}
public void SendData()
{
multiWriter.BeginWriteWaveform(true, waveforms, digitalCallback, digitalStreamTask);
}
private void DigitalWaveformsCallback(IAsyncResult ar)
{
try
{
if (digitalStreamRunningTask != null && digitalStreamRunningTask == ar.AsyncState)
{
// End async write operation
multiWriter?.EndWrite(ar);
// Set up new callback
multiWriter?.BeginWriteWaveform(false, waveforms, digitalCallback, digitalStreamTask);
}
}
catch (DaqException ex)
{
digitalStreamRunningTask = null;
digitalStreamTask?.Dispose();
_logger.Error(ex.Message);
throw ex;
}
}