Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

USB-6210 on Linux - is DAQmxBaseExportSignal supposed to work for this device?

Solved!
Go to solution

I've got two USB-6210 devices that I need to sync up so that they both gather data at exactly the same time. I'd like to trigger the data gathering for each device by sending a trigger out of Dev1/PFI6 and having both devices receive the trigger on PFI0.

 

The analog trigger input doesn't seem to work, but the digital trigger input seems to be accepted. Unfortunately, I can't seem to get the clock signal to be exported.

 

Here is the sample program I'm using:

 

 

/*********************************************************************
*
* ANSI C Example program:
* contAcquire-ExtClk-DigStart.c
*
* Example Category:
* AI
*
* Description:
* This example demonstrates how to acquire a continuous amount of
* data using an external sample clock, started by a digital edge.
*
* Instructions for Running:
* 1. Select the physical channel to correspond to where your
* signal is input on the DAQ device.
* 2. Enter the minimum and maximum voltage ranges.
* Note: For better accuracy try to match the Input Ranges to the
* expected voltage level of the measured signal.
* 3. Select a source for the sample clock.
* 4. Set the approximate Rate of the external clock. This allows
* the internal characteristics of the acquisition to be as
* efficient as possible. Also set the Samples to Read.
* 5. Select a source for the digital edge start trigger.
* 6. Select the edge, rising or falling, on which to trigger.
*
* Steps:
* 1. Create a task.
* 2. Create an analog input voltage channel.
* 3. Define the parameters for an External Clock Source.
* Additionally, define the sample mode to be continuous. The
* external clock rate is given to allow the internal
* characteristics of the acquisition to be as efficient as
* possible.
* 4. Set the parameters for a digital edge start trigger.
* 5. Call the Start function to start the acquisition.
* 6. Read the waveform data in a loop until 10 seconds or an
* error occurs.
* 7. Call the Clear Task function to clear the Task.
* 8. Display an error if any.
*
* I/O Connections Overview:
* Make sure your signal input terminal matches the Physical
* Channel I/O control. Also, make sure that your digital trigger
* signal is connected to the terminal specified in Trigger Source.
*
* Recommended Use:
* 1. Call Configure and Start functions.
* 2. Call Read function in a loop.
* 3. Call Stop function at the end.
*
*********************************************************************/

#include "NIDAQmxBase.h"
#include <stdio.h>
#include <time.h>
#include <unistd.h>

#define DAQmxErrChk(functionCall) { if( DAQmxFailed(error=(functionCall)) ) { goto Error; } }

