LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Problem with DAQmx acquisition timing using EveryNSamplesEvent

    I am writing code using LabWindows/CVI 8.1 (with a PCIe-6361 card) that acquires data from a system under test. The pertinent code is attached. For test purposes, I have a signal generator sending a 30 Hz ramp function to the analog input, with a TTL trigger pulse at the start of each cycle. An NI-DAQmx task is set up in MAX with the following parameters: sample rate is 30kHz, samples to read = 1k, mode = N samples, Start trigger = digital edge on PFI0, rising edge, no reference trigger.Things work fine when I use the MAX test panels.

    The software is set up using the "(DAQmxRegisterEveryNSamplesEvent " technique. I have a handler routine ("CB_ReceiverDataRdy", at the very end of the attached file) that reads the data from the board using "DAQmxReadAnalogF64" and puts it into a buffer for display.

 

The task is initialized as follows

 

    DAQmxStatus = DAQmxLoadTask (ReceiverTask.TaskName, &ReceiverTask.DAQTask_Handle);
    ...   

   activeTask = ReceiverTask.DAQTask_Handle;
    
    //set trigger characteristics
    DAQmxErrChk (DAQmxSetTrigAttribute (ReceiverTask.DAQTask_Handle, DAQmx_StartTrig_Retriggerable, 1));
    
    //Initialize task: initialize local buffers to the same size as the internal ones in DAQmx
    DAQmxErrChk (DAQmxGetBufferAttribute (ReceiverTask.DAQTask_Handle, DAQmx_Buf_Input_BufSize,  &defaultBufferCount));
     DAQHNDLR_AllocateBuffers(&ReceiverTask, defaultBufferCount);
     ...   
    //register data handler callbacks
    //DAQmx_Val_SynchronousEventCallbacks
    DAQmxErrChk(DAQmxRegisterEveryNSamplesEvent (ReceiverTask.DAQTask_Handle,
                                                 DAQmx_Val_Acquired_Into_Buffer,
                                                 defaultBufferCount,
                                                 DAQmx_Val_SynchronousEventCallbacks,
                                                 CB_ReceiverDataRdy, NULL));

 

The DAQmxWriteDigitalU8 statements inside of the //debug markers put out a trigger pulse to monitor things on an o'scope. They show quite nicely that CB_ReceiverDataRdy takes about 3ms to complete.

 

The problem is that CB_ReceiverDataRdy only gets called every 4 to 5 seconds, where it should get called at 30 Hz, or thereabouts. I've tried adding and removing the DAQmx_Val_SynchronousEventCallbacks constant in "DAQmxRegisterEveryNSamplesEvent", and just about everything else that I can think of.

 

Misc info: DAQHNDLR_Init and DAQHNDLR_Close are called when the main program starts and ends; DAQHNDLR_InitTask is called when the program opens the panel that needs data acquisition; DAQHNDLR_StartDAQ  is called when the user presses the "start" button. At the moment, the only thing done with this data is display on an "o'scope" type display, but there will be further processing added later.

 

Any help greatly appreciated.

Download All
0 Kudos
Message 1 of 10
(4,594 Views)

Another interesting datum: apparently there is no good correlation between the incoming data pulse and when the "CB_ReceiverDataRdy" callback routine gets called. Despite the triggering setup in MAX, which acquires properly, the hardware trigger is being ignored. Huh?

0 Kudos
Message 2 of 10
(4,591 Views)

When I call

DAQmxSetTrigAttribute (ReceiverTask.DAQTask_Handle, DAQmx_StartTrig_Retriggerable, 1));

just after I load the DAQmx task, does this delete every other attribute set up in MAX for the trigger? This is the only thing that I can think of that could be producing this behavior.

0 Kudos
Message 3 of 10
(4,590 Views)

Duplicate post.

Matt
Applications Engineer
National Instruments
0 Kudos
Message 4 of 10
(4,545 Views)

