Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

USB-6215 NI-DAQmx Analog Input Problems

Hello:

 

I'm trying to read differential voltages on my USB-6215 from 8 channels.  I've looked at the example code, tried several configurations, but can't seem to get what I need.  The short version is that  no matter what I try, I can only seem to access the data for the first channel.  I'm using AI0/AI8 as the input for channel 1 and AI1/AI9 for channel 2.  In my test, I use two 1.6 volt AA batteries as test signals.  No matter what I try, I can see the 1.6 volt input on channel 1 (Dev1/ai0), but can't see anything on the second channel (Dev1/ai1).  I'm either not reading what I think I am, or I don't understand how to access the data in the array after the read.  Any help would be greatly appreciated.

 

The following code is my latest brute force try at reading multiple channels.  I get no errors (i.e. result = 0) on all function calls, so I think it is just a matter of me not understaning the system:

 

 

// === Analog Input Test ====================================

 int result = 0;

TaskHandle AnalogTaskHandle0 = 0;

TaskHandle AnalogTaskHandle1 = 0;

 

float64 data0[1000];

float64 data1[1000];

 

char errBuff[2048]={'\0'};

int32 numSamplesPerChannelRead = 1;

 

// Create the DAQ tasks for the analog reads.

result = DAQmxCreateTask("",&AnalogTaskHandle0); 

result = DAQmxCreateTask("",&AnalogTaskHandle1); 

  

// Create the Channels

result = DAQmxCreateAIVoltageChan(AnalogTaskHandle1,"Dev1/ai1","",DAQmx_Val_Diff,-10.0,10.0,DAQmx_Val_Volts,NULL);

result = DAQmxCreateAIVoltageChan(AnalogTaskHandle2,
"Dev1/ai2","",DAQmx_Val_Diff,-10.0,10.0,DAQmx_Val_Volts,NULL);

 

 

 

 result = DAQmxCfgSampClkTiming(AnalogTaskHandle0,"",10000.0,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,10);  result = DAQmxCfgSampClkTiming(AnalogTaskHandle1,"",10000.0,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,10);

 

int i = 0;

while(TRUE)

{

   for(i = 0; i < 100; i++)

   {

      data0[i] = 0.0;

      data1[i] = 0.0;

   }

 

   // Start the tasks

   result = DAQmxStartTask(AnalogTaskHandle0);
 

   result = DAQmxStartTask(AnalogTaskHandle1);

 

   // Read the channels

   result = DAQmxReadAnalogF64(AnalogTaskHandle0,10,0.005,DAQmx_Val_GroupByScanNumber,data0,1000,&numSamplesPerChannelRead,NULL);
 

   result = DAQmxReadAnalogF64(AnalogTaskHandle1,10,0.005,DAQmx_Val_GroupByScanNumber,data1,1000,&numSamplesPerChannelRead,NULL);

 

   // Stop the tasks.

 

   DAQmxStopTask(AnalogTaskHandle0);

   DAQmxStopTask(AnalogTaskHandle1);

 

 

   // See if any of the channels have a voltage greater than 1.0 V.

 

   for(i = 0; i < 100; i++)       if(data0[i] > 1.0)

         TRACE("data0[%d]: %0.3f\n", i, data0[i]);

 

   for(i = 0; i < 100; i++)

      if(data1[i] > 1.0)

         TRACE("data1[%d]: %0.3f\n", i, data1[i]);

 

 

}

 

Bob H.

0 Kudos
Message 1 of 11
(4,907 Views)
What you are calling a channel is really a task and you cannot have more than one task running on the same hardware resource. I have no idea why you are not getting an error but you should be. Use a single task and if you require different configurations, use multiple DAQmxCreateAIChannel functions on the same task.
0 Kudos
Message 2 of 11
(4,902 Views)

Thanks for the help.  I'll go off an try your suggestion. 

 

