Digital I/O

cancel
Showing results for 
Search instead for 
Did you mean: 

Change detection used to read digital Input

Hi,

 

 

Tools used: PCI 6221, C++.

 

 

GOAL : Read the value of digital input inside the callback methode generated by the changeDetection.

 

           1. use a ChangeDetection timing to detect change on a physical input line : ok

              

                     (DAQmxCreateDIChan

                      DAQmxCfgChangeDetectionTiming with DAQmx_Val_ContSamps param)

 

           2. generate a call back method on change detection : ok

                  

                     (DAQmxRegisterSignalEvent with DAQmx_Val_ChangeDetectionEvent param)

 

           3. Read the value of the digital line inside the callback method : NOT OK

 

                     (the use of DAQmxReadDigitalU8 give a timout, of cours, by the fact not other change on digital input are coming).

 

 

Question: How to read the value ? Using the

 

 

Workaround:  I can stop the task inside the call back method, create an other task for reading the digital input, and restart the initial task.     But I could lost some change on DI, and it appear not to be nice...

 

 

 

BR

 

Daniel

 

0 Kudos
Message 1 of 6
(3,792 Views)

Hey Daniel,

 

it would be helpfull to see the code in which you configure the task, the callback method and the callback method it self.

 

Regards, Marcus 

0 Kudos
Message 2 of 6
(3,769 Views)

Hi Marcus,

 

Configuration is done inside a class method:

 

 

//--------------------------------------------------------------------------- int32 DAQmxDI::Configure_ReadDigChan(const char chan[], int arraySize, DAQmxSignalEventCallbackPtr CallbackMethod) { int32 error=0; strcpy(Mychan,chan); MyArraySize = arraySize; /********************************************************************* * 1. Create a task. * 2. Create a Digital Output channel. Use one channel for all lines. *********************************************************************/ AnsiString name = ("my_DI_task" + IntToStr(taskNbr)); DAQmxErrChk (DAQmxCreateTask(name.c_str(),&taskHandle)); DAQmxErrChk (DAQmxCreateDIChan(taskHandle, Mychan, "", DAQmx_Val_ChanPerLine)); DAQmxErrChk(DAQmxCfgChangeDetectionTiming(taskHandle, Mychan, Mychan, DAQmx_Val_ContSamps, 1)); DAQmxErrChk(DAQmxRegisterSignalEvent(taskHandle, DAQmx_Val_ChangeDetectionEvent, 0, CallbackMethod, NULL)); Error: return error; }

 

 

and the call of configuration:

 

DigitalInput = new DAQmxDI(); DAQmxErrChk(DigitalInput->Configure_ReadDigChan("622x/port0/line0",1,EveryChangeCallback));

 

 

The callback method, calling a method of the DAQmxDI object.

 

 

//--------------------------------------------------------------------------- int32 CVICALLBACK EveryChangeCallback (TaskHandle taskHandle, int32 signalID, void *callbackData) //--------------------------------------------------------------------------- { frm_main->readData(); } //--------------------------------------------------------------------------- void __fastcall Tfrm_main::readData() //--------------------------------------------------------------------------- { uInt8 data[1]; DAQmxErrChk(DigitalInput->Read_DigChan(data)); //this call raise a -200284 NI error //workaround: //frm_main->DigitalInput->ReadDigChanOtherTask(data); edt_value0->Text = data[0]; Error: if( DAQmxFailed(error) ) { DAQmxGetExtendedErrorInfo(errBuff,2048); mmo_error->Lines->Add(errBuff); } }

 

 

And finally my workaround method. (getting value by stopped and restarted the initial task):

 

//--------------------------------------------------------------------------- int32 DAQmxDI::ReadDigChanOtherTask(uInt8 data[]) { //we cannot acced directly to the "taskHandle" task, because she is triggered by a change of the signal level. //So we stop this task, create another on same phyisical input, read the value and clear it. After that we can restart the first task. //other way to do that? int32 error=0; int32 read; TaskHandle taskHandleSub; error = DAQmxStopTask(taskHandle); DAQmxErrChk (DAQmxCreateTask("my_DI_subtask",&taskHandleSub)); DAQmxErrChk (DAQmxCreateDIChan(taskHandleSub, Mychan, "", DAQmx_Val_ChanPerLine)); DAQmxErrChk(DAQmxReadDigitalU8(taskHandleSub, 1, 2.0, DAQmx_Val_GroupByChannel, data, MyArraySize, &read, NULL)); error = DAQmxStopTask(taskHandleSub); DAQmxClearTask(taskHandleSub); DAQmxStartTask(taskHandle); Error: return error; }

 

 

 

Regards, Daniel

0 Kudos
Message 3 of 6
(3,766 Views)

Hey Daniel,

 

Thanks for posting the Code and giving a general overview. But for advanced debugging it would be nice to see the whole C file!

 

Regards, Marcus.

0 Kudos
Message 4 of 6
(3,746 Views)

One thing that you might be running into: DMA transfers are handled in 4 byte chunks so if you're just watching the output and not stepping through the code it will look like you miss samples when callbacks are qued up and then rapidly proccessed.

 

Hope this helps,

Andrew S.

0 Kudos
Message 5 of 6
(3,732 Views)

Hi,

 

 

Annexed you will find the whole code. Warning, my compiler is Borland C++Builder 2006, so if you use anoter compiler, just keep the NI622xDi.* unit.

 

 

But I will shortly re-formulate my question:

 

 

When I use the DAQmxCfgChangeDetectionTiming, the consequence is that the task acquire samples on the rising and/or falling edges of the lines.

 

Exemple: signal is 0 and become 1.

 

Task aquire a sample and by the way of the DAQmxRegisterSignalEvent, the Callback Method called.

 

Inside the Callback method, I use the DAQmxReadDigitalU8. But, if the signal is still à 1 and won't change for a while, it is normal that the read fire a timeout, because the task will not acquire an other sample, until the signal go to 0!

 

Am I wrong with these exemple or not? That the first question.

 

If I am not wrong, what is the best practice to read input inside a Callback Method.

 

BR

Daniel

 

 

0 Kudos
Message 6 of 6
(3,724 Views)