Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

coordinating waveform generation with analog input

I want to use an AO channel to generate a waveform, for instance a sine wave.  There is a nice example provided in the docs that shows this. 

 

I want to be able to synchronize the analog input on an input channel to the waveform generation.  In other words, I want to be able to get the code to act like there is a trigger - when the generation next reaches the start of the buffer, I want the analog input to start, acquire its alloted number of readings, and then stop.   I need to be able to do this repeatedly - while the waveform generation continues, from time to time I need to be able to start a data acquisition, have the data acq wait until the start of the buffer, and then run.

 

I assume there is a smart way to do this, but I have not found it.

 

The thread "Single-shot waveform and 2 concurrent voltage measurement without hardware trigger " has a similar idea using master/slave tasks, but I need continuous generation and randomly initiated measurement. This thread seems to require the slave task (acquisition) to be started before the master task (generation), which I don't think would work for me.  

 

I'm using NIDAQmx, VB6 and a USB-6212 but am likely to use other hardware as well.

 

Thanks,

 

Van

0 Kudos
Message 1 of 8
(4,181 Views)

Hi Van,

 

As long as you are performing these tasks  on the same card, the measurements will be correlated because they all share a common timebase.  What you will have to do is create your AO task to run continuously then create a retriggerable AI task.  To create a retriggerable AI task, you will have to create a retriggerable finite pulse train output from your counters then use this as the sample clock for your AI task.  You can just run the AO task seperately.

Regards,
Jim Schwartz
0 Kudos
Message 2 of 8
(4,154 Views)

Thanks Jim.  Is there any sample code for this kind of application?  I've not used a sample clock before. 

One thing I still don't understand in your descrption - what "triggers" the retriggerable pulse train such that AI starts at the right time (phase) relative to the AO?

Van

0 Kudos
Message 3 of 8
(4,137 Views)

Hi Van,

 

When do you want to take your acquisition?  From your description, it sounds like you want your AO to run continuously then take a finite  AI acquisition multiple times throughout the program.  When do you want to trigger the AI?  There are no specific examples that do what you want, but you can take a look at the VB6 examples that are attached.  If you just want to perform AI and AO at the same time, you can just combine the AI and AO examples, then perform some post processing.  To create a retriggerable AI task, you will have to:

 

1. Create a continuous AI task

2. Set your AI task to use an external clock

3. Create a retriggerable finite pulse train

4. Use the finite pulse train as the sample clock for the AI task.

 

The example below will show you how to set up a retriggerable finite pulse generation:

Retriggerable Finite PulseTrain Generation with Measurement Studio for Visual Basic

Regards,
Jim Schwartz
0 Kudos
Message 4 of 8
(4,113 Views)

Hi Jim,

 

I hope you are still around to continue this thread... It's been a while.

A short reminder of what I'm trying to do:
  1. Generate a waveform continuously using one of the AO. 
  2. At the same time, record a voltage at the same rate as the waveform is being generated.
  3. At random times, I need to record and use the AI data, at other times I can just ignore it.    
  4. I'm using VB6 and am using the native NIDAQmx C API.  
What I believe I need to do, based your feedback and samples I could find is:
  1. Create a retriggerable finite pulse train.  The frequency is the frequency of the waveform generation and analog input.
  2. Create a continuous AI task.
  3. Create a continuous AO task.
  4. Set the AI task and the AO task to use the finite pulse train as the sample clock using DAQmxCfgSampClkTiming.  They are both therefore synchronized. This also sets the buffer size to N.
  5. Set the AI callback function in DAQmxRegisterEveryNSamplesEvent
  6. Write the waveform data to the AO buffer. 
  7. Start the AO task.
  8. Start the AI task. 
  9. When N samples are taken the callback should be called and I can use the data or discard it. 
Unfortunately, I am stuck.  My code compiles and runs without error, but the Callback event never happens.  Here is the essential part of the code. (Device Name is KPDAQ).  Can you see what I'm missing?
' initialize some variables 
   Dim RFPTchan$, freq#, duty#, initDelay#, numSamples&
   RFPTchan = "KPDAQ/ctr0": freq = 10000#: duty = 0.5: initDelay = 0#: numSamples = 1000
  