One more question... Assuming I get the thing to work, shouldn't I see the data arranged by channel.  That is, since I'm using DAQmx_Val_GroupByScanNumber in the DAQmxReadAnalogF64 call, shouldn't I see the channel 1 value in data[0], channel 2 in data[1], and so forth?  With an array size of 1000, I'd expect to see the 8 channel values in order and the the next 8 channel values in order etc. etc.  Is this correct?

 

Thanks.

Bob

0 Kudos
Message 3 of 11
(4,899 Views)

Dennis:

 

I think I tried what you were suggesting (modified code below - no errors reported from function calls).  I seem to be getting the same results:

  

 

1) With no source connected to any channel, I see the data is all over the place... sometimes around 0 volts and other times around 10 volts.  I'm guessing this is due to the other channels floating since no source is connected to them - probably not a problem.

 

2) I can see the 1.6volt value when I apply the AA battery between AI0 and AI8 (what I'm calling channel 1).  When I apply the source to another channel (AI2 / AI9), I see no change in the data. 

 

3) When I apply the AA battery between AI0 and AI8, all other channels seem to get the same value after a short time.  It's as if I'm charging an internal capacitor.  This may also be due to floating (not a problem when all signals are connected).

 

int result = 0;

TaskHandle AnalogTaskHandle = 0;

float64 data[1000];

char errBuff[2048]={'\0'};

int32 numSamplesPerChannelRead = 1;

 

// Create the DAQ task for the analog reads.

result = DAQmxCreateTask("",&AnalogTaskHandle);

 

// Create the channels.

result = DAQmxCreateAIVoltageChan(AnalogTaskHandle,
"Dev1/ai0","",DAQmx_Val_Diff,-10.0,10.0,DAQmx_Val_Volts,NULL); 

result = DAQmxCreateAIVoltageChan(AnalogTaskHandle,"Dev1/ai1","",DAQmx_Val_Diff,-10.0,10.0,DAQmx_Val_Volts,NULL);result = DAQmxCreateAIVoltageChan(AnalogTaskHandle,

"Dev1/ai2","",DAQmx_Val_Diff,-10.0,10.0,DAQmx_Val_Volts,NULL);

result = DAQmxCreateAIVoltageChan(AnalogTaskHandle,"Dev1/ai3","",DAQmx_Val_Diff,-10.0,10.0,DAQmx_Val_Volts,NULL);result = DAQmxCreateAIVoltageChan(AnalogTaskHandle,

"Dev1/ai4","",DAQmx_Val_Diff,-10.0,10.0,DAQmx_Val_Volts,NULL);

result = DAQmxCreateAIVoltageChan(AnalogTaskHandle,"Dev1/ai5","",DAQmx_Val_Diff,-10.0,10.0,DAQmx_Val_Volts,NULL);result = DAQmxCreateAIVoltageChan(AnalogTaskHandle,

"Dev1/ai6","",DAQmx_Val_Diff,-10.0,10.0,DAQmx_Val_Volts,NULL);

result = DAQmxCreateAIVoltageChan(AnalogTaskHandle,"Dev1/ai7","",DAQmx_Val_Diff,-10.0,10.0,DAQmx_Val_Volts,NULL);

 

result = DAQmxCfgSampClkTiming(AnalogTaskHandle,"",10000.0,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,10);

  

int i = 0;

while(TRUE)

{

   for(i = 0; i < 100; i++)

      data[i] = 0.0;

 

   // Start the task.

   result = DAQmxStartTask(AnalogTaskHandle);

 

   // Read the device.

   result = DAQmxReadAnalogF64(AnalogTaskHandle,10,0.005,DAQmx_Val_GroupByScanNumber,data,1000,&numSamplesPerChannelRead,NULL);

 

 

   // Stop the task.

 

   DAQmxStopTask(AnalogTaskHandle);

 

 

   for(i = 0; i < 100; i++)

      if( (data[i] > 1.5) && (data[i] < 1.7) )         TRACE(

"data[%d]: %0.3f\n", i, data[i]);

  

}

 

