Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

External Trigger USB6210

Hi all,

 

I am trying to do measurements with the NI-DAQ USB6210 using an external trigger source

The main purpose: Sending a trigger signal and aquire X measurements..and that for like 10 000 trigger signals ending up in 10 000 times X measurements. All this is done in Visual Studio using C++.

 To test my system I control a DMD and show bascially black and white patttern. Meaning I show a white pattern, send the trigger signal and do X measurements. Then showing a black pattern, send a trigger signal and do X measurements...and so on. Afterwards taking the average of each X measurements. Therefore I should get as a result like 1,0,1,0,1,0,....and so on. (1 for white pattern, 0 for black pattern). Unfortunately I run somehow out of sync and my result loooks like 1,0,1,0 and after while 0.9,0.1,0.9,0.1.....0.8,0.2,0.8,0.2....and so on.

 

Long story short, here is my piece of code:

 

 

        TaskHandle  taskHandle=0;
	char        chan[256] = "NI_USB6210/ai1";
	float64     min = 0, max = 4.0;
	char        startTrigger[256] = "PFI1";
	int32       numSamplesTotal;
long m_PicNum = 10000; int32 CVICALLBACK EveryNCallback(TaskHandle taskHandle, int32 everyNsamplesEventType, uInt32 nSamples, void *callbackData); int32 CVICALLBACK DoneCallback(TaskHandle taskHandle, int32 status, void *callbackData); //DAQmx Configure Code int32 error = 0; error = DAQmxCreateTask ("", &taskHandle); error = DAQmxCreateAIVoltageChan (taskHandle, chan,"", DAQmx_Val_Cfg_Default, min, max, DAQmx_Val_Volts, NULL); error = DAQmxGetSampClkMaxRate(taskHandle, &maxSampRate); samplingTime = 1e6/maxSampRate; //sampling time in microseconds numSamplesTotal = (int32)(m_PicNum*numSamplesPerImage); //total number of samples to acquire data = new float64[numSamplesTotal]; error = DAQmxSetBufInputBufSize(taskHandle, 2*numSamplesTotal); error = DAQmxCfgSampClkTiming (taskHandle, "", maxSampRate, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, numSamplesTotal); error = DAQmxCfgDigEdgeStartTrig (taskHandle, startTrigger, DAQmx_Val_Rising); error = DAQmxSetStartTrigRetriggerable (taskHandle,1); error = DAQmxRegisterEveryNSamplesEvent (taskHandle, DAQmx_Val_Acquired_Into_Buffer, numSamplesTotal, 0, EveryNCallback, NULL); error = DAQmxRegisterDoneEvent (taskHandle, 0, DoneCallback, NULL); // DAQmx Start Code error = DAQmxStartTask (taskHandle);

 

Using the NI-MAX I can count the trigger signal arriving at PFI1. That´s why I think I might have a software problem.

Any suggestions? Thanks in advance.

0 Kudos
Message 1 of 8
(5,980 Views)

Okay...no suggestions...it's a pity.

 

Anyway, I think I have some assumptions:

 

The USB6210 is not retriggerable, isn't it?

Meaning I only can receive one trigger signal input and then my task starts and runs till the end. And all the other triggers which were send are ignored.

 

And since both clocks are not handshaking (at least at the moment) the synchronisation runs out. I guess.

 

Any comments?

0 Kudos
Message 2 of 8
(5,933 Views)

And also the following functions are not support:

 

DAQmxCreateCOPulseChanFreq (taskHandle, "/NI_USB6210/ctr0", "", DAQmx_Val_Hz, DAQmx_Val_Low,0.0, 200, 0.5);
DAQmxCfgImplicitTiming (taskHandle, DAQmx_Val_FiniteSamps, numSamplesTotal);
DAQmxSetTrigAttribute (taskHandle, DAQmx_StartTrig_Retriggerable, TRUE);

 

Is that correct?

 

 

0 Kudos
Message 3 of 8
(5,926 Views)

Hi ben3000,

 

You are correct that retriggerable tasks are not natively supported on the USB 6210.  You can implement retriggerable tasks on the USB6210 using the architecture described in the following article: http://www.ni.com/tutorial/5382/en/

Message 4 of 8
(5,898 Views)

Sorry, but I have another quesition:

 

Is it then possible to do multiple trigger measurements with this device at all?

I receive a 20kHz trigger signal and at each received trigger signal I would like to do 10 measurements.

Is this too fast?

Do I have to use the regtriggerable and pulse generation functions? (which seemed to have no influence on my program)

 

