Modify XOP


I am hoping to establish RS-232 (with a USB-RS232 dongle, I know about the need to have the right FTDI chip in the dongle) communication with an Agilent 33250A function generator, mainly so I can send arbitrary waveforms to it which it can subsequently output to a microscope. I doubt I'll try to run the function generator from Igor aside from sending the waveforms.

It appears the VDT2 XOP would be appropriate for this task, but the available handshake protocols seem to be different from those available in VDT2.  The function generator can use DTR/DSR or RTS/CTS, whereas the "hardware handshaking" in VDT2 seems to something like CTS/DTR.  The function generator manual is attached and handshaking protocols are described on page 220.  I know XON/XOFF is supported by VDT2, but this protocol doesn't allow for transfer of waveforms.

To me, this suggests I need to modify the VDT2 XOP slightly, with the normal hardware handshaking signals just sent to different pins. My question, aside from any advice you might have on HOW to do this, is whether I am biting off more than I can chew here?  To give you a sense of my proficiency in Igor, I have never done anything with I/O and I am certainly no programmer, but I have been writing functions to load data from (generally ASCII) files and do various data analysis tasks within Igor, mostly pretty rudimentary, but still probably a couple hundred hours of writing simple code in Igor.

An alternative method is to purchase the NI USB-GPIB dongle and connect using GPIB protocol, which I know is supported by a different XOP, but that is $750 vs. maybe maybe $30 for the RS-232 dongle.  But I will convince my boss to let me buy that one if the alternative is burning a ton of hours trying to modify the VDT2 XOP.


Agilent 33250A.pdf

You might start by setting up comms without handshaking and using a low baud rate. If you find that you need handshaking, you can probably achieve what you need with a custom cable. Many RS232 cables don't even have all the handshaking pins connected! So grab a cable that has enough wires, cut it in the middle and connect the wires as appropriate.

I advise that you set up comms with the VDT dialog and try to do something really simple in the terminal window to get started.




Thank you Andy.  From a first pass through the links you sent and some googling, this seems like it should work with the USB-RS232 connection.  It's a little troubling there is no documentation of the VISA approach in the Agilent manual, but it looks like a ton of people have documented their issues on the NI forums using my exact function generator, so there is a decent amount of info out there to help me when I get to the inevitable troubleshooting phase of this.




Thank you Tony, once I get my hands on the USB-RS232 dongle I might try this.  This would certainly be the simplest approach.  I guess the problem is that the manual suggests sending long signals can be a problem with no handshaking, and the waveforms I will send are 64000 points.  I need to use all the data points since the waveforms I want to send will be a exponential functions, so I'd prefer as little interpolation of the waveform as possible.

The source code for VDT2 is part of the Igor XOP Toolkit so you can create your own version of it. But I don't recommend it.

It has been a long time since I looked at it and it was confusing even then, but I believe that the handshaking modes offered by VDT2 are the modes supported by the serial drivers on Macintosh and Windows.

The VDT2 operation buffer keyword allows you, in theory, to set the size of the serial input buffer, and it worked back in the dark ages. But nowadays the OS ignores the requested buffer size on both Macintosh and Windows. Execute this for details:

DisplayHelpTopic "Input Buffer Limitations"

I agree with the suggestions above to try it with no handshaking. Start with a low baud rate. In my experience, it will work with even high baud rates so long as you have called VDTReadBinary2 or VDTReadBinaryWave2 early enough.

I also agree that "If you find that you need handshaking, you can probably achieve what you need with a custom cable." However figuring out what is needed is non-trivial.



In reply to by jmcclimo2003

I used a pretty small range of commands, so my experience is limited. My takeaway is that once you get communication established, the programming of the unit is exactly like the RS-232, but with a VISA envelope.



I have tried the implementation suggested by Andy and it appears to work.  Igor can talk to NI VISA and NI VISA can talk to the function generator.  I tried running some code to send a waveform to the function generator, which showed that the function generator was receiving something, although at that point everything froze and Igor crashed.  I think the issue is that the commands are not terminated by carriage returns as required by the function generator SCPI language.  I tried setting this in the NI-VISA interactive controls, but it appears when you start a session from Igor this is a different session and just uses the default settings, which doesn't terminate commands with a carriage return.  I also just tried adding +"\r" to individual commands and this didn't seem to work either.

I tried adding viSetAttribute() to my code for the IO settings I need to change, and this works for a couple of them because I could find the relevant codes in the VISA.ipf file, but I could not find a relevant code for setting carriage return as the termination character.  I'm a little unclear why I can't just send the attribute strings I see in the NI-VISA interactive controls as I have had no success using viSetAttributeString() which always gives me an error.