int main(void)
{
// Task parameters
int32 error = 0;
TaskHandle AITaskHandle = 0;
char errBuff[2048]={'\0'};
int32 i;
time_t startTime;

// Channel parameters
char chan[] = "Dev1/ai0";
float64 min = -10.0;
float64 max = 10.0;

// Timing parameters
char clockIn[] = "/Dev1/PFI0";
char clockOut[] = "/Dev1/PFI4";
uInt64 samplesPerChan = 1000;
float64 sampleRate = 10000.0;

// Triggering parameters
char triggerIn[] = "/Dev1/PFI2";
char triggerOut[] = "/Dev1/PFI6";
uInt32 triggerSlope = DAQmx_Val_RisingSlope;
uInt32 triggerSamples = 100;

// Data read parameters
#define bufferSize (uInt32)1000
float64 data[bufferSize];
int32 pointsToRead = bufferSize;
int32 pointsRead;
float64 timeout = 10.0;
int32 totalRead = 0;


printf("calling CreateTask - AI...\n");
DAQmxErrChk (DAQmxBaseCreateTask("",&AITaskHandle));
printf("calling CreateAIVoltage - AI...\n");
DAQmxErrChk (DAQmxBaseCreateAIVoltageChan(AITaskHandle,chan,"",DAQmx_Val_Cfg_Default,min,max,DAQmx_Val_Volts,NULL));
//printf("calling CfgSampleClkTiming - AI...\n");
// DAQmxErrChk (DAQmxBaseCfgSampClkTiming(AITaskHandle,clockIn,sampleRate,DAQmx_Val_Rising,DAQmx_Val_ContSamps,1000));
printf("calling CfgSampleClkTiming - AI...\n");
DAQmxErrChk (DAQmxBaseCfgSampClkTiming(AITaskHandle,"OnboardClock",sampleRate,DAQmx_Val_Rising,DAQmx_Val_ContSamps,1000));
printf("calling DigEdgeStartTrig...\n");
DAQmxErrChk (DAQmxBaseCfgDigEdgeStartTrig(AITaskHandle,triggerIn,triggerSlope));
printf("calling ExportSignal - sample clock on %s...\n", clockOut);
DAQmxErrChk (DAQmxBaseExportSignal(AITaskHandle, DAQmx_Val_SampleClock, clockOut));
printf("calling StartTask - AI\n");
DAQmxErrChk (DAQmxBaseStartTask(AITaskHandle));

// The loop will quit after 10 seconds

startTime = time(NULL);
while( time(NULL)<startTime+10 ) {
printf("loop - calling ExportSignal - Trigger...\n");
DAQmxErrChk (DAQmxBaseExportSignal(AITaskHandle, DAQmx_Val_StartTrigger, triggerOut));
printf("loop - calling ReadAnalogF64...\n");
DAQmxErrChk (DAQmxBaseReadAnalogF64(AITaskHandle,pointsToRead,timeout,DAQmx_Val_GroupByChannel,data,bufferSize,&pointsRead,NULL));
totalRead += pointsRead;
printf("Acquired %d samples. Total %d\n",pointsRead,totalRead);
// Just print out the first 10 points of the last data read
for (i = 0; i < 10; ++i)
printf ("data[%d] = %f\n", i, data[i]);

}
printf("\nAcquired %d total samples.\n",totalRead);

Error:
if( DAQmxFailed(error) )
DAQmxBaseGetExtendedErrorInfo(errBuff,2048);
if(AITaskHandle != 0) {
DAQmxBaseStopTask (AITaskHandle);
DAQmxBaseClearTask (AITaskHandle);
}
if( DAQmxFailed(error) )
printf ("DAQmxBase Error %d: %s\n", error, errBuff);
return 0;
}

 

 

 

And here is the result of running the sample program.

 

  $ ./contAcquire-ExtClk-DigStart
  calling CreateTask - AI...
  calling CreateAIVoltage - AI...
  calling CfgSampleClkTiming - AI...
  calling DigEdgeStartTrig...
  calling ExportSignal - sample clock on /Dev1/PFI4...
  DAQmxBase Error -200428: Value passed to the Task/Channels In control is invalid.

 

Can anyone tell me what I'm doing wrong or is ExportSignal not supported for USB-6210 devices on Linux?

 

Thanks,

 

-Tom

 

 

0 Kudos
Message 1 of 11
(5,220 Views)

Hi Tom,

 

Are you using DAQmx Base or DAQmx?

 

DAQmx is not supported on Linux or Mac operating systems.  DAQmx Base is to a lesser extent.  If you can tell the version of DAQmx Base you have, we can cross reference it in the readme file for that version on ni.com/drivers.  Here is the link for the driver download and readme for DAQmx Base 3.4 (SUSE, RedHat).

 

By typing in that error code without the negative sign ("200428") into ni.com, a few knowledgebases crop up which seem to relate to DAQmx Base:

 

NI-DAQmx Base Error -200428

 

Error -200428 Occurred at Unidentified Location When Trying to Use a Task in NI-DAQmx Base

 

Common NI-DAQmx Error Codes and Solutions: Codes -200300 to -200999

 

Furthermore--what version of the driver are you using?  As per the DAQmx Base 3.4 readme, it looks like ExportSignal functionality was added in 2.0.

 

Hope this helps,

Andrew

 

 

National Instruments
0 Kudos
Message 2 of 11
(5,206 Views)

Hello,

 

I'm using NI-DAQmx Base 3.4.0f2 8-June-2010 on CentOS 5. I've been looking through the knowledgebase and I haven't found much help for NI-DAQmx Base. All of the examples seem to be for NI-DAQmx or for Labview vi type programming. The README.txt for this version seems to say that the ExportSignal function works, but I'm having no luck. I've checked out the error message descriptions, but frankly, I don't know how to translate vi centric explanations to C programming.


