Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

DAQmx Synchronized digital outputs

Solved!
Go to solution

Hey, I'm trying to send two syncronized digital signals from a PCIe-6420 device.

 

Here's my code:

 

// DAQmx Configure Clock
DAQmxErrChk (DAQmxCreateTask("Clk",&taskHandleFRQ));
DAQmxErrChk (DAQmxCreateCOPulseChanFreq(taskHandleFRQ,"Dev1/freqout","",DAQmx_Val_Hz,DAQmx_Val_Low,0,ManchSampClkFreq,0.5));

// DAQmx Configure Digital Output
DAQmxErrChk (DAQmxCreateTask("Harmony",&taskHandleHarmony));
DAQmxErrChk (DAQmxCreateDOChan(taskHandleHarmony,channel2,"",DAQmx_Val_ChanPerLine));
DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandleHarmony,"/Dev1/PFI14",ManchSampClkFreq,DAQmx_Val_Rising,DAQmx_Val_ContSamps,sendCount));

DAQmxErrChk (DAQmxCreateTask("DOchan",&taskHandle));
DAQmxErrChk (DAQmxCreateDOChan(taskHandle,channel,"",DAQmx_Val_ChanPerLine));
DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandle,"/Dev1/PFI14",ManchSampClkFreq,DAQmx_Val_Rising,DAQmx_Val_ContSamps,sendCount));

// DAQmx Configure Analoge Output
//DAQmxErrChk (DAQmxCreateTask("AOchan",&taskHandle));
//DAQmxErrChk (DAQmxCreateAOVoltageChan(taskHandle,channel,"",0.0,10.0,DAQmx_Val_Volts,NULL));
//DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandle,"/Dev1/PFI14",ManchSampClkFreq,DAQmx_Val_Rising,DAQmx_Val_ContSamps,sendCount));

// DAQmx Write Code
DAQmxErrChk (DAQmxWriteDigitalLines(taskHandleHarmony,sendCount,0,10,DAQmx_Val_GroupByChannel,SendManchHarmony,NULL,NULL));
DAQmxErrChk (DAQmxWriteDigitalLines(taskHandle,sendCount,0,10,DAQmx_Val_GroupByChannel,SendManchData,NULL,NULL));
//DAQmxErrChk (DAQmxWriteAnalogF64(taskHandle,sendCount,0,10.0,DAQmx_Val_GroupByChannel,SendManchAnalog,NULL,NULL));

// DAQmx Start Code
DAQmxErrChk (DAQmxStartTask(taskHandleHarmony));
DAQmxErrChk (DAQmxStartTask(taskHandleFRQ));
DAQmxErrChk (DAQmxStartTask(taskHandle));

 

Only trouble is, I keep getting "DAQmx Error: NI Platform Services: The specified resource is reserved." messages.

The Task name associated with the error is DOchan: aka: taskHandle. If I reorder all the code such that the taskHandler events occure before the taskHandlerHarmony equivelents, then the errors are associated with Harmony: aka taskHandleHarmony instead.

 

What am I doing wrong, and how should syncornized digital outputs be implimented instead?

0 Kudos
Message 1 of 5
(3,558 Views)

MrSky,

 

I'll assume that PCIe-6420 was meant to read PCIe-6320.

 

Digital input on X Series devices have a single timing engine/FIFO which feeds all lines.  You have created two digital tasks which will attempt to reserve these resources on their own behalf.  Instead you'll want to add both channels to the same task.  Basically you'd end up with something that looks like this:

// DAQmx Configure Clock
DAQmxErrChk (DAQmxCreateTask("Clk",&taskHandleFRQ));
DAQmxErrChk (DAQmxCreateCOPulseChanFreq(taskHandleFRQ,"Dev1/freqout","",DAQmx_Val_Hz,DAQmx_Val_Low,0,ManchSampClkFreq,0.5));

// DAQmx Configure Digital Output - Add both channels to the same task
DAQmxErrChk (DAQmxCreateTask("DOTask",&taskHandleDOTask));
DAQmxErrChk (DAQmxCreateDOChan(taskHandleDOTask,channel2,"",DAQmx_Val_ChanPerLine));
DAQmxErrChk (DAQmxCreateDOChan(taskHandleDOTask,channel,"",DAQmx_Val_ChanPerLine));
DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandleDOTask,"/Dev1/PFI14",ManchSampClkFreq,DAQmx_Val_Rising,DAQmx_Val_ContSamps,sendCount));

//  Need logic to combine SendManchHarmony and SendManchData

// DAQmx Write Code
DAQmxErrChk (DAQmxWriteDigitalLines(taskHandleDOTask,sendCount,0,10,DAQmx_Val_GroupByChannel,CombinedChannelData,NULL,NULL));

