I am in the process of rewriting some legacy NI-DAQ code to work in NI-DAQmx in VB6 (using NI USB-6212). Basically, I want to acquire a square waveform (2kHz, 50% duty cycle, 11 volts peak-to-peak) and then be to have the USB-6212 reproduce that waveform (at the same 2kHz frequency, etc.). With the new DAQmx code, I successfully acquire the 8000 samples once a 1 volt trigger is met. However, the frequency of the square wave that's reproduced from the previoulsy acquired samples is always different from the frequency received on the input channel. The table below summarizes those differences.
Legacy NI-DAQ had the 'DAQ_Rate" function where you can input a desired rate/frequency and it would set the appropriate timebase and internval. DAQmx does not look like it has an equivalent function. Can some explain to me how correctly set the frequency for a waveform I am trying to have my USB-6212 generate.
For reference, below is my legacy code. It acquires a waveform once triggerred (i.e. 1 volt trigger received on the 'ai1' channel, then 8000 samples at 12000 samples/sec. are acquired on the same channel) then outputs that same previously acquired signal. Note that once all parameters necessary for data acquisition are setup, this process runs in the background waiting for the 1 volt trigger to occur. Below is the legacy code used to configure the trigger and then acquire the waveform.
ReDim dataArray(8000 - 1) As Integer '// Calculate Trigger level for DAQ card Trigger = Trigger * 0.5 Trigger = (Trigger / 5 + 1) * 128 TriggerLev = CLng(Trigger) If TriggerLev > 254 Then TriggerLev = 254 End If '// Reset any existing AI triggering process iStatus = DAQ_Clear(iDevice) '// Configure channel for single-ended, bipolar operation iStatus = AI_Configure(iDevice, Channel, 1, 0, 0, 0) '// Turns on analog triggering and sets to trigger at TriggerLev on the rising edge of the channel being measured iStatus = Configure_HW_Analog_Trigger(iDevice, ND_ON, 0, TriggerLev, ND_ABOVE_HIGH_LEVEL, ND_THE_AI_CHANNEL) '// Routes the signal for triggering iStatus = Select_Signal(iDevice, ND_IN_START_TRIGGER, ND_PFI_0, ND_LOW_TO_HIGH) '// The rate passed in generates the appropriate Timebase and Interval for DAQ_Start iStatus = DAQ_Rate(12000, 0, Timebase, Interval) '// Starts data acquisition with a gain of .5 stored to the full size of DataBuffer array iStatus = DAQ_Start(iDevice, Channel, -1, dataArray(0), UBound(dataArray) + 1, Timebase, Interval)
To achieve the equivalent result in DAQmx, I wrote the following code, which uses event handling (i.e. 'EveryNSamplesEventHandler') to fire an event once the the 1 volt trigger is met and the 8000 samples are received. Below is the DAQmx code used to setup waveform acquisition.
'Create physicalChannel name physicalchannel = DeviceName & "/ai" & Channel ReDim dataBuffer(8000 - 1) As Double DAQmxErrChk (DAQmxCreateTask("", taskhandle)) taskIsRunning = True DAQmxErrChk (DAQmxCreateAIVoltageChan(taskhandle, physicalchannel, "", DAQmx_Val_InputTermCfg_RSE, 0, 10, DAQmx_Val_VoltageUnits2_Volts, vbNullString)) DAQmxErrChk (DAQmxCfgSampClkTiming(taskhandle, "", 12000, DAQmx_Val_Rising, DAQmx_Val_AcquisitionType_ContSamps, Samples)) DAQmxErrChk (DAQmxSetBufInputBufSize(taskhandle, 24000)) DAQmxErrChk (DAQmxGetTaskNumChans(taskhandle, numChannels)) DAQmxErrChk (DAQmxRegisterEveryNSamplesEvent(taskhandle, 1, 8000, 0, AddressOf EveryNSamplesEventHandlerArray, Nothing)) ReDim dataBuffer(numChannels * 8000 - 1) As Double DAQmxErrChk (DAQmxStartTask(taskhandle))
Below is code for the 'EveryNSamplesEventHandlerArray' function referenced in the previous code snippet:
Public Function EveryNSamplesEventHandlerArray(ByVal taskhandle As Long, ByVal eventType As Long, ByVal numSamples As Long, ByVal callbackData As Long) As Long Dim numRead As Long Dim averageVoltage As Double 'Get the number of channels in the task and read DAQmxErrChk (DAQmxGetTaskNumChans(taskhandle, numChannels)) DAQmxErrChk (DAQmxReadAnalogF64(taskhandle, numSamples, 10, DAQmx_Val_GroupByScanNumber, dataBuffer(0), numChannels * numSamples, numRead, ByVal 0)) EveryNSamplesEventHandlerArray = 0 For x = 0 To numSamples - 1 If dataBuffer(x) >= 1 Then oneVoltTriggerReceived = True Exit Function End If Next x oneVoltTriggerReceived = False
Below is the DAQmx code utilized to output the previously acquired waveform.
'Create physicalChannel name physicalchannel = DeviceName & "/ao" & Channel ' Create the DAQmx task. DAQmxErrChk DAQmxCreateTask("", taskhandle) taskIsRunning = True ' Add an analog output channel to the task and check to see whether there is only ONE task. DAQmxErrChk DAQmxCreateAOVoltageChan(taskhandle, physicalchannel, "aoChannel", -10, 10, DAQmx_Val_VoltageUnits2_Volts, "") ' Configure task for continuous waveform generation. DAQmxErrChk DAQmxCfgSampClkTiming(taskhandle, "", 12000, DAQmx_Val_Edge1_Rising, DAQmx_Val_AcquisitionType_ContSamps, 100#) ' Write to the desired channel(s). DAQmxErrChk DAQmxWriteAnalogF64(taskhandle, UBound(DataVolts()) + 1, True, 10#, DAQmx_Val_GroupByScanNumber, DataVolts(0), sampsPerChanWritten, ByVal 0&)
Any help is greatly appreciated. Thanks!!!!