Can you provide an NI-DAQmx Base example program in C using the DAQmxBaseExportSignal function?

 

Thanks,

 

-Tom

0 Kudos
Message 3 of 11
(5,203 Views)

Hi Tom,

 

I haven't been able to find an example that uses that particular function, but it may be alluding me.  There are examples about how to synchronize multiple devices:

 

...National Instruments\NI-DAQ\Examples\DAQmx ANSI C\Synchronization

 

Are you able to run lsdaq to find the 6210 device properly on your machine?  

 

I'm still not entirely convinced the code is the problem.  I'm not the most knowledgeable about Kernel distros, but I don't believe CentOS is supported.  Searching around the forums for "CentOS" I found other references that it may not be supported.  I did find  a reference to SELinux causing an issue. You also might try the Linux community for more ideas on troubleshooting why your CentOS 5 code yields this error.

 

Hope this helps,

Andrew

National Instruments
0 Kudos
Message 4 of 11
(5,167 Views)

Hi Tom,

The USB M Series devices (621x) are unable to export their signals with DAQmx Base. The devices that have support for this are PCI M Series, E Series and S Series.

From your other recent posts, I gather you're trying to synchronize two USB-6210 devices on Linux. You've been successful in importing an external clock [1], and now you're looking for a way to share clocks. Unfortunately, you won't be able to export the sample clock from one device and send it to the other, but you can use a counter task on one to generate a clock and then use that as a common clock for both devices.

[1] External clock and hw trigger using USB-6210 on Linux with NI-DAQmx Base?
http://forums.ni.com/t5/Multifunction-DAQ/External-clock-and-hw-trigger-using-USB-6210-on-Linux-with...

Joe Friedchicken
NI Configuration Based Software
Get with your fellow OS users
[ Linux ] [ macOS ]
Principal Software Engineer :: Configuration Based Software
Senior Software Engineer :: Multifunction Instruments Applications Group (until May 2018)
Software Engineer :: Measurements RLP Group (until Mar 2014)
Applications Engineer :: High Speed Product Group (until Sep 2008)
0 Kudos
Message 5 of 11
(5,159 Views)

Thank you for the reply. I'll look into your counter suggestion and see if I can figure it out.

 

Thanks again,

 

-Tom

0 Kudos
Message 6 of 11
(5,154 Views)

Well, I've been trying to figure out how to generate a clock and use it to sample channels and I'm still not having positive results. Here's what I've tried:

 

/*********************************************************************
*
* ANSI C Example program:
* acquireNScans-ExtClk.c
*
*********************************************************************/

#include "NIDAQmxBase.h"
#include <stdio.h>

#define DAQmxErrChk(functionCall) { if( DAQmxFailed(error=(functionCall)) ) { goto Error; } }