Thanks again,

Bob

0 Kudos
Message 4 of 11
(4,891 Views)

Hello,

 

I encountered a similar error, but i haven't found a solution to it. Were you able to rectify your problem? My problem is the signal from one channel shows up on the other 7 channels, and that shouldn't be. Any help would be appreciated. 

 

Thanks.

0 Kudos
Message 5 of 11
(4,793 Views)

I did find a solution...

 

First, the problem of all the voltages being the same is not a big problem after all.  It turns out that all of the channels will follow each other until you actually connect something to them.  I'm using differential mode, so they were able to float (or follow each other) until I connected something to each channel.  As I made connections, the channel I connected to was always right.

 

Now the code problem.  The code below works well for me.  It is a function I use as a thread, so you may want to make some changes (e.g. the "this_object-> syntax" is not necessary in a normal function).  I'm reading two counters (one for tach and one for speed), and 8 differential analog channels on the USB-6215.  I first declare and create 3 task handles (one for tach, one for speed and one for the analog channels).  Next I create the channels and start the tasks.  From there I go into a while loop that continues until KILL_THREAD is true.  In the loop, i just keep reading the device and stop/start the tasks again and again.  I'll have to post the code in multiple replies because of the 10,000 character limit on each message.

 

UINT NIUSB6215::Read(LPVOID pVoid)

