11-29-2011 07:53 PM - edited 11-29-2011 07:55 PM
Hi,
I am a newbie in working with DAQmx system, and need some help on multiple-device USB DAQ synchronization. The goal is to start collection on two USB M-Series DAQ card, and we use C codes (via DAQmx ANSI C library) to achieve this. I have been reading and following some guides from NI resources: "Synchronizing Multiple DAQ Devices" (http://www.ni.com/dataacquisition/videos.htm), as well as some example code on the NI dev zone: "NI-DAQmx: Simultaneous AI/AO in CVI" (http://zone.ni.com/devzone/cda/epd/p/id/879).
My understanding is as follows:
1. Set the first card as the master, and export the signal 'StartTrigger', and 'SampleClock' to PFI1 and PFI2 (the physical pin).
2. Connect physically with wire pin PFI1 and PFI2 (sources) in master card to the pin PFI0 and PFI1 (destination) in the slave card.
3. Configure the slave task to use digital edge start trigger using PFI0, and configure the sample clock of the slave task to use the source clock from the exported signal of master task, at PFI1 (slave pin).
So far the result is not working. The error still indicates as if the physical connection is not recognized (I have not found yet a way to verify if the signal exported successful or not).
I attached the routing table snapshot for the card created in the MAX, and the snippet code I used.
Any help is welcome. Thank you!
Solved! Go to Solution.
11-29-2011 08:48 PM
To add on, another possible closest instruction I found is available at this link, https://decibel.ni.com/content/docs/DOC-3864, but this is in LabVIEW VI code.
12-01-2011 03:41 AM
Giving this a bump, in case anyone can help. Or am I in the wrong forum board, and should post this in software (LabWindows/CVI) forum ? as I know this also concerns the 'how' part on connecting on the physical part -- PFI0 and PFI1 between two cards ? Thanks.
12-01-2011 02:12 PM - edited 12-01-2011 02:14 PM
Hi kusg,
DAQmx doesn't know that some of the PFI terminals on your two devices are connected together, and you can't tell it that they are connected because DAQmx only supports inter-device connections for RTSI cables and PXI chassis, not PFI terminals. So exporting signals from Dev1's task to Dev2's PFI terminals is not going to work.
However, you can export signals from Dev1's task to Dev1's PFI terminals. Try doing that instead, and the error should go away (assuming it's error -89124 like I think it is).
Also, when using PFIs, I recommend committing the master task before starting the slave task, so that starting the master task doesn't generate any unwanted digital edges:
DAQmxTaskControl(masterTask, DAQmx_Val_Commit);
DAQmxStartTask(slaveTask);
DAQmxStartTask(masterTask);
Brad
12-13-2011 03:37 AM
Hi Brad,
Thanks for the reply. Sorry for the late reply. It took me a while to get back the two cards setup.
I got the idea that it would be possible to export the (internal) signal --- (sample clock or start trigger) within the same board to the pin (PFI). I wonder if I should use these command to do that:
DAQmxSetExportedSampClkOutputTerm(taskHandle,"/Dev1/PFI0");
or
DAQmxExportSignal(taskHandle,DAQmx_Val_SampleClock,"/Dev1/PFI0"));
The latter gave me error, while the first one is not. Both it appeared do not work to me. At least how I tested was as follows:
TaskHandle taskHandle=0;
DAQmxErrChk (DAQmxCreateTask("",&taskHandle));
DAQmxErrChk (DAQmxCreateCOPulseChanFreq(taskHandle,"Dev1/ctr0","",DAQmx_Val_Hz,DAQmx_Val_Low,0.0,1.0,0.5));
DAQmxErrChk (DAQmxCfgDigEdgeStartTrig(taskHandle,"/Dev1/PFI0",DAQmx_Val_Rising));
DAQmxErrChk (DAQmxCfgImplicitTiming(taskHandle,DAQmx_Val_ContSamps,1000));
DAQmxSetExportedSampClkOutputTerm(taskHandle, "/Dev1/PFI0");
DAQmxErrChk (DAQmxRegisterDoneEvent(taskHandle,0,DoneCallback,NULL));
printf("Generating pulse train.\n");
TaskHandle taskHandle2=0;
DAQmxErrChk (DAQmxCreateTask("",&taskHandle2));
DAQmxErrChk (DAQmxCreateAIVoltageChan(taskHandle2,"Dev2/ai0","",DAQmx_Val_Cfg_Default,-10.0,10.0,DAQmx_Val_Volts,NULL));
DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandle2, "/Dev2/PFI1",10000.0,DAQmx_Val_Rising,DAQmx_Val_ContSamps,1000));
DAQmxErrChk (DAQmxRegisterEveryNSamplesEvent(taskHandle2,DAQmx_Val_Acquired_Into_Buffer,1000,0,EveryNCallback,NULL));
DAQmxErrChk (DAQmxRegisterDoneEvent(taskHandle2,0,DoneCallback,NULL));
DAQmxErrChk (DAQmxStartTask(taskHandle2));// start the slave card
DAQmxErrChk (DAQmxStartTask(taskHandle));// start the master card
printf("Acquiring samples continuously. Press Enter to interrupt\n");
getchar();
Here I wired the PFI0 from Dev1, to the PFI1 in the Dev2. No error but it does not seem to work.
I'll appreciate it if you have any hints or suggestion. Thanks.
12-13-2011 03:43 AM
Ok, I missed out the DAQmxErrChk on the DAQmxSetExportedSampClkOutputTerm command.. It turned out there is an error : -200452. So both I have errors (using DAQmxSetExportedSampClkOutputTerm or DAQmxExportSignal).
12-13-2011 04:16 AM
Hi Brad,
I got some result -- perhaps the previous example test code was not correct to check if the exported signals work. Below code now looks working for me (with my setup):
int main()
{
TaskHandle taskHandle=0;
TaskHandle taskHandle2=0;
DAQmxErrChk (DAQmxCreateTask("",&taskHandle));
DAQmxErrChk (DAQmxCreateAIVoltageChan(taskHandle,"Dev1/ai0","",DAQmx_Val_Cfg_Default,-10.0,10.0,DAQmx_Val_Volts,NULL));
DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandle, "",10000.0,DAQmx_Val_Rising,DAQmx_Val_ContSamps,1000));
DAQmxErrChk (DAQmxExportSignal (taskHandle, DAQmx_Val_SampleClock, "/Dev1/PFI1"));
DAQmxErrChk (DAQmxCreateTask("",&taskHandle2));
DAQmxErrChk (DAQmxCreateAIVoltageChan(taskHandle2,"Dev2/ai0","",DAQmx_Val_Cfg_Default,-10.0,10.0,DAQmx_Val_Volts,NULL));
DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandle2, "/Dev2/PFI0",10000.0,DAQmx_Val_Rising,DAQmx_Val_ContSamps,1000));
DAQmxErrChk (DAQmxRegisterEveryNSamplesEvent(taskHandle2,DAQmx_Val_Acquired_Into_Buffer,1000,0,EveryNCallback,NULL));
DAQmxErrChk (DAQmxRegisterDoneEvent(taskHandle2,0,DoneCallback,NULL));
DAQmxErrChk (DAQmxStartTask(taskHandle2));
DAQmxErrChk (DAQmxStartTask(taskHandle));
printf("Acquiring samples continuously. Press Enter to interrupt\n");
getchar();
return 0;
}
It is also working if I tried to export the start trigger signal instead of the sample clock -- Next I will try to combine both start trigger and the sample clock .. (need another wire connection), and let you know the result. Hopefully you do not find anything wrong with the above codes.
Thanks.
12-14-2011 03:18 AM - edited 12-14-2011 03:19 AM
12-14-2011 03:18 AM
Just a closure on the initial question I posted -- I have tested the two cards using the previous post code, and it seems to work -- both reading looks syncrhonized from the two cards.. but I have to read sequentially, and not using Val_Auto option .. I guess this would be the hard part on my changing code to do software 'synchronization'..
12-14-2011 01:40 PM
Hi kusg,
Glad to hear you got it working.
Here's the problem with the code in message 5:
DAQmxErrChk (DAQmxCfgDigEdgeStartTrig(taskHandle,"/Dev1/PFI0", DAQmx_Val_Rising));
DAQmxSetExportedSampClkOutputTerm(taskHandle, "/Dev1/PFI0");
Exporting the start trigger to the same pin from which you are importing the start trigger is unlikely to do what you want. Also, the counter output task does not support exporting its sample clock.
Then in message 7 you changed it to this:
DAQmxErrChk (DAQmxExportSignal (taskHandle, DAQmx_Val_SampleClock, "/Dev1/PFI1"));
DAQmxErrChk (DAQmxCfgSampClkTiming(taskHandle2, "/Dev2/PFI0",10000.0,DAQmx_Val_Rising,DAQmx_Val_ContSamps,1000));
This version works because taskHandle and taskHandle2 are both AI tasks, which support exporting the sample clock, and you're not using the same PFI terminal for two things at the same time.
> both reading looks syncrhonized from the two cards.. but I have to read sequentially, and not using Val_Auto option .. I guess this would be the hard part on my changing code to do software 'synchronization'..
That's right, you shouldn't use DAQmx_Val_Auto in this case. Passing DAQmx_Val_Auto for the numSampsPerChan parameter of DAQmxReadAnalogF64() causes it to read any samples that are available in the buffer. Even though your tasks are synchronized, your program calls DAQmxReadAnalogF64() at a different time for each task, so there is a different number of samples in the buffer each time you read.
Brad