Measurement Studio for VC++

cancel
Showing results for 
Search instead for 
Did you mean: 

I cannot access my stop button while data aquistion is going on

I have written an application that aquires data from a GPS reciever over a TCP connection and displays it on a graph in "real-time" and it works except that I cannot access my STOP button to stop the connection while it is working. I think I need to do something with multithreading and have done some multithread programming before to do background processing but cannot seem to get a handle on how to make this work. I am sure it must be something qite simple as it seems like something that is quite common. Any help greatly appreciated. My application started life as the Multi XY plot example program from NI.

Thanks
DEan
0 Kudos
Message 1 of 7
(4,197 Views)
Hi Dean:

It appears that this may be more of a Visual C++ question for which I would recommend that you post your question at http://forums.microsoft.com/msdn/

I was wondering if you were acquiring data in a loop and hence not able to control the button located external to the loop. I tried looking for the example program you had mentioned but could not find it. Could you send me the program so I can take a look at it.

Also, please ensure that you are enabling the button that stops data acquisition once the program starts.

Thank you
Nandini Subramaniam
Applications Engineering
0 Kudos
Message 2 of 7
(4,187 Views)
Hello Nandini
Thanks for the reply and the link. You are right, I am aquiring the data in a loop and cannot access the button that is located outside the loop. Can you tell me how to make the button accessibe from within the loop? I can get you code later if necessary.

Cheers,

Dean
0 Kudos
Message 3 of 7
(4,178 Views)
When you create the button in Visual C++, you can right click >> Events and view all the possible events that can be handled by the button. In this way when you are acquiring data in a loop, you can jump to this function when you want to stop acquiring data. As soon as the button is clicked the code inside the ButtonClicked function will begin to execute and you can stop and close data acquisition here.

Thank you

Nandini Subramaniam
Applications Engineering
National Instruments
0 Kudos
Message 4 of 7
(4,177 Views)
While you are in the aqusition loop, none of your windows messages are getting processed. You need to ensure that you either return from the callback fast enough that you allow windows to process messages, or you add a message processing loop as part of your DAQ loop to manually dispatch the messages yourself.

So if you have Measurement Studio, you can the CNiTimer class to fire a callback at specific intervals where you can read the data. Or you can add this standard Win32 message pump to your acquisition loop. You will need to handle error conditions by breaking out of the loop.

MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
//read acquisition data here
}

Another thing you could do is have your acquisition occur in a seperate dedicated worker thread. This way, you won't have to worry about the UI not getting updated and your DAQ operation not slowly down too much. You will need to synchronize how to access any shared data using locks or critical sections.

I hope this helps
Bilal Durrani
NI
0 Kudos
Message 5 of 7
(4,170 Views)
hello Bilal
I think that doing the data aquisition in a separate thread is the right way to do it, I have done this in another application, but I also want to graph it as it is aquired which the other apllication does not do. I have not been able to figure out how to give the aquisition thread access to the CNIGraph control while main thread has access to the rest of the dialog box so I can access the stop button.

Thanks

Dean
0 Kudos
Message 6 of 7
(4,165 Views)
You can pass a reference to the dialog class into your thread and manipulate the graph that way. The following snippet demonstrates one way of doing this using the DAQmx C API

UINT CDAQMTExampleDlg::AcquisitionThread(void* pParam)
{
CDAQMTExampleDlg* pDlg = static_cast < CDAQMTExampleDlg* >(pParam);
double data[1000];
int32 read;
int error;

if( (pParam != NULL) && pDlg->IsKindOf(RUNTIME_CLASS(CDAQMTExampleDlg)))
{
CoInitialize(NULL);
TaskHandle taskHandle = pDlg->taskHandle;
CNiReal64Vector vectorData(1000);
double *pvectorData = (double*)vectorData;

while(!pDlg->stopTask)
{
DAQmxErrChk(DAQmxReadAnalogF64(taskHandle,1000,10.0,DAQmx_Val_GroupByScanNumber,pvectorData,1000,&read,NULL));
pDlg->m_Graph.PlotY(vectorData);
}
Error:

DAQmxStopTask(taskHandle);
DAQmxClearTask(taskHandle);
pDlg->stopTask = true;
CoUninitialize();
}

return 0;
}

void CDAQMTExampleDlg::OnBnClickedButton1()
{
int error;

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(DAQmxStartTask(taskHandle));
stopTask = false;

AfxBeginThread(AcquisitionThread, this);

return;

Error:
char errBuff[2048]={'\0'};
if( DAQmxFailed(error) )
DAQmxGetExtendedErrorInfo(errBuff,2048);
if( taskHandle!=0 ) {
/*********************************************/
/*/ DAQmx Stop Code
/*********************************************/
DAQmxStopTask(taskHandle);
DAQmxClearTask(taskHandle);
}
if( DAQmxFailed(error) )
printf("DAQmx Error: %s\n",errBuff);
}

void CDAQMTExampleDlg::OnBnClickedButton2()
{
stopTask = true;
}


I also wanted to make sure that you know that if you have Measurement Studio 7.x, you have access to a C++ DAQmx API. You can find examples of that API under ..\MeasurementStudio\VCNET\Examples\DAQmx. The C++ API provides asynchronous methods, which means that aquisition worker threads are automatically created for you in the background instead of you having to create them yourself. Plus the C++ DAQmx API provides error handling via exceptions and is designed for use with MFC.

I hope this helps
Bilal Durrani
NI
0 Kudos
Message 7 of 7
(4,143 Views)