{

if( pVoid == NULL )
return 0;

NIUSB6215* this_object = (NIUSB6215*)pVoid;

TaskHandle TachCounterTaskHandle = 0;

TaskHandle SpeedCounterTaskHandle = 0;

TaskHandle AnalogTaskHandle = 0;

int32 result = 0;

int32 numSamplesPerChannelRead = 0;

LARGE_INTEGER start_time;

LARGE_INTEGER time_now;

LARGE_INTEGER freq;

BOOL timer_result;

char err[1000];

DAQmxGetSysDevNames(err, 1000);

 

 

// Create the DAQ task for the tach counter.

result = DAQmxCreateTask("",&TachCounterTaskHandle);

 

 

// Create the DAQ task for the speed counter.

result = DAQmxCreateTask("",&SpeedCounterTaskHandle);

 

 

// Create the DAQ task for the analog reads.

result = DAQmxCreateTask("",&AnalogTaskHandle);

 

  // Create the tach counter channel.

 

// Input is PFI 1 - Pin 2result = DAQmxCreateCIFreqChan(TachCounterTaskHandle,"Dev1/ctr0","",500,5100.000000,DAQmx_Val_Hz,DAQmx_Val_Rising,DAQmx_Val_LowFreq1Ctr,0.001,1,"");

 

 

// Create the speed counter channel.

// Input is PFI 2 - Pin 3

result = DAQmxCreateCIFreqChan(SpeedCounterTaskHandle,"Dev1/ctr1","",2,1120.000000,DAQmx_Val_Hz,DAQmx_Val_Rising,DAQmx_Val_LowFreq1Ctr,0.001,1,"");

 

  // Create the analog channels.

 

result = DAQmxCreateAIVoltageChan(AnalogTaskHandle,"Dev1/ai0:7","",DAQmx_Val_Diff,-10.0,10.0,DAQmx_Val_Volts,NULL);  // Configure the sample clock for the analog conversions.

 

result = DAQmxCfgSampClkTiming(AnalogTaskHandle,"",10000.0,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps, this_object->NumAnalogSamples);

 

 

// Start the tach task.

result = DAQmxStartTask(TachCounterTaskHandle);

 

// Start the speed task.

result = DAQmxStartTask(SpeedCounterTaskHandle);

 

// Start the analog sample task.

result = DAQmxStartTask(AnalogTaskHandle);

 

 

Hope this helps.

Bob

0 Kudos
Message 6 of 11
(4,786 Views)

Part two of the code...

 

// Loop until we're told to quit.

 while(!this_object->KILL_THREAD) {

 

// Re-start the clock to keep track of elapsed time.

timer_result = QueryPerformanceCounter(&start_time);

 

// Enter the critical section so no one can read while we write.

EnterCriticalSection(&(this_object->CriticalSection));

 

// Read the tach counter.

 this_object->RPM = 0;

result = DAQmxReadCounterScalarF64(TachCounterTaskHandle,0.3,&this_object->RPM,0);

this_object->analog_counts[this_object->Tach_index] = this_object->RPM;

 

//TRACE("RPM: %0.3lf\n", this_object->RPM);

// Read the speed counter.

this_object->VehicleSpeed = 0;

result = DAQmxReadCounterScalarF64(SpeedCounterTaskHandle,0.1,&this_object->VehicleSpeed,0);

this_object->analog_counts[this_object->Speed_index] = this_object->VehicleSpeed;

 

// Read the analog channels.

result = DAQmxReadAnalogF64(AnalogTaskHandle,10,0.005,DAQmx_Val_GroupByChannel,this_object->analog_voltages,this_object->voltage_arr_size,&numSamplesPerChannelRead,NULL);if( numSamplesPerChannelRead != 10 )

   memset(&this_object->analog_voltages[0], 0, this_object->voltage_arr_size);

else

   this_object->AverageAnalogValues();

 

// Release the CriticalSection.

LeaveCriticalSection(&(this_object->CriticalSection));

 

// Stop the tach task and re-start it.

result = DAQmxStopTask(TachCounterTaskHandle);

result = DAQmxStartTask(TachCounterTaskHandle);

 

// Stop the speed task and re-start it.

result = DAQmxStopTask(SpeedCounterTaskHandle);

result = DAQmxStartTask(SpeedCounterTaskHandle);

 

// Start the analog sample task.

DAQmxStopTask(AnalogTaskHandle);

result = DAQmxStartTask(AnalogTaskHandle);

 

// Get the the current time and calculate the elapsed time.

timer_result = QueryPerformanceCounter(&time_now);

this_object->CounterET = 1.0/freq.LowPart * (time_now.LowPart - start_time.LowPart);

 

Sleep(0);

}
// End while loop.

 

// Cleanup by stopping the tasks and clearing the memory allocated to it.

 if( TachCounterTaskHandle!=0 ) {

DAQmxStopTask(TachCounterTaskHandle);

DAQmxClearTask(TachCounterTaskHandle);

}

if( SpeedCounterTaskHandle!=0 ) {

DAQmxStopTask(SpeedCounterTaskHandle);

DAQmxClearTask(SpeedCounterTaskHandle);

}

if( AnalogTaskHandle!=0 ) {

DAQmxStopTask(AnalogTaskHandle);

DAQmxClearTask(AnalogTaskHandle);

}

 

TRACE(
"NIUSB6215 Thread exiting.\n");

AfxEndThread(0);

return 0;

}

 

Bob

0 Kudos
Message 7 of 11
(4,784 Views)

Thanks, Bob. That's exactly what happens -- they all follow each other until you connect something to them or short the other channels. I'm also using differential mode. I'd like to clarify something: if you make a connection to, say channel 2 and another connection to channel 5, do you see the same voltage at channels 2, 3, and 4, but a different voltage at 5 through 1? More like it's rotating?

 

Thanks,

Ben.

0 Kudos
Message 8 of 11
(4,779 Views)

It's been a while since I looked (don't have it set up right now), but I believe that is correct.  I used a small battery (AA or 9V) to test the channels.  I remember that the disconnected channels did tend to follow one or more of the connected ones.  I guess I was concentrating on the fact that when I connected a source (battery) to channel 2 and a different one to channel 5, they both read correctly.  If you're reading all the channels and only really using some of them, you may want to modify your code to ignore the floating voltages.

 

Bob

0 Kudos
Message 9 of 11
(4,777 Views)
Cool, thanks.
0 Kudos
Message 10 of 11
(4,775 Views)