Digital I/O

cancel
Showing results for 
Search instead for 
Did you mean: 

How do I use clocked digital outputs on an NI-8259 USB card.

I was trying to speed up our digital outputs through the 6259 USB card by using clocked digital outputs using the AO sample clock as a clock source.  The code I am using (see below) is getting a timeout error return from the call to DAQmxWaitUntilTaskDone(). 

Could anybody tell me what I am doing wrong?

I am using LabWindows/CVI version 9.0 with an NI-8259 USB card (Driver Version NI-DAQ 8.7.2) on Windows XP.

 

An example call to the function is:

               O2HwIF_SerialOut( “Dev2/port0/line30”,“Dev2/port0/line31”, 0, 7 );

Here is the code:

static char errorString[200];
static int CheckStatus( int iStatus, int iLine ) { DAQmxGetErrorString( iStatus, errorString, sizeof(errorString) ); return iStatus == 0; }


char *_stdcall O2HwIF_SerialOut( const char *serialChannel, const char *clockChannel, uInt16 data, int iNumBits )
{
   TaskHandle  taskHandleDO, taskHandleAO;
  
   DAQmxCreateTask( "", &taskHandleAO );
   DAQmxCreateTask( "", &taskHandleDO );
   if ( CheckStatus( DAQmxCreateAOVoltageChan( taskHandleAO, "Dev2/ao0", "", 0, 10, DAQmx_Val_Volts, NULL ), __LINE__ ) )
   {
      char combinedChannel[100];
      strcpy( combinedChannel, serialChannel );
      strcat( combinedChannel, "," );
      strcat( combinedChannel, clockChannel );
  
      DAQmxStartTask( taskHandleAO );
  
      if ( CheckStatus( DAQmxCreateDOChan( taskHandleDO, combinedChannel, "", DAQmx_Val_ChanPerLine ), __LINE__ ) )
      {
         uInt8 *buffer = calloc( 2 * iNumBits * 3, 1 );
         uInt16 i;
         int32 written;

         for ( i = 0; i < iNumBits; i++ )
         {
            uInt16 iMask = 1 << (iNumBits-i-1);
            buffer[i*3+0] = buffer[i*3+2] = buffer[i*3+4] = (data & iMask) == 0 ? 0 : 1;   // the data bit
            buffer[i*3+3] = 1;                                                             // the rising edge of the clock
         }
         if ( CheckStatus( DAQmxCfgSampClkTiming( taskHandleDO, "ao/SampleClock", 500, DAQmx_Val_Rising, DAQmx_Val_ContSamps, iNumBits * 3 ), __LINE__ ) )
         {
            if ( CheckStatus( DAQmxWriteDigitalLines( taskHandleDO, iNumBits * 3, 0, 0, DAQmx_Val_GroupByScanNumber, buffer, &written, NULL ), __LINE__ ) )
            {
               if ( written != iNumBits * 3 )
                  sprintf( errorString, "DAQmxWriteDigitalLines() wrote only %d of %d samples", written, iNumBits * 3 );
               else
               {
                  DAQmxStartTask( taskHandleDO );
                  CheckStatus( DAQmxWaitUntilTaskDone( taskHandleDO, 10.0 ), __LINE__ );
                  DAQmxStopTask( taskHandleDO );
               }
            }
         }
         free( buffer );
      }
      DAQmxStopTask( taskHandleAO );
   }

   DAQmxClearTask( taskHandleDO );
   DAQmxClearTask( taskHandleAO );
   return errorString;
}

0 Kudos
Message 1 of 2
(3,153 Views)

Hi Tom 02,

 

It looks like you're configuring your digital task to be continuous:

DAQmxCfgSampClkTiming( taskHandleDO, "ao/SampleClock", 500, DAQmx_Val_Rising, DAQmx_Val_ContSamps,  ...

By definition, a continuous task is never going to be done, so the DAQmxWaitUntilTaskDone should typically only be used for finite tasks.  Also, I don't see where you are configuring your AO sample clock--you'll want to do this so you can use the on-board clock for DO.

 

There is a C Example for correlating Analog Input with Digital Input.  I didn't see a C example for AO/DO, but there is a LabVIEW version.  The steps in the LabVIEW code are as follows:

1.  Create an analog output voltage channel and a digital output channel.

 

2.  Configure both sample clocks to be at the same rate.  The digital task will use the AO Sample Clock.  The LV code has the digital set to continuous but you can change this to finite if you'd like.

 

3.  Write the digital waveform information using pre-defined data.  If you aren't using the AO you shouldn't need to write to the analog task.

 

4.  Start the two functions.  It's good practice to start the digital task first--this way both tasks will start off of the first edge of the analog output sample clock (it will make it possible to add triggers etc. at a later time if necessary).

 

5.  Wait until the tasks are done.  If the tasks are continuous, you will need to use a loop to check the status of the tasks (you can use the DAQmx Is Task Done function to do so since it is as a non-blocking call).  If the digital task is finite, you can instead call the Wait Until Task Done function for that digital task.

 

6.  After the generation has been completed, clear both tasks.

 

Another option for a clock source would be one of the on-board counters of the 6289.  

 

I hope this helps you out, if you run into any problems don't hesitate to let us know.

 

 

-John

Message Edited by John P on 11-12-2009 09:49 AM
John Passiak
0 Kudos
Message 2 of 2
(3,142 Views)