Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

Timed D-A output from USB-6211

We are trying to use the USB-6211 to generate a analog output from a data buffer. The data is to be output at 8KHz. At the same time an Analog input task in reading data at the same rate. The input task seems to work but there is an error message when attempting to set the data rate for the output. The code setting up the task is:

DAQmxErrChk (DAQmxCreateTask("",&DAStaskHandle));
sprintf_s(devcmd,sizeof(devcmd),"%s/ao1",NI_device);

DAQmxErrChk (DAQmxCreateAOVoltageChan(DAStaskHandle,
    devcmd,    //physical channel
    "",    //name assigned
    -1.0,    //min output value
    1.0,    //max output value
    DAQmx_Val_Volts,    //units of output
    ""    //custom scale name
    ));
DAQmxErrChk (DAQmxCfgSampClkTiming(DAStaskHandle,
    "",    //source (default to OnboardClock)
    SAMPLE_FREQUENCY,    //rate in samples per second
    DAQmx_Val_Rising,    //active edge
    DAQmx_Val_ContSamps,    //Continuous sampling
    ADSampleSize    //samples to aquire
    ));

/*********************************************/
// DAQmx Start Code
/*********************************************/
DAQmxErrChk (DAQmxStartTask(DAStaskHandle));


where the macro DAQmxErrChk is an error check causing a program abort and error message display.
and the error message is:

Non-buffered hardware-timed operations are not supported for this device and Channel Type.

Set the Buffer Size to greater than 0, do not configure Sample Clock timing, or set Sample Timing Type to On Demand.
Task Name: _unnamedTask<3>

Status Code: -201025


If this is not the correct command or the device is not programed this way, How does one send a buffer of on the order of 100000 samples to the D-A at a 8 KHz rate? Is the device limited to only input or output but not both? As the device claims to output at up to 250KHz and buffer upto 8191 samples, it would appear that it has some form of internal clocking to output the samples.
The message says "Set Buffer Size to greater than 0" but there does not seem to be anyplace to do this other than the last argument in DAQmxCfgSampClkTiming and I have tried values from 1000 to 32000 there with the same result.
0 Kudos
Message 1 of 7
(4,106 Views)
It would seem that the sequence for the DA side of the USB-6211 is different from the AD side. The following seqnence worked:

DAQmxCreateTask("",&DAStaskHandle);
DAQmxCreateAOVoltageChan(DAStaskHandle,
    devcmd,    //physical channel
    "",    //name assigned
    -1.0,    //min output value
    1.0,    //max output value
    DAQmx_Val_Volts,    //units of output
    ""    //custom scale name
    );
DAQmxCfgSampClkTiming(DAStaskHandle,
    "",    //source (default to OnboardClock)
    8000,    //rate in samples per second
    DAQmx_Val_Rising,    //active edge
    DAQmx_Val_FiniteSamps,    // sampling mode
    100000       //samples to aquire and buffer size
    );
int32 sampleswritten;
DAQmxWriteAnalogF64(DAStaskHandle,
    100000,    //samples per channel
    1,    //auto start
    20.0,    //timeout in seconds
    DAQmx_Val_GroupByChannel,    //data layout
    soundbuff,    //data to output
    &sampleswritten,    //samples written
    NULL    //reserved
    );
DAQmxWaitUntilTaskDone(DAStaskHandle,-1);
DAQmxStopTask(DAStaskHandle);
DAQmxClearTask(DAStaskHandle);

It is still unclear how one would output very large sequences that could not be buffered in memory. There seems not to be a very clear description of just how things get buffered, by what (the driver or the board?), and what the limitations are. Finding all this out by trial and error is not the best programing practice in the world although it is the Microsoft way.
   
0 Kudos
Message 2 of 7
(4,099 Views)
mhubel,

Even when writting the data out in chunks (not writing the entire output sequence at one time) it is necessary to write the initial chunk to memory before starting the task.  If you don't write the data before starting the task, this implies to the driver that you are trying to do non-buffered output, which is not supported on USB devices.  When you write this first chunk of data to memory it creates an initial buffer to hold the data that you will write later.  It also implicitly configures the driver to do buffered output.  Hence

Configure >> Write >> Start >> Write more

will work, while

Configure >> Start >> Write

will not.

Regards,

Neil S.
0 Kudos
Message 3 of 7
(4,077 Views)
Thanks,
    Thinking about it this makes sense. It  is just that I couldn't find anything anywhere in the documentation of these functions that said this.
    It would be very nice and save a lot of questions like this if there were a meaningful library of basic code examples in all supported languages. TI does this for their processors. Typically there are 5-10 examples for each function showing various combinations of the options. Each example is only 10-50 lines long. They are not always perfect but are effectively wonderful documentation.
0 Kudos
Message 4 of 7
(4,072 Views)
mhubel,

We do provide many useful examples.  For ANSI C these examples are located at:

C:\Documents and Settings\All Users\Documents\National Instruments\NI-DAQ\Examples\DAQmx ANSI C

These examples are based on application (say Finite Acquisition with a Start Trigger or Continuous generation using On-board Regeneration) rather than organized by specific functions.  I agree it would be excellent addition to have examples for each function call (or cross references to the examples that already exist for each function call).  I have wanted this for some time, but as you can imagine, it is a pretty big task.  How would you prefer these examples be included in the help documentation?  As we look for ways to improve our documentation feedback from customers such as yourself is highly valued and I would love to hear any feedback you might have.

Regards,

Neil S.
Product Support Engineer
Multifunction DAQ SW R&D
National Instruments

0 Kudos
Message 5 of 7
(4,067 Views)
Perhaps the best option would be for each function to point to a string of examples of code that use that functon. The important thing is to keep them simple. An example I made for a digital input for our use is:

void DAE(int32 error,int lineno)
{//error capture
if (error)
    printf("\n lind %d DAQmx error \n%d",lineno,error);
}

int _tmain(int argc, _TCHAR* argv[])
{
int ia;

TaskHandle  taskHandle=0;    //NI task
uInt8 data[100];   //a place to put the result
int32 samplesread,bytesPerSamp;    //bytespersamp;
DWORD last_time;   //for timing

for (ia=0;ia<1000;ia++)
    {//sit in loop displaying values read from line 0
    for (last_time=GetTickCount()+1000;last_time>GetTickCount(););    //wait for one second
    DAE(DAQmxCreateTask("",&taskHandle),__LINE__);
    DAE(DAQmxCreateDIChan(taskHandle,"Dev4/port0/line0","",DAQmx_Val_ChanForAllLines),__LINE__);
    DAE(DAQmxStartTask(taskHandle),__LINE__);
    DAE(DAQmxReadDigitalLines(taskHandle,1,10.0,DAQmx_Val_GroupByChannel,data,1,&samplesread,&bytesPerSamp,NULL),__LINE__);
    printf("\n%d phone but %d samp %d bytes %d",ia,data[0],samplesread,bytesPerSamp);
    DAE(DAQmxStopTask(taskHandle),__LINE__);
    DAE(DAQmxClearTask(taskHandle),__LINE__);
    }
}

This illustrates accessing a device, defining the name, getting the value and closing things. You could do one better and show this with multiple lines being read and show another example with only one line using a different function that only allows one line.
If someone is doing this on a regular basis then I would suggest that the functions be more self documented such as:

DAQmxCreateAOVoltageChan(
        DAtaskHandle,   //task handle
        "Dev4/ao0",    //physical channel
        "",    //name assigned
        0.0,    //min output value
        5.0,    //max output value
        DAQmx_Val_Volts,    //units of output
        ""    //custom scale name
        );

It is very import to define everything with actual functional values, no abstract values should be included. For example don't use channel_name, instead use a real channel name "Dev4/ao0". Sometimes one spends rediculus amounts of time finding a legal value for such things when you have no idea what a valid one looks like.

One can then have a link to "examples" at the end of each function where only those examples that are relevant would show. Borland did a very good job of this in their very old version 4.5 compilier but seem to have given up the good work after that.

it would be nice if this message system had a spell checker (I can't find it).

0 Kudos
Message 6 of 7
(4,065 Views)
mhubel,

Thanks for the feedback.  I would really like to see the examples linked from the function help as well.  I will pass the feedback onto our documentation folks.  They are a pretty busy group, but hopefully we will be able to implement these changes in the future.  We do have some examples for ANSI C but we could also use more such as the one you mentioned.  We have one that acquires only a single digital sample, but not one that reads multiple samples in a for loop.  Our example is located at

C:\Documents and Settings\All Users\Documents\National Instruments\NI-DAQ\Examples\DAQmx ANSI C\Digital\Read Values\Read Dig Chan\ReadDigChan.c


I would also like to make a recommendation to improve the performance of your example.  In your example you recreate the task on each loop iteration which will create unnecessary overhead.  I would modify the example to be written in this manner:

DAE(DAQmxCreateTask("",&taskHandle),__LINE__);

DAE(DAQmxCreateDIChan(taskHandle,"Dev4/port0/line0","",DAQmx_Val_ChanForAllLines),__LINE__);
DAE(DAQmxStartTask(taskHandle),__LINE__);
for (ia=0;ia<1000;ia++)
    {//sit in loop displaying values read from line 0
    for (last_time=GetTickCount()+1000;last_time>GetTickCount());    //wait for one second
    DAE(DAQmxReadDigitalLines(taskHandle,1,10.0,DAQmx_Val_GroupByChannel,data,1,&samplesread,&bytesPerSamp,NULL),__LINE__);
    printf("\n%d phone but %d samp %d bytes %d",ia,data[0],samplesread,bytesPerSamp);
    }
}

DAE(DAQmxStopTask(taskHandle),__LINE__);

DAE(DAQmxClearTask(taskHandle),__LINE__);

This way if you reduce your wait it will still perform well.  Also if you remove the wait completely you can achieve maximum performance.

Let me know if you have any further questions.

Thanks,

Neil S.

P.S. I use Firefox that has a built-in spell-checker for forms.  If you right click on a form you can select "Spell Check This Field" and it will highlight misspelled words.  I find it pretty useful.  You can get Firefox from http://www.mozilla.com.
0 Kudos
Message 7 of 7
(4,044 Views)