12-22-2016 11:46 AM
Hello,
I have a project with NI USB-6003 device, where I need to acquire in continues mode Analog Inputs using EveryNSamplesEvent.
I am using Visual C++ ( Visual Studio 2013 ).
The project consists of following attached files:
- Source.cpp -> main function implementation
- IOController.cpp(h) -> declaration and implementation of IOController class
I grabbed the snipped, provided in "Cont Acq-Int Clk" example and copied into Source.cpp.
Using #if macro I branched my code in two parts:
1) NI_Example_Part - this is the code from NI Example, slightly modified to eleminate DoneEvent part.
2) MY_Example_Part - this is my code, which uses the same steps for Acquisition setup as NI_Example_Part. The difference is that I am starting in separate thread a functor object, which will setup and start acquisition.
If USE_IO_CONTROLLER is defined then the compiled code will execute MY_Example_Part, otherwise NI_Example_Part.
NI_Example_Part runs without any problems.
MY_Example_Part is setting properly the task, the channels and EveryNSample event. This part works and I checked it with the debugger. The problem is that on the first event the function DAQmxReadAnalogF64 blocks and never returns, although a time-out has been set( see "everyNCallback" function in IOController.cpp ).
I am puzzled as the implementation is exactrly the same as in NI example, but it does not work.
Could you please help?
Will appreciate any hint.
Best Regards,
Varko
Solved! Go to Solution.
12-27-2016 02:49 PM - edited 12-27-2016 02:50 PM
Hey Varko,
At first glance, I think the issue is probably related to how you are spawning a new thread. The snippet below creates a new thread, "first", that calls the function "foo".
thread first(foo);
In your code, you have a similar line:
thread ioThread(controller);
The difference here is that "controller" is not a function like "foo", it is an object of your IOController class. I'm not sure what happens if you spawn a thread that calls an object rather than a function, but I think that may be causing some issues
I would start by isolating the code that you want to run on the new thread first. Without spawning a new thread for it, are you able to get the code to run? At first glance, everything looked correct in regards to how you were setting up tasks and calling DAQmxReadAnalogF64. If you are able to execute this code separately, then it looks like thread management is the issue.
Likely, it would be more effective for you to spawn a new thread that calls the DAQmxReadAnalogF64. Or you could create your own function that creates the "controller" object of your IOController class and goes through configuring and running your DAQmx tasks. Then spawn a new thread that calls your custom function from your main, rather than spawning a thread that calls an object.
I hope this is helpful!
Regards,
Will
12-27-2016 03:12 PM
Hello Will,
The "contoller" is a functor object and it's operator() will be called on start of the thread.
This works if I use finite mode of sampling, i.e. "DAQmx_Val_FiniteSamps" and it does not with continues mode.
I followed your advice and avoided threading, implemented a separate function to start the controlled and start it instead.
But again it does not help for continues mode, but works with finite mode.
Please see the modified code.
Best regards,
Varko
12-28-2016 08:14 AM
Varko,
Ah, okay. That makes sense. Thanks for trying to isolate the code and see if it helped at all.
Backing up a little bit, you were saying DAQmxReadAnalogF64 "blocks and never returns"? Is it giving you a run-time error of any sort? If so, what's the error? If there is no error, what exactly do you mean by "it blocks"? The execution hangs there and you're forced to quit?
Regards,
Will
12-28-2016 11:08 AM
Hi Will,
The execution hangs at the call of DAQmxReadAnalogF64( "blocks" ) and I am forced to quit.
Regards,
Varko
12-29-2016 11:18 AM
Varko,
Syntactically, your code is correct. You are using the proper functions with the correct paramters to set up and run your tasks. However, the structure is strange. If you look at IOController.cpp, when this gets executed (and we're in continuous mode, so !USE_FINITE_MODE), it doesn't look like the DAQmxReadAnalogF64 ever actually gets called. We configure and start a task, then we eventually get to this code:
#if !USE_FINITE_MODE m_aiController->blockOnTask(); #endif
This only includes a DAQmxWaitUntilDone, but what are we waiting for? We never started reading anything. I think that would explain the "hang".
I hope this helps sort things out!
Regards,
Will
12-29-2016 12:17 PM
Will,
That was a good catch!
My intention was to use DAQmxWaitUntilDone as a blocking call, thinking that the callback will be triggered in parallel.
Obviously missunderstood.
Thank you so much,
Varko
12-30-2016 12:18 PM
Varko,
Happy to help! Glad we got this figured out!
Regards,
Will