简体   繁体   中英

Setting the Frequency for Analog Output using NI DAQMx

I'm trying to ouptput a the waveform contained in a wav file using the NI DAQMx ANSI C library. I'm using the libsnd library to read the wav file and I'm able to extract the data sucessfully, however the frequency of the output waveform is much higher than the actual wav file itself. Does anyone know how the frequency of the output waveform can be set. I'm using the PCIe 6351 Data Acquisition card.

Below is some code I wrote out to do this task:

#include<stdio.h>
#include<conio.h>
#include <math.h>
#include <stdlib.h>
#include <windows.h>
#include "NIDAQmx.h"
#include "Sync_AIAO.h"
#include "sndfile.h"
#include "RIB2.h"


int32 fnCreateTask(TaskHandle *AOTaskHandle)
{
    int32 error=0;
    DAQmxErrChk(DAQmxCreateTask("", AOTaskHandle));
    Error:
    return error;
}






int main(int argc, char** argv)
{
    int i=0;
    int32 error=0;
    TaskHandle  AOtaskHandle = 0;
    float64* AIOSample;
    float *fWavSample;
    SNDFILE *SoundFile;
    SF_INFO SoundFileInfo;  
    int iNoOfSamples=0;
    FILE* fp;
    //Error code
    //Handle to the tasks created
    char        errBuff[2048]={'\0'};


    //DAQmxErrChk(DAQmxCreateTask("",AOtaskHandle));
    fnCreateTask(&AOtaskHandle);

    //Create an analog out channel
    DAQmxErrChk (DAQmxCreateAOVoltageChan(*   (&AOtaskHandle),"Dev1/ao1","",-10.0000000,+10.00000,DAQmx_Val_Volts,NULL));

    //Set for 
  //DAQmxErrChk     (DAQmxCfgDigEdgeStartTrig(&AOtaskHandle,"ai/StartTrigger",DAQmx_Val_Rising));


SoundFile=sf_open("sine.wav", SFM_READ, &SoundFileInfo);

  //Check if file is opened sucessfully
  if (SoundFile == NULL)
  {
    printf("Failed to open the file.\n");
    exit(-1);
  }

  //allocate memory for the buffer that is to hold the wav data:
  fWavSample = new float[SoundFileInfo.channels * SoundFileInfo.frames]; 
  iNoOfSamples = SoundFileInfo.channels * SoundFileInfo.frames;

  //Read data into the float structure
  sf_readf_float(SoundFile, fWavSample, SoundFileInfo.frames);

  printf("Float:%d, Float64:%d\n",sizeof(float),sizeof(float64));

  //printf("%f\n",fWavSample[0]);
  //printf("%f\n",fWavSample[200000]);

  AIOSample = new float64[iNoOfSamples];


 // fopen_s(&fp,"output.dat","w");

  for(i=0;i<SoundFileInfo.channels * SoundFileInfo.frames;i++)
  {
     // fprintf(fp,"Data[%d]:%f\n",i,fWavSample[i]);
      AIOSample[i] = (float64)fWavSample[i];

  }

 // fclose(fp);
  int32 written;


  /*calling function that will output the trigger on PFI6*/

  //fnSrPlayElectric(); //play electric stimulus 
  while(1)
  {
      /*
      DAQmxErrChk(DAQmxWriteAnalogF64(AOtaskHandle,(SoundFileInfo.channels * SoundFileInfo.frames), 
      true, 10.0, DAQmx_Val_GroupByChannel,AIOSample,&written,NULL));
      */

      DAQmxErrChk(DAQmxWriteAnalogF64(AOtaskHandle,1000, 
      true, 10.0, DAQmx_Val_GroupByChannel,AIOSample,&written,NULL));

  //Sleep(3000);
  }





//Display the error to the user here.
Error:
    if( DAQmxFailed(error) )
    {
        DAQmxGetExtendedErrorInfo(errBuff,2048);
        puts(errBuff);
    }




getch();
}

I'd appreciate any help I can get. Thanks!

Atul

Right now, your program is writing samples to the DAQ card one at a time as fast as the process can and you're sending samples in groups of 1000. In DAQmx terms, this is a "software-timed" task, since the OS, scheduler, CPU, and other system dynamics affect how often a sample is written to the card.

Since audio files are sampled at a constant rate, you will also need to program the DAQ card to generate the samples at that same rate . In DAQmx terms, using a sample clock is called a "hardware-timed" task. DAQmx also comes with ANSI C examples for configuring a sample clock [1]. Take a look at "Continuously Generate Voltage - Internal Clock", which probably has an abbreviated name on disk, and how it uses the function DAQmxCfgSampClkTiming [2]. There is also more information on how timing works for DAQmx online [3].

For example, if your audio file is sampled at 44.1 kHz, you'll need to set the sample clock frequency to be the same. Beware however, that the 6351 has a 100 MHz timebase [4] and divides it down by integers to get lower sample clock rates. So for this 44.1 kHz example, the closest frequency you can get is 44.111 kHz (100 MHz / 2267) or 44.091 kHz (100 MHz / 2268). You can check the actual sample rate using DAQmxGetSampClkRate [5] after you configure it -- DAQmx will coerce it to a valid value.

[1] Text Based NI-DAQmx Data Acquisition Examples :: ANSI C
http://www.ni.com/white-paper/6999/en/#ANSIC

[2] NI-DAQmx C Reference Help :: DAQmxCfgSampClkTiming
http://zone.ni.com/reference/en-XX/help/370471W-01/daqmxcfunc/daqmxcfgsampclktiming

[3] Timing, Hardware Versus Software
http://zone.ni.com/reference/en-XX/help/370466V-01/TOC11.htm

[4] X Series User Manual :: Clock Routing (page 183)
http://digital.ni.com/manuals.nsf/websearch/82BB2FBF407E178586257D15006F596C

[5] NI-DAQmx C Reference Help :: DAQmxGetSampClkRate
http://zone.ni.com/reference/en-XX/help/370471W-01/mxcprop/func1344

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM