Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

Synchronous continuous AI between 6034 devices in C/C++ with DAQmx

Dear all,

I would like to continuously and synchronously read data from two devices mounted on
two E6034 (6 differential AI channels by device). I use the C API for DAQmx (no Labview or
measurement studio). The RTSI bus is registered with MAX.

My initial idea was to read from the second device simply by extending the list of
channels specified in DAQmxCreateAIVoltageChan. Here is the idea:

DAQmxCreateTask("",&task);
DAQmxCreateAIVoltageChan(task,"Dev1/ai0:5,Dev2/ai0:5","", // physical channels belong to both devices
DAQmx_Val_Diff,minVal,maxVal,DAQmx_Val_Volts,NULL);
DAQmxCfgSampClkTiming(task,"",rate,DAQmx_Val_Rising,DAQmx_Val_ContSamps,sampsPerChan);
DAQmxExportSignal(task,DAQmx_Val_SampleClock,"Dev2/ai/SampleClock"); // to synchronize sample clock ???
DAQmxStartTask(task);

while(!done) {
DAQmxReadAnalogF64(task,DAQmx_Val_Auto,timeout,DAQmx_Val_GroupByScanNumber,
buffer,bufferSize,&sampsPerChanRead,NULL);
// display data in buffer
}

DAQmxStopTask(task); DAQmxClearTask(task);

This works when reading from one device. However, I did not succeed making this
program for reading from both devices. I don't seem to be able to create
virtual channels with DAQmxCreateAIVoltageChan from different devices (if true,
where is this info documented?). Also, I am not sure if exporting the SampleClock
signal with DAQmxExportSignal in this way would work.

From Fig 10 in

http://zone.ni.com/devzone/conceptd.nsf/webmain/2638A8DA4E4CFD1F86256D250070C093

I infer that I need to define TWO tasks. Therefore, the program skeletton should be

DAQmxCreateTask("",&task1);
DAQmxCreateAIVoltageChan(task1,"Dev1/ai0:5","",DAQmx_Val_Diff,minVal,maxVal,DAQmx_Val_Volts,NULL);
DAQmxCfgSampClkTiming(taskHandle,"",rate,DAQmx_Val_Rising,DAQmx_Val_ContSamps,sampsPerChan);

DAQmxCreateTask("",&task2);
DAQmxCreateAIVoltageChan(task1,"Dev2/ai0:5","",DAQmx_Val_Diff,minVal,maxVal,DAQmx_Val_Volts,NULL);
// synchronization is obtained by specifying the
DAQmxCfgSampClkTiming(task2,"/Dev1/ai/SampleClock",rate,DAQmx_Val_Rising,DAQmx_Val_ContSamps,sampsPerChan);

DAQmxStartTask(task1); DAQmxStartTask(task2);

while(!done) {

DAQmxReadAnalogF64(task1,DAQmx_Val_Auto,timeout,DAQmx_Val_GroupByScanNumber,
buffer1,bufferSize,&sampsPerChanRead,NULL);

DAQmxReadAnalogF64(task2,DAQmx_Val_Auto,timeout,DAQmx_Val_GroupByScanNumber,
buffer2,bufferSize,&sampsPerChanRead,NULL);

// display data in buffer1 and buffer2
}

DAQmxStopTask(task1); DAQmxClearTask(task1);
DAQmxStopTask(task2); DAQmxClearTask(task2);

Is it the correct approach? I would much prefer to read all virtual channels in a
single DAQmxReadAnalogF64 call because I would have to manage a single buffer. Here,
it is possible that more data get acquired in the second call.
Is there anyway to make the first approach work?

Thanks,

Gabriel

Message Edited by gavril on 06-07-2005 01:54 PM

0 Kudos
Message 1 of 7
(4,367 Views)
Hi again,

Where can I find an example in C/C++ with DAQmx API to do continuous and synchronous
AI acquisition from two or more E-series devices?

Do I need to define two tasks or would it be possible to configure the task
so that I can read channels from both device with a single call to DAQmxReadAnalogousF64?
How?

Thanks,

Gabriel

PS: See my previous posting for more details.

Message Edited by gavril on 06-08-2005 03:51 AM

0 Kudos
Message 2 of 7
(4,351 Views)
Hi again,

I succeeded synchronizing several 6034E device with DAQmx (6 diff. AI voltage channels
per DAQ). The noteworthy points are:

1) I defined one task per each device
2) I use DAQmxSampClkTiming to use the sample clock "/Dev1/ai/SampleClock/" for all tasks
3) I start only the task associate with the first device (the sample clock signal will
automically start the other tasks).
4) In the loop, I read all available samples for the first device and I use the number of
sample read by this call to read the same number of samples from the other devices. In this
way, I always read the same number of samples from all devices.

I would still appreciate comments on this program (see the skeletton on my program below
and my other posts on the thread).

Regards,

Gabriel

PS: I would suggest to NI to include some additional documentation about multi-device
sync with DAQmx. In particular, I would like to see more explicit info about defining
master and slave tasks operaing on different device (this is implicit when configuring
routes across devices), what happen to the slave task when I start or stop the master
task, how starting and stopping tasks interact with start and stop triggers, etc.
These issues are handled differently with DAQmx than with Traditional NI-DAQ for which
there is more documentation.

