NIDAQ scan wave not updating during procedure

I created a procedure using NIDAQ Tools and SOCKIT to allow me to send a waveform to an instrument, capture a synchronized response from the instrument, and also send text commands to the instrument using SOCKIT at particular points during the output waveform which I know in advance.  To synchronize the text commands to the NIDAQ output, I created wave that goes from -1V when I want a certain instrument state to be active, to +1 V when I want the other instrument state to be in place. I then output this waveform with a waveform generation command, which I feed back to a NIDAQ input with a BNC cable.  The scan wave I read is initialized at 0V, and the idea is that when the scan wave is written, when the voltage goes to +1V at the point in the waveform it is supposed to a command will be sent to the instrument to switch states.  Likewise when -1V is read during the scan the state should switch back.

The problem is that it appears that the scan wave (XFB) is not actually updated in the data browser until the code is finished, and of course the code never finishes because the loop looking for the voltage change in the relevant index position of XFB never changes. I confirmed this with a breakpoint. XFB is all zeros when the breakpoint is reached.  If I comment out the block with the loops, the code finishes and I can watch XFB slowly populate as a background process during the scan as expected.

Is there a way to make the scan wave update while the code is still running in an essentially empty loop? Is there a smarter way to synchronize with the NIDAQ output?

Here is the relevant code:

Function RunVSTestwFB(WGwave,XFBwave,HoldTime)
Wave WGwave,XFBwave
Variable HoldTime
String WGwavePath = GetWavesDataFolder(WGwave, 2)
String XFBwavePath = GetWavesDataFolder(XFBwave, 2)
    //String WGwavePath
String WGParamString = WGwavePath+",0;"+XFBwavePath+",1"

    //start TCP comms
make/t buf
variable sockitID
SOCKITopenconnection/NOID sockitID, "127.0.0.1", 12600, buf

//Wave XFB
Make/N=(numpnts(WGwave)*deltax(WGwave)*8*1000+2000) LF, XFB
XFB=0
SetScale/P x, 0,0.001, "s", LF
SetScale/P x, 0,0.001, "s", XFB
    //Set up data acq
DAQmx_Scan /DEV="dev1"/AVE=100/BKG/TRIG={"/Dev1/ao/StartTrigger"} WAVES="LF, 0/DIFF,-0.5,0.5;XFB,1/DIFF,-2,2"
    //set up waveform generation
DAQmx_WaveformGen /DEV="dev1" /NPRD=8  WGParamString            //8 periods of waveform and trigger wave XFB
if (GetRTError(1)) // 1 to clear error and continue execution
    print "Error starting scanning operation"
    print fDAQmx_ErrorString()
endif




    //wait for trigger to flip FB
variable n=0
variable i=120*2/50*1000    //for start of 1st hold time

do
    do
    n=XFB[i+3]
    while(n < 0.5)      //wait for XFB wave to flip to +1V during scan
    SOCKITsendmsg sockitID, "SetHWParameter, Lockin 1,PI1-1 Tip Control, Unlimit"    //turn on FB
    i=i + HoldTime*1000
    do
    n=XFB[i+3]
    while(n > -0.5)     //wait for XFB wave to flip to -1V during scan
    SOCKITsendmsg sockitID, "SetHWParameter, Lockin 1,PI1-1 Tip Control, Freeze"    //turn off FB
    i=i + 120*4/50*1000
while( i < numpnts(XFB)  )      //repeat until end of wave



SOCKITcloseconnection(sockitID) //close TCP/IP connection
end

 

NIDAQ Tools MX transfers data from the internal NI-DAQmx buffer to your wave while Igor's idle loop is active. During a user function, the idle loop is not active. You can ask Igor to do the XOP's idle activity by adding a call to DoXOPIdle inside your loop. This may slow down execution.

Ugh, I see now that you warn about this exact problem in the NIDAQ Tools manual.  In any case, thanks so much, everything works now.  There does seem to be a delay of about 60-90ms from when XFB changes state to when the instrument implements the changed state, but I'd expect that delay is mostly due to the TCP/IP communication with the instrument taking some time rather than the loop itself.  The delay seems relatively constant so I can probably compensate for it elsewhere.

 

Here is the slightly modified code in case its helpful to anyone else:

Function RunVSTestwFB(WGwave,XFBwave,HoldTime)
Wave WGwave,XFBwave
Variable HoldTime
String WGwavePath = GetWavesDataFolder(WGwave, 2)
String XFBwavePath = GetWavesDataFolder(XFBwave, 2)
    //String WGwavePath
String WGParamString = WGwavePath+",0;"+XFBwavePath+",1"

    //start TCP comms
make/t buf
variable sockitID
SOCKITopenconnection/NOID sockitID, "127.0.0.1", 12600, buf

//Wave XFB
Make/N=(numpnts(WGwave)*deltax(WGwave)*8*1000+2000) LF, XFB
XFB=0
SetScale/P x, 0,0.001, "s", LF
SetScale/P x, 0,0.001, "s", XFB
    //Set up data acq
DAQmx_Scan /DEV="dev1"/AVE=100/BKG/TRIG={"/Dev1/ao/StartTrigger"} WAVES="LF, 0/DIFF,-0.5,0.5;XFB,1/DIFF,-2,2"
    //set up waveform generation
DAQmx_WaveformGen /DEV="dev1" /NPRD=8  WGParamString
if (GetRTError(1)) // 1 to clear error and continue execution
    print "Error starting scanning operation"
    print fDAQmx_ErrorString()
endif




    //wait for trigger to flip FB
variable n=0, k
variable i=120*2/50*1000    //for start of 1st hold time

do
    do
    DoXOPIdle
    n=XFB[i+5]
//  n=WaveMax(XFB,pnt2x(XFB,i-50),pnt2x(XFB,i+50))      //2nd method to do same thing, maybe slower though
    while(n < 0.5)      //wait for XFB wave to flip to +1V during scan
    SOCKITsendmsg sockitID, "SetHWParameter, Lockin 1,PI1-1 Tip Control, Unlimit"    //turn on FB
    FindLevel/P/EDGE=1/R=[i-50,i+50] XFB,0
    i=V_LevelX + HoldTime*1000
    do
    DoXOPIdle
    n=XFB[i+5]
//  n=WaveMin(XFB,pnt2x(XFB,i-50),pnt2x(XFB,i+50))
    while(n > -0.5)     //wait for XFB wave to flip to -1V during scan
    SOCKITsendmsg sockitID, "SetHWParameter, Lockin 1,PI1-1 Tip Control, Freeze"    //turn off FB
    i=i + 120*4/50*1000
while( i < numpnts(XFB)  )      //repeat until end of wave



SOCKITcloseconnection(sockitID) //close TCP/IP connection
end

 

Glad I could help. The need for DoXOPIdle is unexpected, so it's easy to miss when you first read.

Generally, if latency and timing accuracy are important, it's best if you can do the timing entirely in hardware. But it kind of looks like your situation doesn't permit that since you have to send a text command to your instrument.