Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

Correctly Setting the 'Rate' Parameter of " DAQmxCfgSampClkTiming' for Signal Acquisition & Subsequent Signal Output

 Hi, 

 

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.

Oscilloscope Output (Sq. Wave).JPG

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!!!!

 

0 Kudos
Message 1 of 1
(2,775 Views)