int main(void)
{
// Task parameters
int32 error = 0;
TaskHandle AITaskHandle = 0;
TaskHandle CounterTaskHandle = 0;
char errBuff[2048]={'\0'};
int32 i;

// Channel parameters
char chan[] = "Dev1/ai0";
float64 min = -10.0;
float64 max = 10.0;

// Timing parameters
char clockSource[] = "Dev1/ctr0";
uInt64 samplesPerChan = 1000;
float64 sampleRate = 10000.0;
float64 delay=0.0;
float64 freq=1.0;
float64 duty=0.5;

// Data read parameters
#define bufferSize (uInt32)1000
float64 data[bufferSize];
int32 pointsToRead = bufferSize;
int32 pointsRead;
float64 timeout = 10.0;

DAQmxErrChk (DAQmxBaseCreateTask("",&CounterTaskHandle));
DAQmxErrChk (DAQmxBaseCreateTask("",&AITaskHandle));

printf("Calling DAQmxBaseCreateCOPulseChanFreq...\n");
DAQmxErrChk (DAQmxBaseCreateCOPulseChanFreq(CounterTaskHandle, clockSource, NULL, DAQmx_Val_Hz, DAQmx_Val_Low, delay, freq, duty));
printf("Back from calling DAQmxBaseCreateCOPulseChanFreq...\n");
DAQmxErrChk (DAQmxBaseCreateAIVoltageChan(AITaskHandle,chan,"",DAQmx_Val_Cfg_Default,min,max,DAQmx_Val_Volts,NULL));

printf("Calling DAQmxBaseCfgSampClkTiming (%s)...\n", clockSource);
DAQmxErrChk (DAQmxBaseCfgSampClkTiming(AITaskHandle,clockSource,sampleRate,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,samplesPerChan));
printf("Back from calling DAQmxBaseCfgSampClkTiming...\n");

DAQmxErrChk (DAQmxBaseStartTask(AITaskHandle));
DAQmxErrChk (DAQmxBaseStartTask(CounterTaskHandle));

DAQmxErrChk (DAQmxBaseReadAnalogF64(AITaskHandle,pointsToRead,timeout,DAQmx_Val_GroupByChannel,data,bufferSize,&pointsRead,NULL));

printf ("Acquired %d samples\n", pointsRead);

// Just print out the first 10 points
for (i = 0; i < 10; ++i)
printf ("data[%d] = %f\n", i, data[i]);

Error:
if( DAQmxFailed(error) )
DAQmxBaseGetExtendedErrorInfo(errBuff,2048);
if(AITaskHandle != 0) {
DAQmxBaseStopTask (AITaskHandle);
DAQmxBaseClearTask (AITaskHandle);
}
if( DAQmxFailed(error) )
printf ("DAQmxBase Error %d: %s\n", error, errBuff);
return 0;
}

 

 

and here are the results:

 

 

  $ ./acquireNScans-ExtClk
  Calling DAQmxBaseCreateCOPulseChanFreq...

  Back from calling DAQmxBaseCreateCOPulseChanFreq...
  Calling DAQmxBaseCfgSampClkTiming (Dev1/ctr0)...
  DAQmxBase Error -200220: Device identifier is invalid. Source must be on same device as channel.

 

Is the DAQmxBaseCreateCOPulseChanFreq function the correct way to create a counter?

 

What device name should be used? I've tried Dev1/ctr0, /Dev1/ctr0, Dev1/ctr1, /Dev/ctr1, Dev1/port0, /Dev1/port0, Dev1/port1, and /Dev1/port1 and they all fail. From the error -200220 is seems like my device channel for the counter is incorrect, but I can't find the name that should be used for a USB-6210 device.

 

Any ideas?

 

-Tom

 

0 Kudos
Message 7 of 11
(5,137 Views)

Hi Tom,

 

The name of the counter is indeed "Dev1/ctr1".  I believe the problem is that this string references the counter while the 2nd input of DAQmxBaseCfgSampClkTiming is supposed to be a terminal.  Try using "/Dev1/Ctr1InternalOutput" as the clock source (you still have to use "Dev1/ctr1" when configuring your counter output task however).  Terminals are designated with a "/" in the front of the name and correspond to the possible places that signals can be routed to and from (e.g. PFI lines).

 

 

Best Regards,

John Passiak
0 Kudos
Message 8 of 11
(5,077 Views)

Hi John,

 

Thanks for the reply and thanks for explaining the distinction between virtual channels and terminals. I tried what you suggest and I just generated a different error. Here's the source code I used and the error message I received:

 

 

#include "NIDAQmxBase.h"
#include <stdio.h>

#define DAQmxErrChk(functionCall) { if( DAQmxFailed(error=(functionCall)) ) { goto Error; } }

