
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.
July 14, 2020 at 10:32 am - Permalink
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:
July 14, 2020 at 12:19 pm - Permalink
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.
July 14, 2020 at 01:20 pm - Permalink