The problem seemed to be one of timing; I wasn't allowing quite enough time after the conclusion of a sample acquisition. I fixed a few things and sped up the acquistion rate so that I could be absolutely sure that an acquisition would finish before a new trigger came along and now things seem to be working well. Apparently something in this system has real problems if a trigger comes along before a previous acquisition is done. It does not just skip the trigger and wait for the next one.

0 Kudos
Message 5 of 10
(4,440 Views)

Ok, now this thing is driving me nuts. The parts work separately, but when combined into the final program it falls apart. I've attached a copy of the data acquisition module, with a little program that lets me exercise it. The test setup is a signal generator, putting out a 12 Hz sawtooth (approx 40 millisecond each rising then falling) with a trigger pulse synchronized to the rising slope. The "Receiver" task is setup in MAX for 50 kHz acquistion, triggered on the rising edge of a digital pulse coming into PFI0, 1000 samples. So, one acquisition should run for 20 ms. I should see  20 ms of the sawtooth rising edge, starting at the breakpoint.The sawtooth goes from approximately -60mV to 160 mV (it's not the best signal generator in the world).

 

I'm also looking at the signal with an o'scope, and have the program generating a little pulse in the DAQ_Handler callback routine, "CB_ReceiverDataRdy", that gets called whenever DAQmx has data to be processed. so, I can see precisely when ReceiverDataRdy is being called and how long it takes to run through. This includes the call to the routine, from within ReceiverDataRdy, that plots the data to the screen and the whole routine takes about 10 ms to handle the data (although this seems to depend heavily upon the graph scale and how much data is being displayed).

 

The test program runs fine, ripping right through the data (of course it doesn't do anything with it), and the retriggering works fine. I see an pulse from the test output with every waveform cycle.

 

When I put it into the main program, though, the triggering goes to pot. I still get 1000 samples nicely, and ReceiverDataRdy is called when done, but I get a sample set every 4 (four) seconds or so, and it has lost synchronization with the trigger pulse. See picture in attached, which should be a nicely rising line starting at -60 mV. The display on the o'scope correlates nicely with the screen display - what I'm seeing is the 20ms prior to the time that ReceiverDataRdy is called by DAQmx. But I have no clue as to what is triggering the acquisition, or where the process is going for the 3 to 4 seconds between acquisition runs.

0 Kudos
Message 6 of 10
(4,431 Views)

Here's another screen shot. The acquistion drifts over time, now I can see the peak of the sawtooth - right where it should be, BTW.

0 Kudos
Message 7 of 10
(4,429 Views)

Hi Pblase,

 

If you’re having trouble identifying what part is taking longer than expected; can you pull a system time at different parts of your code? You can use that difference to see what portion is taking longer. It sounds like some portion or analysis in your full code is holding up the rest of your code.

Matt
Applications Engineer
National Instruments
0 Kudos
Message 8 of 10
(4,375 Views)

One question I have is: Where in the process does the NI-DAQmx acquisition engine decide to arm the board again for the next set of data. I have the MAX DAQmx Task set to acquire 1000 points at 50 kHz. It should, therefore, call the callback routine "CB_RecieverDataRdy" at most every 20 ms.  Does DAQmx re-arm the PCIe-6361 when the routine calls DAQQmxReadAnalogF64 to get the data, or when CB_RecieverDataRdy returns? If the former, then the time necessary to process the data does not cut into the acquisition cycle time, if the latter than it does.

0 Kudos
Message 9 of 10
(4,355 Views)

Found it. (and I'd like to recommend a small change in NI-DAQmx) In some old code elsewhere in the program the software changed the DAQmx Trigger Attribute "DAQmx_StartTrig_DelayUnits" from "ticks" to "seconds". Unfortunately, when DAQmx does this it does not adjust the actual delay value accordingly. The default value for the trigger delay is 4 ticks, a few microseconds; the call switched this to 4 seconds.

0 Kudos
Message 10 of 10
(4,328 Views)