Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

Data read with DAQmxReadAnalogF64

Solved!
Go to solution

Hi,

 

I am using DAQmxReadAnalogF64 and I am not sure about the time at wich the data are read.

For example, I would like to acquire data during 3s.

I if use DAQmxReadAnalogF64 function at time t, will the read data correspond to the interval t + 3 (start reading at the time the use the function) or t - 3 (read the past 3s data)?

 

Thanks,

Miko

Miko
0 Kudos
Message 1 of 9
(5,755 Views)

Miko,

 

What is returned by DAQmxRead is dependent on how your task is configured along with when DAQmx read is called.

 

Based on the fact that you want to read three seconds worth of data, the easiest case would be to use DAQmxCfgSampClkTiming to setup a finite task.  This task would be configured to acquire data at a known rate, and to acquire 3x this number of samples.  With the task configured like this, the data returned from DAQmxReadAnalogF64 would correspond to (Time at DAQmxStartTask through Time at DAQmxStartTask + 3s).  This is the data returned regardless of when DAQmxRead is called.

 

For Example, your program can look like the following (error handling omitted for brevity):

TaskHandle  taskHandle=0;

int32       read;
float64     data[30000];

DAQmxCreateTask("", &taskHandle);

DAQmxCreateAIVoltageChan(taskHandle,"Dev1/ai0","",DAQmx_Val_Cfg_Default,-10.0,10.0,DAQmx_Val_Volts,NULL);

// Set up timing: Finite task, three seconds worth of data

DAQmxCfgSampClkTiming(taskHandle,"",10000.0,DAQmx_Val_Rising,DAQmx_Val_FiniteSamps,30000);

DAQmxStartTask(taskHandle); // Data Acquisition begins here

DAQmxReadAnalogF64(taskHandle,30000,10.0,DAQmx_Val_GroupByChannel,data,30000,&read,NULL); // Read waits until 3 seconds worth of data is acquired and returns them

DAQmxStopTask(taskHandle);
DAQmxClearTask(taskHandle);

 

If you call DAQmxCfgSampClkTiming with sampleMode set to DAQmx_Val_ContSamps, then determining what data DAQmxRead returns is a bit more challenging.  Like with finite timing, DAQmx will begin acquiring data when DAQmxStartTask is called (I'll call this t0).  This data is transferred from the device to a buffer which DAQmxRead will read from.  If you call read in a loop and specify 'sampsPerChanToAcquire' to be 3 times the 'rate', then DAQmxRead should return data every three seconds.  This data corresponds to:

First Read = Data from t0 through t0 + 3

Second Read = Data from t0 + 3 through t0 + 6

Third Read = Data from t0 + 6 through t0 + 9

etc..

 

If this is not what you'd desire, there are ways to change DAQmxRead's behavior such that DAQmxRead returns data relative to something other than the last sample returned.  This can be done using DAQmxSetReadRelativeTo and DAQmxSetReadOffset.

 

Some information on this can be found in NI-DAQmx Help under topics:

NI-DAQmx Key Concepts->Reading and Writing Data->Buffering

 

Hope that helps,

Dan

 

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

Hi Dan,

 

Thanks for your detailed answer.

I'll explain you what I wanted to do: I have 2 DAQ devices for acquisitioin. One is triggered with an external trigger and I wanted to trigger the second device on the same external trigger. To do so, I run the start task of the second device as soon as the logging property of the acquisition task of the first device was 'On'. And just after that I had my 'DAQmxReadAnalogF64' function. However when looking at the signals, I saw a delay varying from 150 ms to 200 ms between the two acquisitions. That's why I wondered how this function works.

 

Anyway it seems that I am doing it wrong concerning the second triggering. I am trying a new method to do this but I am facing some diffculties (can't detect the trigger for the second DAQ). If I can't solve these, I'll make a new post.

 

Thanks again, your reply was helpful,

Miko

Miko
0 Kudos
Message 3 of 9
(5,732 Views)

Miko,

 

With external triggers, what I said above isn't exactly true.  If you are using an external trigger to start your acquisition calling DAQmxStartTask causes the device to begin waiting for the external trigger.  In terms of what I wrote above, you can replace 'Time at DAQmxStartTask' with 'Time of External Trigger'.  For this to work, ensure that you have called DAQmxStartTask prior to the assertion of the external trigger signal.

 

What hardware are you using?  Are you using some sort of digital signal as a trigger for your tasks?  Your comment, "To do so, I run the start task of the second device as soon as the logging property of the acquisition task of the first device was 'On'." leads me to believe that you are not starting your second task until after the trigger signal has already occurred.  Generally you'd want both task to be started before the assertion of the trigger signal, so that both devices begin acquisition at the same time.

 

If you can provide more details about what you'd like to do I may be able to provide more specific suggestions.

 

Dan

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

Hi Dan,

 

I changed my code to start the Task before assertion of the trigger signal.

Below is a piece of my code:

 

    %% Counter Output
    TaskCO = libpointer('voidPtrPtr',[]);
    calllib('myni','DAQmxCreateTask','CO',TaskCO);
    calllib('myni','DAQmxCreateCOPulseChanFreq',TaskCO,'Dev2/ctr0','',int32(10373),int32(10214),0,16000,0.5);
    NbSamples = 160000;
    calllib('myni','DAQmxCfgImplicitTiming',TaskCO,uint32(10178),uint64(NbSamples));
    
    %% Digital Output
    TaskDO = libpointer('voidPtrPtr',[]);
    calllib('myni', 'DAQmxCreateTask', 'DO', TaskDO);
    calllib('myni','DAQmxCreateDOChan',TaskDO,'Dev2/port0/line4:7','',uint32(0));
    calllib('myni','DAQmxCfgSampClkTiming',TaskDO,'/Dev2/ctr0InternalOutput',16000,int32(10280),uint32(10178),uint64(NbSamples));
        
    % Write ditigal sequence to output buffer
    L1 = repmat([0 1],1,NbSamples/2);
    L2 = repmat([0 0 1 1],1,NbSamples/4);
    L3 = round(repmat([0 0 0 0 1 1 1 1],1,NbSamples/8));
    L4 = repmat([0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 ],1,NbSamples/16);
    WriteArray = cat(1,L1,L2,L3,L4);
    WriteArray = libpointer('uint8Ptr',WriteArray);
    SampsPerChanWritten = libpointer('int32Ptr',0);
    Reserved = libpointer('uint32Ptr',[]);
    calllib('myni','DAQmxWriteDigitalLines',TaskDO,int32(NbSamples),uint32(0),10,uint32(1),WriteArray,SampsPerChanWritten,Reserved);
        
    %% Analog Input
    TaskAI = libpointer('voidPtrPtr',[]);
    calllib('myni','DAQmxCreateTask','AI',TaskAI);
    calllib('myni','DAQmxCreateAIVoltageChan',TaskAI,'Dev2/ai0:3','',10083,-10,10,10348,'');
    calllib('myni','DAQmxCfgSampClkTiming',TaskAI,'/Dev2/ctr0InternalOutput',16000,int32(10280),uint32(10178),NbSamples);
    
    % ReadAnalogF64 parameters
    ReadArray0 = libpointer('doublePtr',zeros(4,NbSamples));
    SampsPerChanRead = libpointer('int32Ptr',0);
    Reserved = libpointer('uint32Ptr',[]);
    
    % Start acquisitions
    calllib('myni','DAQmxStartTask',TaskCO);
    calllib('myni','DAQmxCfgDigEdgeStartTrig', TaskAI, 'PFI0', 10171);
    calllib('myni','DAQmxCfgAnlgEdgeStartTrig', TaskDO, 'APFI1', 10171, 0.5);
    calllib('myni','DAQmxStartTask',TaskDO);

 

I have an error (200452) at the last but one line for triggering Digital output on APFI1. I have a usb-6259 device.

Thanks,

Miko

Miko
0 Kudos
Message 5 of 9
(5,716 Views)

Miko,

 

The error (-200452) is happening because you are attempting to configure an analog trigger on a digital output task.  This is not supported on M Series devices.  Here is what I would recommend you do:

 

1) Use a dummy AO task to create a sample clock for TaskDO.  I recommend AO because this task type supports analog triggering on M Series.  The task can be configured as such:

float64 AOData[10];

DAQmxCreateTask("AO", TaskAO);

DAQmxCreateAOVoltageChan(TaskAO, Dev2/ao0, 'dummyAO', -10.0, 10.0, DAQmx)Val_Volts, "");