int main(void)
{
    // Task parameters
    int32       error = 0;
    TaskHandle  AITaskHandle = 0;
    TaskHandle  CounterTaskHandle = 0;
    char        errBuff[2048]={'\0'};
    int32       i;

    // Channel parameters
    char        chan[] = "Dev1/ai0";
    float64     min = -10.0;
    float64     max = 10.0;

    // Timing parameters
    char        clockSource[] = "Dev1/ctr1";
    char        clockTerminal[] = "/Dev1/Ctr1InternalOutput";
    uInt64      samplesPerChan = 1000;
    float64     sampleRate = 10000.0;
    float64     delay=0.0;
    float64     freq=1.0;
    float64     duty=0.5;

    // Data read parameters
    #define     bufferSize (uInt32)1000
    float64     data[bufferSize];
    int32       pointsToRead = bufferSize;
    int32       pointsRead;
    float64     timeout = 10.0;

    DAQmxErrChk (DAQmxBaseCreateTask("",&CounterTaskHandle));
    DAQmxErrChk (DAQmxBaseCreateTask("",&AITaskHandle));
        
printf("Calling DAQmxBaseCreateCOPulseChanFreq... (%s)\n", clockSource);
    DAQmxErrChk (DAQmxBaseCreateCOPulseChanFreq(CounterTaskHandle, clockSource, NULL, DAQmx_Val_Hz, DAQmx_Val_Low, delay, freq, duty));    
printf("Back from calling DAQmxBaseCreateCOPulseChanFreq...\n");
    DAQmxErrChk (DAQmxBaseCreateAIVoltageChan(AITaskHandle,chan,"",DAQmx_Val_Cfg_Default,min,max,DAQmx_Val_Volts,NULL));

printf("Calling DAQmxBaseCfgSampClkTiming (%s)...\n", clockTerminal);
    DAQmxErrChk (DAQmxBaseCfgSampClkTiming(AITaskHandle,clockTerminal,sampleRate,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,samplesPerChan));
printf("Back from calling DAQmxBaseCfgSampClkTiming...\n");

    DAQmxErrChk (DAQmxBaseStartTask(AITaskHandle));
    DAQmxErrChk (DAQmxBaseStartTask(CounterTaskHandle));    

    DAQmxErrChk (DAQmxBaseReadAnalogF64(AITaskHandle,pointsToRead,timeout,DAQmx_Val_GroupByChannel,data,bufferSize,&pointsRead,NULL));

    printf ("Acquired %d samples\n", pointsRead);

    // Just print out the first 10 points
    for (i = 0; i < 10; ++i)
        printf ("data[%d] = %f\n", i, data[i]);

Error:
    if( DAQmxFailed(error) )
        DAQmxBaseGetExtendedErrorInfo(errBuff,2048);
    if(AITaskHandle != 0) {
        DAQmxBaseStopTask (AITaskHandle);
        DAQmxBaseClearTask (AITaskHandle);
    }
    if( DAQmxFailed(error) )
		printf ("DAQmxBase Error %d: %s\n", error, errBuff);
    return 0;
}

 

 

$./acquireNScans-ExtClk
Calling DAQmxBaseCreateCOPulseChanFreq... (Dev1/ctr1)
Back from calling DAQmxBaseCreateCOPulseChanFreq...
Calling DAQmxBaseCfgSampClkTiming (/Dev1/Ctr1InternalOutput)...
DAQmxBase Error -89136: <err>Specified route cannot be satisfied, because the hardware does not support it.

 

I tried all combinations of "Dev1/ctr0", "Dev1/ctr1", "/Dev1/Ctr0InternalOutput", and "/Dev1/Ctr1InternalOutput" and the error message returned is the same. After doing more research, I found suggestions in the forums to use MAX to find out what terminals and channels are available. Unfortunately, I can't run the MAX program on Linux.


Does a USB-6210 device not support internal clock mapping? Should I be using one of the PFI lines instead of /Dev1/Ctr1InternalOutput?

 

Any advice would be helpful.

 

Thanks again,

 

-Tom

 

0 Kudos
Message 9 of 11
(5,061 Views)
Solution
Accepted by topic author ase-tom

Hey Tom,

 

Thanks for the update, I should have tested my suggestion before posting but I didn't have hardware handy at the time.  As it turns out, DAQmx Base doesn't support routing the internal counter outputs to AI Sample Clock.

 

The workaround is going to be physically wiring the counter output terminal (default is PFI 4 for counter 0, PFI 5 for counter 1) back to one of the input PFI lines (PFI 0:3) and use the input PFI as the source for your AI Sample Clock (e.g. "/Dev1/PFI0"). 

 

 

Best Regards,

John Passiak
Message 10 of 11
(5,054 Views)