Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

How to continuously acquire voltage samples - software timed, ANSI C

Hello all,

 

I am trying to do a software triggered, single sample read and write from my NI USB-6218 in C/C++. I do not have Measurement Studio. I have created the two tasks, created the channels, and started the tasks. I have a waitable timer set up to signal when I want to read and write (I have a multi-threaded application and am triggering the read/write with one of my worker threads). I used DAQmxWriteAnalogScalarF64 for the write, and would like to use DAQmxReadAnalogScalarF64 for the read. The write task works fine, but the read task will not work. Every time i get to the DAQmxReadAnalogScalarF64, the program stalls and never exits, not even with a time-out error.  I checked with the measurement explorer and the DAQ is functioning properly. 

I was wondering if anyone has any suggestions as to why the read will not work when the write works just fine. What am i not doing for the read application? Do i need to set a specific software trigger? What else can i do?

 

Also, an older white paper (http://www.ni.com/white-paper/6999/) suggests that there is an ANSI C example under analog input called "Continuously Acquire Voltage Samples - Software Timed." I can't find this under the installed examples. Does someone have a copy of this example? This could help with my problem. 

 

Thanks,

 

Ariel

 

Relevant Code:

 

int error = DAQmxCreateTask("",&outTaskHandle);
if(errorFunc(error, outTaskHandle))
return (0);

 

error = DAQmxCreateTask("",&inTaskHandle);
if(errorFunc(error, inTaskHandle))
return (0);

 

for(int i = 0; i < num_out_analog_ch; i++)
{
error = DAQmxCreateAOVoltageChan(outTaskHandle,out_analog_channels[i],"",MIN_VOLTS,MAX_VOLTS,DAQmx_Val_Volts,"");
if(errorFunc(error, outTaskHandle))
return (0);
}

 

for(int i = 0; i < num_in_analog_ch; i++)
{
error = DAQmxCreateAIVoltageChan(inTaskHandle,in_analog_channels[i],"",DAQmx_Val_Cfg_Default,MIN_VOLTS,MAX_VOLTS,DAQmx_Val_Volts,NULL);
if(errorFunc(error, inTaskHandle))
return (0);
}

 

error = DAQmxStartTask(outTaskHandle);
if(errorFunc(error, outTaskHandle))
return (0);

 

error = DAQmxStartTask(inTaskHandle);
if(errorFunc(error, inTaskHandle))
return (0);

 

if(m_hRobotWriteEvent = CreateWaitableTimer(NULL, FALSE, TEXT("RobotWriteTimer")))
{
LARGE_INTEGER startTime;
startTime.QuadPart = 0;

bool bSuccess = SetWaitableTimer(
m_hRobotWriteEvent, // Handle to the timer object.
&startTime, // When timer will become signaled.
1.0/SAMP_RATE*1000.0, // Periodic timer interval
TimerCompletion, // Completion routine.
this, // Argument to the completion routine.
FALSE ); // Do not restore a suspended system.

 

if(!bSuccess)
cout << "Could not set timer." << endl;
}
else
cout << "Timer could not be created." << endl;

 

 

void TimerCompletion()
{
int error;
double nextVoltage = currentVoltage; // global variable
float64 readValue = 0.0;

 

error = DAQmxWriteAnalogScalarF64(outTaskHandle,1,-1,nextVoltage ,NULL);
if(errorFunc(error, outTaskHandle))
return;

 

error = DAQmxReadAnalogScalarF64(inTaskHandle,10.0,&readValue, NULL); // will not work
if(errorFunc(error, outTaskHandle))
return;

}


0 Kudos
Message 1 of 9
(5,148 Views)

Are you certain you don't have that specific example installed? It should get installed with the DAQmx driver. Just to be clear, it can be found here (if you have Windows 7 or Vista installed): C:\Users\Public\Documents\National Instruments\NI-DAQ\Examples\DAQmx ANSI C\Analog In\Measure Voltage\

 

Brice Sorrells

Applications Engineer

National Instruments

www.ni.com/support

0 Kudos
Message 2 of 9
(5,133 Views)

Absolutely positive. I have that folder installed, but the specific example (software timed analog input) is missing. I have the regular voltage analog input examples, the continuous voltage analog input examples, and the reading directly to a binary file. But no software timed analog voltage input. I have downloaded the latest daqmx software (9.5.5)

 

if you have a copy of this example, could you copy the relevant section into a response? It would be immensely helpful. 

0 Kudos
Message 3 of 9
(5,126 Views)

ArielD,

 

You have your code written such that it appears as though you allow for multiple AI channels in your task, however you are using a version of DAQmxRead which is only compatible with tasks of a single channel.  If you're allowing for multiple channels, you'll need to call DAQmxReadAnalogF64.  However, I would expect that DAQmx would return an error if your number of channels was incompatible with the read flavor chosen.

 

Dan

0 Kudos
Message 4 of 9
(5,111 Views)

It's true, in that code I had it set up to take more than one channel. However, i was only running through the loop once, and therefore was only creating one channel. I subsequently tried it with just one channel without the loop, and it still wouldn't work (even though the same exact code worked with DAQmxWriteAnalogScalarF64). 

 

The strangest part of the issue is that i was never getting an error. the function was just...hanging, like it an infinite while loop. it would just stick. I tried changing the include and library files to see if maybe there was an error in the library, but i still got nothing. that thread would just get stuck on the read, and never return, not even a timeout error.

 

i finally made it work by using the continous read with DAQmxReadAnalogF64 with twice my target sample rate and a 2 sample read array. I wrapped the callback function so that I could access my class variables and functions. But i still can't understand what the issue was with the scalar read (and it certainly would have been cleaner if i could have avoided the continuous read with an event callback in my worker thread). But as usual, a workaround made it work. 

0 Kudos
Message 5 of 9
(5,097 Views)

ArielD,

 

I'm glad that you were able to find a workaround, however this really shouldn't be necessary.  I'm curious to see what is going wrong with the code that you posted.  Unfortunately I don't currently have a USB-6212 on hand.  You had mentioned that you can't find the software timed example program, however I don't think the location you were told to look in is correct.  The folder should be named 'Measure Slow Varying Signal'.  In this folder, you should find an example named 'Cont Acq Samp-SW Timed'.  Can you run this successfully?  In case you have trouble find this example, I'll attach the source here.  If that doesn't run correctly for you, I'll see if I can find myself a USB-6218 to reproduce the issue.

 

Hope that helps,

Dan

0 Kudos
Message 6 of 9
(5,086 Views)

Hi Dan,

 

Thanks for the response. I'll be back in the office on sunday (work week in israel is sunday-thursday) and will use this example to try out the daq. I noticed you didn't use DAQmxReadAnalogScalarF64 but used DAQmxReadAnalogF64 with a one sample array. Is there a reason for this discrepancy? 

 

Also, i forgot to mention that the data collected from the read is...questionable. I'm currently sampling 2 samples at 1000 Hz and then selecting the first sample for my program (to get my ideal sampling rate of 500hz, which is a bit low). About 1/4 of the data is wrong. I'm testing with a power supply to get a consistent signal, and about 3/4 of the samples are correct, and 1/4 are completely off, 3 to 4 volts less or greater than the commanded signal. So it isn't working great. I also tried different channels and am always getting the same results. 

 

One of my labmates blew our other daq this week with a poorly protected circuit, so i believe we'll have someone from NI israel coming to the lab this upcoming week to fix it. If we don't get this issue resolved by then, i'll try to get the name of whoever is coming out to see us and see if i can connect them with you guys so we can resolve my problem. thank you for your help. 

 

ariel

0 Kudos
Message 7 of 9
(5,078 Views)

Ariel,

 

I'm not entirely sure why DAQmxReadAnalogF64 was used instead of DAQmxReadAnalogScalarF64.  If I had to guess it would be so that the code could be modified to support multiple channels without needing to change read functions.  For the single channel case, either read function will work.

 

Dan

0 Kudos
Message 8 of 9
(5,068 Views)

I finally found the solutions, and looked through them all. They are located in a different place, under the "measure slow varying signal folder". I ran these examples and they worked just fine, meaning my DAQ isn't the problem. I tried implementing those examples in my solution, as well as played with the code a bit. The issue seems to be the waitable timer. The function will not execute within the waitable timer callback routine, but will execute outside of it. I don't know why this incompatibility is there, but the two functions do not seem to work together. Outside the timer loop, everything is fine, but inside it will not work. So i guess for a now i'll keep my workaround function, since that seems to be giving me data (albeit inconsistent data, but that might be a result of my power supply). However, there seems to be an incompatibility issue with waitable timers and the read function.

0 Kudos
Message 9 of 9
(5,049 Views)