' set up the retriggerable finite pulse train
   DAQmxErrChk (DAQmxCreateTask("", tsk_Ctr0))
   DAQmxErrChk (DAQmxCreateCOPulseChanFreq(tsk_Ctr0, RFPTchan, "", DAQmx_Val_Hz,
            DAQmx_Val_High, initDelay, freq, duty))
   DAQmxErrChk (DAQmxCfgImplicitTiming(tsk_Ctr0, DAQmx_Val_ContSamps, numSamples))
   DAQmxErrChk (DAQmxSetStartTrigRetriggerable(tsk_Ctr0, True))
  
   RFPTchan = "/KPDAQ/Ctr0InternalOutput"

' set up the AO task
   DAQmxErrChk (DAQmxCreateTask("", AOtaskHandle))
   DAQmxErrChk (DAQmxCreateAOVoltageChan(AOtaskHandle, "/" + DevName + "/ao0", "", -10#, _
             10#, DAQmx_Val_Volts, ""))
   DAQmxErrChk (DAQmxCfgSampClkTiming(AOtaskHandle, RFPTchan, freq, _
             DAQmx_Val_Rising, DAQmx_Val_AcquisitionType_ContSamps, numSamples ))
  
' set up the AI task
   DAQmxErrChk (DAQmxCreateTask("", AItaskHandle))
   DAQmxErrChk (DAQmxCreateAIVoltageChan(AItaskHandle, "/" + DevName + "/ai0", "", _
             DAQmx_Val_Cfg_Default, -10#, 10#, DAQmx_Val_Volts, ""))
   DAQmxErrChk (DAQmxCfgSampClkTiming(AItaskHandle, RFPTchan, freq, DAQmx_Val_Rising, _
             DAQmx_Val_AcquisitionType_ContSamps,  numSamples))
           
' register callbacks
   DAQmxErrChk (DAQmxRegisterEveryNSamplesEvent(AItaskHandle, _
             DAQmx_Val_Acquired_Into_Buffer, numSamples, 0, AddressOf EveryNCallback, _
             ByVal 0&))
   DAQmxErrChk (DAQmxRegisterDoneEvent(AItaskHandle, 0, AddressOf DoneCallback, ByVal 0&))
  
' load the AO buffer and write to the card
   Call GenSineWave(1000, 1#, 1# / numSamples , phase, AOData)
   DAQmxErrChk (DAQmxWriteAnalogF64(AOtaskHandle, numSamples , False, 10#, _
             DAQmx_Val_GroupByChannel, AOData(0), 0, ByVal 0&))
 
' Finally, start the AO and then start the AI
   DAQmxErrChk (DAQmxStartTask(AOtaskHandle))
   DAQmxErrChk (DAQmxStartTask(AItaskHandle))
 
Thanks!
Van
0 Kudos
Message 5 of 8
(3,767 Views)

Van,

 

It'll take some time for me to get a good grasp of all the above, but to simplify a bit, are you able to read any of the data that is being used to register the callback? In other words, are the conditions you are using to trigger the callback changing or being set as you expect? Also, have you been able to get simple callbacks to work with functions of this type before? We might want to work on simply to a basic program checking that value or working on a callback before we try to find out the issue in your program as a whole.

 

Timothy

Timothy S.
Senior Technical Support Engineer
0 Kudos
Message 6 of 8
(3,733 Views)

Hi Van,

 

You might be doing this elsewhere in your program, but you haven't included the part where you start the CO Task with DAQmxStartTask(tsk_Ctr0).  This should occur after the AI and AO tasks have started so they are armed and ready to receive the external sample clock.  If you don't start the CO task this would explain why no samples are ever available.

 

Also, while it shouldn't cause any problems, setting the counter output to retriggerable doesn't do anything in this case since the task is not being triggered by anything and is configured to run continuously.  The comment for that section of code is misleading since you are configuring a continuous CO task rather than a retriggerable finite CO task.  Actually, if you're not using the counter for its retriggerable functionality, you could just instead share the AI or AO sample clock directly.

 

 

Best Regards,

John Passiak
0 Kudos
Message 7 of 8
(3,727 Views)

Hi John and Timothy,

 

Thanks for your feedback.  Indeed, I was not starting the task!  However, rather than try to continue down that path using the counter, I've taken your suggestion of not using the counter at all.  I'm not sure why I was told to go down that path, perhaps I had not explained myself well enough, or perhaps the realization that the equivalent functionality could be achieved by just doing continuous AI and then ignoring all the data I don't need, rather than trying to start AI at random times when needing data.

 

At this point, I have removed the counter stuff and seem to have a working demo program that does simultaneous AO and AI, and uses the callbacks to collect the data. 

 

Van

 

0 Kudos
Message 8 of 8
(3,693 Views)