Trouble using two xops in a loop (Sockit + nidaqmx)

Hi,

I'm having trouble understanding where a delay is coming from in my igor code and was hoping that someone can shed some light on how XOPs work with IGOR. I'm using the nidaqmx xop to communicate with an NI DAQ card as well as the sockit xop to send *TRG commands to an external pulse generator (used as a master trigger for a whole rack of equipment). The important chunk of code is below:

for(avgs = 0; avgs<shots; avgs +=1)
        DAQmx_Scan/DEV="pxi6289"/AVE=1/TRIG={("/pxi6289/PFI0"),1,0}/bkg=1  WAVES=("scaleddaqwave, 1/DIFF FL={1,0};") //sample rate taken from x scaling of first wave in list
       
        if (GetRTError(1))  // 1 to clear error and continue execution
            print "Error starting scanning operation"
            print fDAQmx_ErrorString()
        endif
        sockitsendmsg/time=(.001) mtaddress, "*TRG\r\n"
        fdaqmx_scanwait(daqname)
        fDAQmx_ScanStop(daqname)
        doupdate

        scaleddaqwave = scaleddaqwave * scalefactor
endfor


This acquires 10ms of data and the loop takes only about 15ms to complete for the first iteration then jumps to around 250ms for subsequent iterations. If I remove the DAQmx_Scan operation I can just send software triggers to the pulse generator and I get triggers out every 2ms as measured using an oscilloscope. I can also remove the software trigger and set the pulse generator to run untriggered and the DAQmx_scan returns a fresh trace every 20-30ms.

So I guess my question would be how does IGOR deal with calling multiple xops in a single loop and is there something like a 200ms overhead to loading or switching xops? If so is there any way around it?

Any help would be appreciated, I've tried about everything I can think of and just can't get the code to run faster than about 4-5 Hz.

Thanks!
I don't think the delay has anything to do with how Igor calls XOPs. If you comment out the call to sockitsendmsg, I suspect you will see the same delay.

I would expect DoUpdate to slow things down, but I suspect that the delay has to do with fdaqmx_scanwait. Try commenting both out.
In addition to what HRodstein says, you shouldn't need the call to fDAQmx_ScanStop(). The call to fDAQmx_ScanWait() should guarantee (unless there is a scanning error) that the scan has finished, so you don't need to stop the scan.

Another possible source of delay is creating a scanning task and setting it up every time through the loop. You might have better luck using DAQmx_Scan/RPT. To do this you may need to re-organize your code to use /RPTH to run whatever code needs to run when each wave is acquired.

You say trigger pulses are coming every 2mS, but the scan takes 20? So there are 10 trigger pulses during a single scan?

How much data is being acquired? We can't tell from your code how big the wave scaleddaqwave is, or what the sample rate is. If the wave is quite large, and it is displayed in a graph that is re-drawn every time through the loop, that could be slowing things down.

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
Thanks for the quick responses.

hrodstein: I tried commenting out the sockitsendmsg command and the loop runs fast (10.8ms to acquire 10ms of data). Here is the puzzling part. If I remove the DAQmx commands and run the loop with only the sockitsendmsg command the loop still runs fast and I measure triggers coming out of my pulse generator with a period of about 2ms - as measured using the oscilloscope. Things only get slow when I try running both.

John: The DAQ is collecting 10ms of data at 200 ks/s. I've tried removing the doupdate but it didn't help. I will look into using the /RPT flag but I'm a little worried that there is a more subtle source of the delay.

Thanks!
Anthony
I suspect that the generation of the trigger is somehow impacting the behavior of NIDAQ. Try changing the sockitsendmsg command so that it sends a message that does nothing.
Just a quick update: I tried using the /rpt flag with a /rpth to a function calling the sockitsendmsg as shown below.

Now to start the acquisition I simply run:

DAQmx_Scan/DEV="pxi6289"/AVE=1/TRIG={("/pxi6289/PFI0"),1,0}/rpt=(shots)/rpth="processtrace()"  WAVES=("scaleddaqwave, 1/DIFF FL={1,0};") //sample rate taken from x scaling of first wave in list

function processtrace()
    variable/g agt1id
    sockitsendmsg/time=(.002) agt1id, "TRIG1\n"
    doupdate
end


But this still only runs at 4-5 Hz. Note: i've also tried removing the doupdate with no improvement.

Any other suggestions?
Interesting...

Things are still slow when using sockit and a blank message. However I tried hooking up the signal generator using gpib and when I send *TRG using the gpibwrite2 command things speed up to around 10ms per acquisition. So maybe this is an issue with sockit? I ultimately want to avoid GPIB for ground loop reasons. Any ideas?

Anthony
What sort of device is your pulse generator? Perhaps you could use NIDAQ Tools MX to generate your pulse- see DAQmx_CTR_OutputPulse. If you need a lot of current, you might use the NIDAQ pulse to trigger your pulse generator. Kind of indirect, but it would probably work. And it eliminates using a networking call to send a message to your device.

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
Some comments on SOCKIT.
- It would be worth you pinging the oscilloscope to see what kind of overhead you get communicating with the device.
- SOCKIT picks up incoming asynchronous messages from its connections when Igor sends it an IDLE message. This is when Igor is not doing anything, or when a DoUpdate is used. If there is a significant amount of incoming traffic from the oscilloscope then processing those incoming messages can take some time. Does the oscilloscope send a lot of return information to SOCKIT?
- SOCKITsendmsg is an operation designed to send something to a socket and immediately return control (without waiting for a reply). The XOP will wait for up to /TIME=timeout seconds to deliver the message (as in your original message), if it delivers before that then it will return immediately. If it doesn't succeed in delivering the message then it will set an error flag (the error variable is created regardless). I note that you don't check for the error flag in your original code.

Perhaps 0.001 seconds is a pretty tight tolerance for tcp communication. Try relaxing to e.g. 0.1 s. The sockitsendmsg will communicate with the oscilloscope as fast as the TCP stack allows, there is no other delay in the sockit XOP. I would remove the Doupdate as well.