Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

Unable to Output to Multiple Analog Channels

Solved!
Go to solution

Hi all,

 

I am using NIDAQmx to send signals that control the movement of a scanner in the X and Y axis, with the code being written in C++. The issue I am running into happens when I attempt to send more than one analog output signal.

 

What I have found is that only the first analog output channel specified will have samples written to it. In the following example:

    ////////    ANALOG X AXIS
    // Create analog task
    DAQmxCreateTask("", &aoHandle);
    // Create analog channel
    DAQmxCreateAOVoltageChan(aoHandle, "Dev1/ao0", "", -10.0, 10.0, DAQmx_Val_Volts, NULL);
    // Configure analog timing
    DAQmxCfgSampClkTiming(aoHandle, "", ANALOG_FREQ, DAQmx_Val_Rising, DAQmx_Val_ContSamps, 1000);
    // Analog write
    DAQmxWriteAnalogF64(aoHandle, ((COpulse_width + deadTime) * 2), 0, 10.0, DAQmx_Val_GroupByChannel, analogData, NULL, NULL);

    ////////    ANALOG Y AXIS
    // Create analog task
    DAQmxCreateTask("", &aoHandleY);
    // Create analog channel
    DAQmxCreateAOVoltageChan(aoHandleY, "/Dev1/ao1", "", -10.0, 10.0, DAQmx_Val_Volts, NULL);
    // Configure analog timing
    DAQmxCfgSampClkTiming(aoHandleY, "", ANALOG_FREQ, DAQmx_Val_Rising, DAQmx_Val_ContSamps, ((COpulse_width + deadTime) * volHeight * 2));
    // Analog write
    DAQmxWriteAnalogF64(aoHandleY, ((COpulse_width + deadTime) * volHeight * 2), 0, 10.0, DAQmx_Val_GroupByChannel, analogDataY, NULL, NULL);

only the "ao0" channel will have samples written to it.

 

If I cut and paste the Y Axis section so that it is before the X Axis, then only the "ao1" channel has samples written to it. If I try to specify both channels in the same task and comment out the other (for example, I only use the X axis section but set the parameter in CreateAOVoltageChan to "Dev1/ao0, Dev1/ao1"), then neither channel has samples written to it.

 

For context, the reason I am using two tasks here is that the shape of the waveform in the Y axis is dependent on 'volHeight,' which is set by the user.

 

I'm not sure if the issue maybe has something to do with there being multiple tasks or if the number of samples being written is too high. Any help or suggestions would be greatly appreciated!

 

- Morgan

0 Kudos
Message 1 of 6
(1,501 Views)

Well, you didn't mention what device you are using and most analog output devices do not support multiple tasks per device (probably all of them except for the CompactRIO with DAQmx).

 

https://knowledge.ni.com/KnowledgeArticleDetails?id=kA00Z0000019KWYSA2&l=en-US

 

https://www.ni.com/en-us/support/documentation/supplemental/18/number-of-concurrent-tasks-on-a-compa...

 

Even on a CompactDAQ chassis with multiple Analog Output modules you'd need to group them in a single tasks, and I doubt 

I suspect the reason only one task has samples written to it is because you are not "catching" the error on the other task (which is probably related to a reserved resource or something similar). I believe you should troubleshoot why using a single task is not working since that's likely what you'll need to do, but let's start getting the info about the hw you are using.

Camilo V.
National Instruments
Message 2 of 6
(1,468 Views)

Hi Camilo,

 

I think you are correct in that the issue is that the device does not support more than one analog output task. The device I am using is an NI DAQ 777643-01 for use with PXIe-6124.

 

It seems like the solution then is to combine them into one task, but I am running into two issues that I am hoping you might be able to help with:

  1. When I comment out the other task and specify a list of channels in the CreateAOVoltageChan function (and write the same float64 samples to both), neither channel outputs a signal:
    // Create analog task
    DAQmxCreateTask("", &aoHandle);
    // Create analog channel
    DAQmxCreateAOVoltageChan(aoHandle, "Dev1/ao0, Dev1/ao1", "", -10.0, 10.0, DAQmx_Val_Volts,        NULL);
    // Configure analog timing
    DAQmxCfgSampClkTiming(aoHandle, "", ANALOG_FREQ, DAQmx_Val_Rising,  DAQmx_Val_ContSamps, 1000);
    // Analog write
    DAQmxWriteAnalogF64(aoHandle, ((COpulse_width + deadTime) * 2), 0, 10.0, DAQmx_Val_GroupByChannel, analogData, NULL, NULL);​
  2. The samples for each channel need to be different. Essentially, they are both triangle waveforms with the same amplitudes but different length periods.