Thanks in advance for clarifying that for me.

0 Kudos
Message 5 of 8
(5,802 Views)

Yes you may do this using the implementation described in the tutorial that was linked above:

 

Application Architecture_mod.jpg

 

The counter output is retriggerable, generating 10 pusles per trigger.  The analog input is continuous.

 

 

Best Regards,

John Passiak
0 Kudos
Message 6 of 8
(5,787 Views)

We finally managed to make it run.

Here is the piece of code we used...this may help some others.

TaskHandle	anaTask = 0;
TaskHandle	digTask = 0;

float64 min = 0, max = 4.0;

char  anaInput[50] = "NI_USB6210/ai1";
char  triggerSource[50] = "/NI_USB6210/PFI0";
char	counterSource[50] = "/NI_USB6210/Ctr0InternalOutput";	//AI Sample Clock
char	counterChannel[50] = "/NI_USB6210/ctr0";				//Counter used to Generate Pulses


DAQmxCreateTask("anaTask", &anaTask);
DAQmxCreateTask("digTask", &digTask);

DAQmxCreateAIVoltageChan(anaTask, anaInput, "analogInput", DAQmx_Val_Diff, min, max, DAQmx_Val_Volts, NULL);
DAQmxGetSampClkMaxRate(anaTask, &maxSampRate);

DAQmxCfgSampClkTiming(anaTask,counterSource,maxSampRate, DAQmx_Val_Rising, DAQmx_Val_ContSamps,numSamplesPerTrigger);
DAQmxCfgInputBuffer(anaTask,numSamplesTotal);

DAQmxCreateCOPulseChanFreq (digTask, counterChannel, "coChannel", DAQmx_Val_Hz, DAQmx_Val_Low, 0, maxSampRate,0.5);
DAQmxCfgImplicitTiming(digTask, DAQmx_Val_FiniteSamps, numSamplesPerTrigger);

DAQmxCfgDigEdgeStartTrig(digTask, triggerSource, DAQmx_Val_Rising);
DAQmxSetTrigAttribute(digTask, DAQmx_StartTrig_Retriggerable, TRUE);

DAQmxStartTask(anaTask);
DAQmxStartTask(digTask);

/*
here: code to start your triggering device
*/

DAQmxReadAnalogF64(anaTask, numSamplesTotal, 10, DAQmx_Val_GroupByScanNumber, data, numSamplesTotal, &read, NULL);

DAQmxStopTask(digTask);
DAQmxStopTask(anaTask);
Message 7 of 8
(5,741 Views)

This was very useful for me. I just wanted to add an extension for anybody who might need it, because it seems to be very poorly documented.

 

The 'Arm Start' Trigger is used to start a set of acquisitions that are triggered separately. In the case of the retriggered acquisition from the code above, using an arm start trigger would only begin acquiring once the arm start trigger fires, even if the 'start' trigger fires before it. A diagram might help. Imagine you have two digital triggers and an analog signal to acquire from:

Trigger A – occurs once to signal the beginning of the acquisition process (arm start)

Trigger B – occurs repeatedly, to commence each fixed-length analog acquisition (start, retriggerable in this case)

Analog signal – a fixed length spectrum generated each time trigger B fires

 

Here is an example timeline for the triggers and desired acquisition: (| indicates a trigger occurred, X indicates acquisition occurring)

Trigger A   --------------|-----------------------------------

Trigger B   |----|----|----|----|----|----|----|----|----|---- ...

Acquisition ----------------XXX--XXX--XXX--XXX--XXX--XXX--XXX- ...

 

Although the functions are effectively undocumented, implementing the arm start trigger in code is simple. In the above code, right before starting the tasks, just add the following:

 

char armStartTriggerSource[50] = "/NI_USB6210/PFI2";

DAQmxSetArmStartTrigType(digTask, DAQmx_Val_DigEdge);
DAQmxSetDigEdgeArmStartTrigEdge(digTask, DAQmx_Val_Rising);
DAQmxSetDigEdgeArmStartTrigSrc(digTask, armStartTriggerSource);

The code will now wait for the arm start trigger to fire before beginning retriggered acquisition.

 

NOTE: In the M-series (which includes the 6210), it is not possible to use a FALLING edge for the arm start trigger. So the second function call is superfluous and any other parameter will fail with the error -89133: "Specified inversion cannot be satisfied" (when starting the task).

 

Hopefully this will help somebody else from wasting several weeks like I had to.

 

Message 8 of 8
(4,148 Views)