Here's a copy of my little testing code with the viSetAttribute issue, in case anyone sees a way for me to set this:

Function SerialTestingCode()
Variable defaultRM, instr = 5, status
String resourceName = "ASRL3::INSTR"

viOpen(defaultRM, resourceName, 0, 0, instr)

    //These work
//status = viSetAttributeString(instr, VI_ATTR_ASRL_FLOW_CNTRL, "DTR/DSR")        //DTR/DSR flow control
status = viSetAttribute(instr, VI_ATTR_ASRL_FLOW_CNTRL, 4)        //DTR/DSR flow control
//status = viSetAttributeString(instr, VI_ATTR_ASRL_END_OUT, "Termination Character")            //end with termination character
status = viSetAttribute(instr, VI_ATTR_ASRL_END_OUT, 2)            //end with termination character
//viSetAttributeString(instr, VI_ATTR_SEND_END_EN, "VI_TRUE")   //send end on writes
viSetAttribute(instr, VI_ATTR_SEND_END_EN, 1)   //send end on writes

    //This one doesn't work
status = viSetAttributeString(instr, VI_ATTR_TERMCHAR, "0xD")                //end writes with carriage return
//status = viSetAttribute(instr, VI_ATTR_TERMCHAR, "0xD")                //end writes with carriage return

// Do something with instr
    //These don't work, but maybe because no carriage return at end, manually adding \r doesnt work
//VISAWrite instr, "SYSTem:LOCal"
//VISAWrite instr, "FREQ 1"
//VISAWrite instr, "*CLS" + "\r"




Thank you,


The help for Igor's viSetAttributeString function says:

viSetAttributeString does not correspond to a VISA library function of the same name. It corresponds viSetStringAttribute for ViString and ViRsrc-type attributes. As of this writing, VISA defines no read/write attributes of these types.

That was written a long time ago. I don't know if there are now any VISA attributes for which it applies.

The documentation for VI_ATTR_ASRL_FLOW_CNTRL says that its data type is ViUInt16, so viSetAttributeString would not apply for it.

The documentation for VI_ATTR_TERMCHAR says

When the termination character is read and VI_ATTR_TERMCHAR_ENis enabled during a read operation, the read operation terminates.

So I think it affects reads only, not writes.

It appears that VI_ATTR_ASRL_END_OUT sets the serial port terminator character for writes. It defaults to VI_ASRL_END_NONE. I recommend that you leave it that way and send the terminator character explicitly as part of the VISAWrite command.

Most instruments that I dealt with (in the previous millennium) expected either LF or CRLF terminators. HP (now Agilent) instruments used LF. The best approach is to try to find the required terminator in the documentation for the instrument. If that is not available, I would try "\n" and "\r\n".

I would try to get something simple working with no handshaking. VISAWrite could hang if the handshaking is wrong. Setting VI_ATTR_TMO_VALUE might help.



Thank you.  The approach you recommended works well.  At 4800 baud and no handshaking I was able to write a 64K point waveform with no problems after sorting out a few other things and working up from simple commands.

Here is some code that works with NI VISA and the Agilent 33250A, in case it is helpful to someone at some point.

Function SerialTestingCode2()
Variable defaultRM, instr = 5, status
String resourceName = "ASRL3::INSTR", FGoutput

viOpen(defaultRM, resourceName, 0, 0, instr)

    //These work

status = viSetAttribute(instr, VI_ATTR_ASRL_BAUD, 4800)     //4800 baud

// Do something with instr
//VISAWrite instr, "DATA:DELETE P_10 \n"
VISAWrite instr, "DATA:COPY RampSpdExp\n"
//VISAWrite instr, "FREQ 1\n"
//VISARead instr, FGoutput
//Print FGoutput
VISAWrite instr, "SYSTem:LOCal\n"



Function SerialWriteWave(ArbWave)
Wave Arbwave
Variable defaultRM, instr = 5, status
String resourceName = "ASRL3::INSTR"

viOpen(defaultRM, resourceName, 0, 0, instr)

//Set up IO attributes: no handshaking (default), slow baud rate
status = viSetAttribute(instr, VI_ATTR_ASRL_BAUD, 4800)     //4800 baud

// Write Wave

//VISAWrite instr, "DATA VOLATILE, 1, .67, .33, 0, -.33, -.67, -1\n"
VISAWriteWave/F={"%f", ",", "", "" } instr, ArbWave
VISAWrite instr, "\n"







Igor Pro 8

Learn More

Igor XOP Toolkit

Learn More

Igor NIDAQ Tools MX

Learn More