And thanks for taking a look at this

0 Kudos
Message 3 of 6
(1,462 Views)
Solution
Accepted by topic author morgmorgan

Confirmed. The 6124 can only handle a single analog output task, but it CAN be multi-channel.

 

  1. When I comment out the other task and specify a list of channels in the CreateAOVoltageChan function (and write the same float64 samples to both), neither channel outputs a signal:
    // Create analog task
    DAQmxCreateTask("", &aoHandle);
    // Create analog channel
    DAQmxCreateAOVoltageChan(aoHandle, "Dev1/ao0, Dev1/ao1", "", -10.0, 10.0, DAQmx_Val_Volts,        NULL);
    // Configure analog timing
    DAQmxCfgSampClkTiming(aoHandle, "", ANALOG_FREQ, DAQmx_Val_Rising,  DAQmx_Val_ContSamps, 1000);
    // Analog write
    DAQmxWriteAnalogF64(aoHandle, ((COpulse_width + deadTime) * 2), 0, 10.0, DAQmx_Val_GroupByChannel, analogData, NULL, NULL);​

There is probably an error, but you are not checking for errors, so information about it will not be displayed. Look at how the DAQmxErrChk macro is implemented in the DAQmx examples in C:\Users\Public\Documents\National Instruments\NI-DAQ\Examples\DAQmx ANSI C\Analog Out\Generate Voltage and do the same in your program to check if the write or other functions are returning errors. Check Error Handling in the link below for details.

 

https://www.ni.com/en-us/support/documentation/supplemental/07/transition-from-traditional-ni-daq--l...

 

Errors generally provide clues about how to fix the problem, so let's start with that and see if you are indeed getting an error.

 

Also, I have no idea how the analogData array is defined. I am not much of a text based programmer (more of a HW person) but I believe that with the function dataLayout set to DAQmx_Val_GroupByChannel, you need to provide a 1D array with concatenated data for the channels. See the not-interleaved case in the link below.

 

https://zone.ni.com/reference/en-XX/help/370466AH-01/mxcncpts/interleaving/

 

As long as you provide the data in the right format and the function is not returning an error, the program should work.

 

2. The samples for each channel need to be different. Essentially, they are both triangle waveforms with the same amplitudes but different length periods.


There are a few ways you could pull this trick. Because the channels are in the same task, the sample rate and number of samples in the buffer will be the same (arguable, I know, but high-level, that's how it is). The easiest method is probably setting up a buffer with a just large enough amount of samples to hold integer cycles of both waveforms.

 

For example, say waveform 1 is a 100 Hz triangle and waveform 2 is 60 Hz. The minimum amount needed for an integer number of cycles in both is 50 ms, meaning 5 cycles for waveform 1 and 3 cycles for waveform 2, which at 1000 S/s would be 50 samples in the buffer. Any integer multiple of that would work. Do you think this would work? Do the waveforms need to change in frequency on the fly?

Camilo V.
National Instruments
Message 4 of 6
(1,446 Views)

That worked!

 

It looks like the reason no samples were being written to either channel was because of the sample size arguments. I was able to send the different waveforms by having the first half of the data array contain channel 1's samples, and the second half contain channel 2's samples.

   analogData = new float64[analogSampLen * 2]; 

// Create analog task
    DAQmxErrChk(DAQmxCreateTask("", &aoHandle));
    // Create analog channel
    DAQmxErrChk(DAQmxCreateAOVoltageChan(aoHandle, "Dev1/ao0:1", "", -5.0, 5.0, DAQmx_Val_Volts, NULL));
    // Configure analog timing
    DAQmxErrChk(DAQmxCfgSampClkTiming(aoHandle, "", ANALOG_FREQ, DAQmx_Val_Rising, DAQmx_Val_ContSamps, analogSampLen));
    // Analog write
    DAQmxErrChk(DAQmxWriteAnalogF64(aoHandle, analogSampLen, 0, 10.0, DAQmx_Val_GroupByChannel, analogData, NULL, NULL));

After setting the 'samples to write' argument in the last two functions to half of the array, they wrote properly.

 

Thank you for your feedback!

0 Kudos
Message 5 of 6
(1,433 Views)

Glad it helped! 🙂

Camilo V.
National Instruments
0 Kudos
Message 6 of 6
(1,421 Views)