12-29-2016 10:50 AM
Hello,
I must be missing something very basic, but I've been lost for hours...
I'm trying to send a Current flash of 10 mA during 5 ms, sent by a C software.
The issue is that the card seems to be stuck at the first value (10 mA) and never to go down to 0 mA.
My code is the following.
Any clue? Thanks so much!
int32 error = 0; TaskHandle taskOutput = 0; float64 waveform[1000]; char errBuff[2048] = { '\0' }; int i = 0; // set-up the waveform buffer to 10 mA for the first miliseconds and then 0. for (; i < 5 ; i++) waveform[i] = 0.01; for (; i < 1000; i++) waveform[i] = 0.; DAQmxErrChk(DAQmxCreateTask("Current flash", &taskOutput)); DAQmxErrChk(DAQmxCreateAOCurrentChan(taskOutput, "/cDAQ2Mod2/ao2", "IR_flash", 0.0, 0.01, DAQmx_Val_Amps, NULL)); DAQmxErrChk(DAQmxCfgSampClkTiming(taskOutput, NULL, 1000.0, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, 1000)); DAQmxErrChk(DAQmxWriteAnalogF64(taskOutput, 1000, 0, 10.0, DAQmx_Val_GroupByChannel, waveform, NULL, NULL)); DAQmxErrChk(DAQmxRegisterDoneEvent(taskOutput, 0, DoneCallback, NULL)); DAQmxErrChk(DAQmxStartTask(taskOutput));
Solved! Go to Solution.
12-30-2016 09:01 AM
After some try & fail periods, I have some insights...
Apparently, the waveform generation stops when I leave the function, keeping the last value. In my case, I left shortly after my code and Error management, so the value was kept at the original point.
The configuration works if I put a getchar() at the end of the code (not convenient), or if I put a Sleep(1000) or Sleep(100), so that it can finish emitting the samples.
12-30-2016 11:23 AM
Well, you didn't show us the code following the abstract so it's difficult to guess what is happening, but if you have a StopTask or a ClearTask immediately following the code shown, the generation is stopped at that point.
CVI shipping examples like e.g. MultCurrUpdates-IntClk simply exit the start function but the program is not stopped since it remains alive waiting in RunUserInterface () instruction (thus leaving the generation time to terminate), the task being cleared only in DoneCallback (), which you actually have in your code but apparently are not executing at the right point.
GetChar () leaves the program alive until a key press; Sleep (1000) leaves the program time to terminate the whole generation; Sleep (100) just aborts the generation prematurely but since the 5 ms burst has already terminated it seems all is well even if the process is still going on.
12-31-2016 09:35 AM
If I may...
I still have issues with this topic, in fact.
I want to launch the Flashes in threads (so that the "Sleep" do not block the reception of the flash). So the code is the following :
int32 CVICALLBACK DoneCallback(TaskHandle taskHandle, int32 status, void *callbackData) { printf("\ndone\n"); DAQmxClearTask(taskHandle); return 0; } void flash() { int32 error = 0; TaskHandle taskOutput = 0; float64 waveform[1000]; char errBuff[2048] = { '\0' }; int i = 0; // set-up the waveform buffer to 10 mA for the first miliseconds and then 0. for (; i < 5 ; i++) waveform[i] = 0.01; for (; i < 1000; i++) waveform[i] = 0.; DAQmxErrChk(DAQmxCreateTask("Current flash", &taskOutput)); DAQmxErrChk(DAQmxCreateAOCurrentChan(taskOutput, "/cDAQ2Mod2/ao2", "IR_flash", 0.0, 0.01, DAQmx_Val_Amps, NULL)); DAQmxErrChk(DAQmxCfgSampClkTiming(taskOutput, NULL, 1000.0, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, 1000)); DAQmxErrChk(DAQmxWriteAnalogF64(taskOutput, 1000, 0, 10.0, DAQmx_Val_GroupByChannel, waveform, NULL, NULL)); DAQmxErrChk(DAQmxRegisterDoneEvent(taskOutput, 0, DoneCallback, NULL)); DAQmxErrChk(DAQmxStartTask(taskOutput)); Sleep(1010); Error: if (DAQmxFailed(error)) DAQmxGetExtendedErrorInfo(errBuff, 2048); if (taskOutput != 0) { /*********************************************/ // DAQmx Stop Code /*********************************************/ DAQmxStopTask(taskOutput); DAQmxClearTask(taskOutput); } if (DAQmxFailed(error)) printf("DAQmx Error: %s\n", errBuff); } main(){ // create 5 threads flashing once each nbThreads = 0; std::thread process[5]; for (; nbThreads < 5 ; nbThreads ++ ) { process[nbThreads ++] = std::thread(flash); Sleep(2000); }
// at this point, I expected all threads to be finished and self-killed. But it's not the case... }
But the code does not exit cleanly: the "DoneCallback" is never launched (I don't see the printf), and I get an error at the end of "main" :unhandled exception when trying to close the threads , on the "terminate" line of
~thread() _NOEXCEPT { if (joinable()) _XSTD terminate(); } .
So the process of flasing and sleeping does not terminate (I expected the thread to be killed automatically after the Sleep).
What may be the solution? Why don't I launch the DoneCallback function???
Thanks!
12-31-2016 11:13 AM - edited 12-31-2016 11:13 AM
The reason the done callback is not executed lies probably in that the task is cleared before the process is complete.
If I were you I'll get rid of the done callback and instead of the sleep I'd sit in a loop waiting for DAQmxIsTaskDone () function to signal the task is terminated. In the main you should check if all threads are terminated before terminating: you should get no error on exit.
01-01-2017 11:36 AM
Thanks a lot, I think this solution solves my problems!