DAQmxCreateTask("",&task1);
DAQmxCreateAIVoltageChan(task1,"Dev1/ai0:5","",DAQmx_Val_Diff,minVal,maxVal,DAQmx_Val_Volts,NULL);
DAQmxCfgSampClkTiming(taskHandle,"",rate,DAQmx_Val_Rising,DAQmx_Val_ContSamps,sampsPerChan);

DAQmxCreateTask("",&task2);
DAQmxCreateAIVoltageChan(task1,"Dev2/ai0:5","",DAQmx_Val_Diff,minVal,maxVal,DAQmx_Val_Volts,NULL);
DAQmxCfgSampClkTiming(task2,"/Dev1/ai/SampleClock",rate,DAQmx_Val_Rising,DAQmx_Val_ContSamps,sampsPerChan);

DAQmxStartTask(task1);

while(!done) {

DAQmxReadAnalogF64(task1,DAQmx_Val_Auto,timeout,DAQmx_Val_GroupByScanNumber,
buffer1,bufferSize,&sampsPerChanRead1,NULL);

DAQmxReadAnalogF64(task2,sampsPerChanRead1,timeout,DAQmx_Val_GroupByScanNumber,
buffer2,bufferSize,&sampsPerChanRead2,NULL);

// display data
}

DAQmxStopTask(task1);
0 Kudos
Message 3 of 7
(4,331 Views)
Hi Gabriel,

I'm working on the same issue these days, just that I'm using two PCI-6143 S-series devices.
I think you're right, this topic is not documented well enough. I also couldn't find examples that would fit.

I'm sure about a few things though:

1. You can't access multiple devices in one task, you have to create two different tasks and deal with two buffers. In this case one device is called master and the second one slave.

2. In order to prevent one device from acquiring more samples than the other, you need to synchronize the clocks of the two devices, this is done by telling the slave device that its 20MHz master timebase source and rate will be taken from the master device. This way the clocks are shared through the RTSI bus, which should be properly declared by you in MAX. I currently have a problem implementing this using DAQmx (am I sharing the wrong lines?)

I've done it like this:

char trigName1[256],trigName2[256];
GetTerminalNameWithDevPrefix(hMasterTask,"MasterTimebase",trigName1);
GetTerminalNameWithDevPrefix(hMasterTask,"MasterTimebaseRate",trigName2);
DAQmxSetTimingAttribute(hSlaveTask,DAQmx_MasterTimebase_Src,trigName1);
DAQmxSetTimingAttribute(hSlaveTask,DAQmx_MasterTimebase_Rate,trigName2);

This doesn't work, I get an error that the specified rate is higher than the maximal rate supported.


3. If you want both devices to start reading samples at the same moment, you have to tell the slave device to start acquiring samples upon arrival of the trigger, which is generated by the master device the moment it starts the task.

It's done the following way:

char trigName3[256];
GetTerminalNameWithDevPrefix(hMasterTask,"ai/StartTrigger",trigName3);
DAQmxCfgDigEdgeStartTrig(hSlaveTask,trigName3,DAQmx_Val_Rising);


4. The slave task should be started before the master task, so it won't miss the trigger.



I can run my application at the moment (without clock synchronization), and there's a constant drift (since the clocks of both devices differ a bit).

Any help about implementing clock synchronization in C/C++ using DAQmx would be much apriciated.
Hope I could partially help.

Alex.
0 Kudos
Message 4 of 7
(4,331 Views)
Hi Gabriel,


As I said, you need to start the slave task before the master. It doesn't work if you only start the master task.

Other than that, your code works great and my application works now.


Cheers,

Alex.
0 Kudos
Message 5 of 7
(4,323 Views)
Hi Alex,

For some reason, I did not have to start the slave task before the master task. Starting only the master
task was sufficient. I don't know if it is related to the device (E-series in my case) or it is
because I had started the task before in a previous attempt to run my application while
developping my code in VC (what happen to tasks when you exit from your application if you have
did not explicitely stop them?).

BTW, how do you stop your tasks? In my case, I only stop the master task. It would also be nice
to have some info about what happen to the slave task in this case.

ABout using your previous approach (sharing Master Time Base with a Start Trigger), I found the
some info in NIDAQmx Help/Device Considerations/Synchronization/E-Series. I have not tried only
the second approach (sharing Sample Clock signal).

Regards,

Gabriel

PS: I won't be able to go back on this topic until tomorrow.
0 Kudos
Message 6 of 7
(4,316 Views)
Having problems synchronousing two NI 6534 cards using LW CVI Version8.0. Current scenero is I have using the High speed Digitial i/o. One card is setup to read the buss output and the other is setup to do the writting.  Information is place on the buss 150nano seconds after a read/write command is sent to the unit under test.
 
Could you send me a copy of your code. This might help in my situation. Limited examples for these cards in LW CVI using two cards with RTSI cable connected.
 
THANKS
Ron(Chinook)
0 Kudos
Message 7 of 7
(3,882 Views)