02-23-2011 04:27 PM
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
Solved! Go to Solution.
02-24-2011 11:00 AM
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:
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
02-24-2011 11:10 AM
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
02-28-2011 12:59 AM
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
02-28-2011 09:20 AM
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)
02-28-2011 09:25 AM
Thank you for the reply. I'll look into your counter suggestion and see if I can figure it out.
Thanks again,
-Tom
02-28-2011 04:49 PM
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
03-09-2011 06:21 PM - edited 03-09-2011 06:22 PM
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,
03-10-2011 10:31 AM
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
03-10-2011 02:05 PM
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,