12-31-2013 04:21 PM
Hi everyone. My first question in this community:
I am interfacing PCI 6259 + BNC2110 with QT Creator IDE (based on C++).
I am trying to sample signal using external triggering. I have a running microprocessor that produces trigger signals.
DAQmxCfgChangeDetectionTiming seems like a good approach. I configured it to sample at the falling edge of my signal that is hooked to port0/line0. Thus, DAQmxRegisterSignalEvent initiates callback in which I perform sampling.
The problem is that I wish to have two or more callbacks that would react on DAQmxRegisterSignalEvent. Currently, I need to have two virt. channels - port0/line0 and port0/line1. The change in one of them should call it's own callback. The theoretical approach would look like:
void main()
{
...
DAQmxCreateDIChan(task1,"Dev1/port0/line0","",DAQmx_Val_ChanPerLine);
DAQmxCfgChangeDetectionTiming(task1,NULL,"Dev1/port0/line0",DAQmx_Val_HWTimedSinglePoint,1);
DAQmxRegisterSignalEvent(task1,DAQmx_Val_ChangeDetectionEvent,0,signal_from_line0_callback,null);
...
DAQmxCreateDIChan(task2,"Dev1/port0/line1","",DAQmx_Val_ChanPerLine);
DAQmxCfgChangeDetectionTiming(task2,NULL,"Dev1/port0/line1",DAQmx_Val_HWTimedSinglePoint,1);
DAQmxRegisterSignalEvent(task2,DAQmx_Val_ChangeDetectionEvent,0,signal_from_line1_callback,null);
...
}
void signal_from_line0_callback()
{
...take a sample;
return;
}
void signal_from_line1_callback()
{
...do other things;
return;
}
However, this schema does not work. It seems like when a change occurs on line0 or line1, the DAQmxRegisterSignalEvent does not care on which line the change was, and thus, tries to call one of the callbacks.
Is there a way to make this approach to work? How to find out which of the lines the change occured on? I need changes in line0 or line1 to trigger different callback functions.
Thank you very much in advance.
01-02-2014 11:48 AM - edited 01-02-2014 11:48 AM
You shouldn't be able to run more than one change detection timing task on your 6259. I'm surprised at the behavior you are describing--I would expect the 2nd task you try to start to return an error stating resources are reserved (but there isn't any error handling in your example so maybe it is going unnoticed) and then only one of the task's change detection events would be registered.
Anyway, you don't need to use a software callback to sample an input based on your external signal. You can configure an input task that uses the external sample clock directly using DAQmxCfgSampClkTiming. If you want the event in software as well you could use DAQmxRegisterEveryNSamplesEvent along with this task. So doing this, you could configure your analog input task to sample off of the external clock (and generate a software event if desired) as well as configure your change detection task to generate a software event based on a different external signal.
Best Regards,
01-02-2014 01:11 PM
John,
Thank you for your advice. You were right - there is an error registered and the callback is allways the same.
I dont see the sampleclocktiming as the best option at this moment. I need two different control inputs. Let's say that I can use only one collback for EventRegister for port0/line0:1. Is there a way to know on which of the lines the change occured, so I could use an IF statement in the callback function to do one thing or another?
01-02-2014 01:18 PM - edited 01-02-2014 01:19 PM
You could call DAQmxRead when handling the event--assuming the lines are normally high you can look for which line has toggled low.
Or, you could configure dummy sample-clocked tasks with subsystems you aren't using (e.g. the two counters) and register a unique sample clock event for each task. This wouldn't scale as well to multiple channels though.
Best Regards,
01-02-2014 02:39 PM
Good idea. Reading the digital channel and see which line is high or low will probably work in general. However, I need to sample data at around 1MHz. So spending time on IF statements or reading digital lines might slow down my sampling frequency. I was wondernig if the event register could pass such information to the callback. What's the signalID?
01-02-2014 03:10 PM
If I am understanding correclty, a quick test with just a single channel should confirm that this software event-driven approach isn't feasible at 1 MHz.
If you really want to sample an input at 1 MHz, you'll need to use a sample clock and generate a software event every N samples (you'll have to investigate to determine a sustainable value for N) and read back N samples at a time in your event handler. This way, the sampling frequency is exactly 1 MHz (within the accuracy spec of the oscillator on the DAQ card anyway) and doesn't depend on non-deterministic software timing at all. The software event handler can run at a more reasonable rate that allows enough time for the DAQmx Read call to execute--non-determinism isn't a problem as long as the allocated read buffer is large enough to accomodate any delays.
Software has no way of determining which line caused the change detection event to fire without actually monitoring the status of the lines themselves. The hardware signal that generates the interrupt is a result of the OR of the enabled change detectors (see here).
The signalID is how you specify which type of hardware event you are looking for. For example, if you want to use the change detection event: signalID = DAQmx_Val_ChangeDetectionEvent.
Best Regards,
01-02-2014 04:43 PM
John,
I am driving a linear ccd array with a microprocessor. The timing for ccd sampling is not 100% periodic, so if I use NI internal clock, I will not be able to sample the data at the right moment. So, I need the DAQ to sample the data according to the microprocessor TTL signals (the idea of trigerred sampling by falling edge sounded good for me). At the same time, I need to sample 1051 samples for each line. So, after collecting 1051 samples I need another trigger to reset to a new line and update the image (wanted to use line0 and line1 to trigger smpling and reset respectively).
Could you, please, suggest how to use external clock and 'TriggerEventAfterNsamples'?
01-02-2014 04:50 PM
That's perfectly fine, you can connect the external TTL signal to a PFI line and use it as the sample clock (can specify rising or falling edge).
I'm not sure I understand the need for the "trigger to reset to a new line". Couldn't you just read back the data in multiples of 1051 samples, and each block of data would correspond to some integer number of lines?
Best Regards,
01-02-2014 05:30 PM
Exactly,
I need to sample in multiples of 1051. So, after I collected those 1051 samples, I need to call myFunction() which will restart the Task to sample another 1051 samples and will update the image.
I just don't know how to properly set up the task:
DAQmxCreateTask("",&samplHandle);
DAQmxCreateAIVoltageChan(samplHandle,"Dev1/ai0","",DAQmx_Val_RSE,-10.0,10.0,DAQmx_Val_Volts,NULL);
DAQmxReadAnalogF64(samplHandle,1051,10.0,DAQmx_Val_GroupByScanNumber,data,1051,&numRead,NULL);
DAQmxCfgDigEdgeStartTrig(samplHandle,"Dev1/port1/line0",DAQmx_Val_Rising);//will be connected to PFI1/P1.0
But then, after 1051 samples were read, I need some kind of trigger to call myFunction(). How do I know that sampling finished?
The overall scheme is like this:
-- cofigure the task;
-- no reaction/sampling until the Task is started;
-- start Task;
-- the Task collects a sample per rising edge on the PFI1/P1.0. After it collected 1051 samples the Task automatically stops, calls myFunction().
-- myFunction() does some magic and starts the Task again to get another 1051 samples.
Could you tell me what I am missing in Task configuration. Also, how to call myFunction upon collection of 1051 samples?
01-02-2014 05:56 PM
Also, every sample has a number at the readout. So I need to make sure that sample1 is a readout1. Then, how would I start the Task other than with trigger?