DAQmxCfgSampClkTiming(TaskAO, "", 16000, DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, NbSamples);

DAQmxCfgAnlgEdgeStartTrig(TaskAO, "APFI1", DAQmx_Val_Falling, 0.5);

DAQmxGetWriteRegenMode(TaskAO, DAQmx_Val_AllowRegen);

DAQmxSetAOUseOnlyOnBrdMem(TaskAO, true);

for(int32 i=0, i<10, i++)

{

   AOData[i] = 0.0;

}

DAQmxWriteAnalogF64(TaskAO, 10, false, 10.0, DAQmx_Val_GroupByChannel, AOData, &sampsWritten, NULL);

 

2) Change the following line:

calllib('myni','DAQmxCfgSampClkTiming',TaskDO,'/Dev2/ctr0InternalOutput',16000,int32(10280),uint32(10178),uint64(NbSamples));

to

calllib('myni','DAQmxCfgSampClkTiming',TaskDO,'/Dev2/ao/SampleClock',16000,int32(10280),uint32(10178),uint64(NbSamples));

 

3) Change

calllib('myni','DAQmxStartTask',TaskCO);

to

calllib('myni','DAQmxStartTask',TaskDO);

 

4) Remove all the TaskCO stuff.

 

If I understand what you're trying to accomplish, I think this will do as you need.  Additionally, the newer X Series family of data acquisition devices have a built in timer for digital input/output and do actually support analog triggers for these operations.

 

Hope that helps,

Dan

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

 

Hi Dan,

 

I tried your suggestion but I have the same error.

After that I even tried to trigger TaskDO on a digital signal with DAQmxCfgDigEdgeStartTrig, but I still get the same error.

 

Do you have another suggestion?

 

Thanks,

Miko

Miko
0 Kudos
Message 7 of 9
(5,699 Views)

Miko,

 

At what point are you seeing the error now?

 

Just to make sure we're on the same page, DO is no longer configuring a trigger at all, but rather using the Sample Clock from the AO task which is triggered, correct?

 

Dan

0 Kudos
Message 8 of 9
(5,676 Views)
Solution
Accepted by topic author Miko42

Hi Dan,

 

Sorry for the late reply.

I finally acquire the trigger and trigger my signal in post processing.

So, problem solved.

Miko

Miko
0 Kudos
Message 9 of 9
(5,593 Views)