// DAQmx Start Code
DAQmxErrChk (DAQmxStartTask(taskHandleDOTask));
DAQmxErrChk (DAQmxStartTask(taskHandleFRQ));

 

This will prevent two tasks from attempting to reserve the same resources, and will synchronize the two channels.

 

Hope that helps,

Dan

0 Kudos
Message 2 of 5
(3,555 Views)

Thanks for the reply Dan.

 

I did indeed intend to say 'PCIe-6320'. My bad there.

 

While I suspected the device had a single clock, I hadn't realized that the digital inputs were fed by what sounds like a single FIFO data queue.

 

So... how is the data combined? Does data alternate A/B/A/B etc? Does each binary bit in queued data corispond to a different chanel? Are the channels locked into outputing the same signal?

 

I hope channels aren't locked into suppling identical outputs. The data lines I'm tring to ouput are complete perfect inversions of the others.

 

-Sky

0 Kudos
Message 3 of 5
(3,552 Views)
Solution
Accepted by topic author MrSky

Think of the fifo as a block of memory that is the same width as the digital port where each bit corresponds to a single digital line.  Samples are transferred from this FIFO to the port in port-wide writes (though there is some enabling logic, so only lines which are configured in your output task are actually updated each sample clock).  DAQmx will combine the data you write to ensure that the correct port-wide data gets written to the FIFO.  DAQmx does this by looking at the configuration of the 'line grouping' in DAQmx Create DO Channel, and the 'dataLayout' specified to DAQmxWriteDigitalLines function.

You have two lines which you've set to DAQmx_Val_ChanPerLine.  This means that when you call DAQmxWriteDigitalLines, it will expect to see enough data for two channels of data.  The way this data is specified is configured by the dataLayout.  By specifying DAQmx_Val_GroupByChannel, you're telling DAQmx that the the data for each channel should be grouped together.  You should make these groupings in the same order you specify your channels.

So consider the following:

DAQmxErrChk (DAQmxCreateTask("DOTask",&taskHandleDOTask));
DAQmxErrChk (DAQmxCreateDOChan(taskHandleDOTask,"Dev1/port0/line0","",DAQmx_Val_ChanPerLine));
DAQmxErrChk (DAQmxCreateDOChan(taskHandleDOTask,"Dev1/port0/line1","",DAQmx_Val_ChanPerLine));
DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandleDOTask,"/Dev1/PFI14",ManchSampClkFreq,DAQmx_Val_Rising,DAQmx_Val_ContSamps,sendCount));

// Let's alternate digital high/low between our two lines (we'll write 10 values to each line), except for the last point, where we'll write both lines high
// Data needs to be written to the bit position of the corresponding line (if I remember correctly)

// meaning for line 0, you want to manipulate the lsb and for line 1 you manipulate the 2nd lsb.

int32[10] line0Data = {1,0,1,0,1,0,1,0,1,1}

int32[10] line1Data = {0,2,0,2,0,2,0,2,0,2}

int32[20] dataArrayByChannel;

int32[20] dataArrayInterleaved;

 

for(int32 i = 0; i < 10; ++i)

{

   // Group data by channel

   dataArrayByChannel[i] = line0Data[i];

   dataArrayByChanne[i+10] = line1Data[i];

 

   // Group data by scan

   dataArrayInterleaved[2 * i] = line0Data[i];

   dataArrayInterleaved[2 * i + 1] = line1Data[i];

}

 

// We can write data in either of the formats we just built, but we need to provide DAQmx with the correct dataLayout.

DAQmxErrChk (DAQmxWriteDigitalU32(taskHandleDOTask,sendCount,0,10,DAQmx_Val_GroupByScanNumber,dataArrayInterleaved ,NULL,NULL));

 

// Or, we could write by channel.  If we chose to, it would look like this (you would not do both).

DAQmxErrChk (DAQmxWriteDigitalU32(taskHandleDOTask,sendCount,0,10,DAQmx_Val_GroupByChannel,dataArrayByChannel ,NULL,NULL));

 

DAQmxErrChk (DAQmxStartTask(taskHandleDOTask));

 

In either case, DAQmx should write the following data to the FIFO:

x1

x2

x1

x2

x1

x2

x1

x2

x1

x3

 

In this manner the data written for each line is combined by DAQmx before being written to the FIFO.  This allows you to specify data for each channel individually.

 

That was fairly long winded, but hopefully will answer your question.  If I've not been clear, please let me know.

 

Dan

 

Message 4 of 5
(3,543 Views)

Ah, that makes sense.

 

Thanks for the explanation!

0 Kudos
Message 5 of 5
(3,535 Views)