Using a Python VISA API within IC-CAP for Instrument Control

Blog Post created by michea on Dec 13, 2017

Have you ever found yourself in a situation where the characterization software did not support the hardware you were trying to use?  Your tests may be complex, where the measurement conditions of your next data point depend on previous measurement results.  I have found that using Python integrated with the IC-CAP software leads to a powerful and flexible solution that is supported by an open community. To help with the test development, I have found it useful to create a software layer that handles error checking and low-level function calls. In what follows, I'll describe the use of a "PyVISAWrapper" that can simplify your test suite development.


My Motivation

I found myself in a tricky situation when I started using IC-CAP to characterize and model my memristor devices. I needed to perform a quasi-static measurement to precisely control the ramp rate of the voltage sweep by adding a hold time and source delay time, and to control the delay between measurements. However, in some tests, the measurement conditions for the next measurement in IC-CAP depend on previously measured values. Because of that, IC-CAP’s built-in, general-purpose instrument drivers didn’t support my need to perform a quasi-static measurement.


The solution I found to my dilemma was to write Python code in IC-CAP to control my instruments. The process builds on my previous post, Extending the Power of IC-CAP with Python - PyVISA Instrument Control. Using this process, you too can write Python code to control your instruments and create highly flexible measurement routines.


The PyVISA library turned out to be a great way for me to meet these goals, plus it enables portability across several control interfaces (e.g., GPIB and LAN). And, it was tempting for me to dive right in and start writing instrument specific commands using the default GPIB interface. Instead though, I took a step back and thought about how to make my Python code more general. To that end, I decided to create a wrapper for PyVISA’s low-level library functions that would allow me to send the most common VISA calls to control an instrument (e.g., open(), write(), read(), query(), etc.).


PyVISA Wrapper Utility

You might ask, “Why employ a wrapper utility to use the PyVISA library for instrument control?” It’s a fair question and the answer is pretty straightforward. The wrapper utility may be considered a high-level API for controlling instruments. With carefully constructed API function calls, an engineer can more easily create a suite of tests leveraging smarter I/O function calls, including writing instrument commands, querying responses, checking for command complete events, parsing the measurement data, checking for errors, and providing meaningful troubleshooting information.


What follows are details on how you can use an open source PyVISA wrapper utility I wrote called pyvisawrapper.py to simplify writing custom Python code to control almost any instrument. The example code provides the same functionality as the _init_pyvisa macro presented in my last article, but it also adds some useful features described above. The pyvisawrapper API facilitates communication with any instrument that uses TCP/IP or USB, in addition to the standard GPIB. Using the E5270B analyzer as an example instrument, I’ll revisit the _init_pyvisa macro and illustrate the advantages of using the pyvisawrapper functions over low-level function calls.



Since for this process, we’ll leverage the IC-CAP Python library, as well as the PyVISA library, using import statements, it’s important to make sure you have your Python environment configured correctly. Here’s a few of the basic prerequisites:

  1. Install IC-CAP_2016_01 or later, under Windows 7 in the default installation directory, which is typically C:\Keysight\ICCAP_2016_01.
  2. Install the Keysight IO Libraries 17.x software and configure it to use the VISA library visa32.dll. This dynamic link library will be installed in the C:\Windows\system32 directory.
  3. Configure and test communication with your instruments using the Keysight Connection Expert software.
  4. Before attempting this example, install and configure a virtual Python environment and install the PyVISA library presented in my aforementioned article, Extending the Power of IC-CAP with Python - PyVISA Instrument Control. Key to this process is the installation of a standalone Python interpreter, which will be great for developing experimental Python scripts and debugging in programming tools for making future modifications to your custom code, like pyvisawrapper itself, outside of the IC-CAP environment.
  5. Download and copy the pyvisawrapper.py script to your user directory. I personally like to create a sub-directory under my account C:/Users/username/iccap/python to store my own custom python code.
  6. Set the ICCAP_USER_PYTHON_PATH environment variable in your Windows 7 advanced systems settings to add this directory to the search path. This will allow IC-CAP to find your Python scripts.
  7. You will need some instruments that can be remotely controlled via GPIB or LAN. Any instrument will do.


Keysight E5270B with ASU



The following is a high-level overview of the code we are going to implement:

  • Test your new virtual Python environment installed as part of the prerequisites.
  • Create a new IC-CAP macro named _pyvisa_run.
  • Activate the virtual Python environment from your script.
  • Import the iccap.py and visa.py modules from the IC-CAP and virtual Python 2.7 environments.
  • Import the pyvisawrapper.py to use the high-level API functions in your macro.
  • Use the visaOpenSession() function to access the PyVISA ResourceManager
    and perform the VISA open() on the Keysight E5270B resource via the GPIB interface.
  • Use the visaCloseSession() to close the resource before exiting the script.
  • Use the visaQuery() function to send the *IDN? command to the E5270B and read its response.
  • Use the visaClear() function to perform a GPIB device clear and leave the GPIB interface in a initialized state.



Step-By-Step Process for Using pyvisawrapper


Step 1. Verify your new virtual Python environment

Verify the activated Python 2.7 environment by checking the system path 'sys.path' and system prefix 'sys.prefix.' To do this, open a Windows command shell and perform the following steps:

Activate the (icenv) virtual environment

C:\Users\username> workon icenv

(icenv) C:\Keysight\IC-CAP_2016_01\tools\win32_64>

Change the directory to virtual env (icenv)

C:\Users\username> cdvirtualenv

Check the Python interpreter version for (icenv)

(icenv) C:\Users\username\Envs\icenv> python -V

The version should return:

Python 2.7.3

Start the interactive Python interpreter for the virtual environment.

(icenv) C:\Users\username\Envs\icenv> python

You should see something like the following:

Python 2.7.3 (default, Feb 1 2013, 15:22:31) [MSC v.1700 64 bit (AMD64)] on win32

Type "help", "copyright", "credits" or "license" from more information.


Now, enter the following commands at the Python >>> interactive prompt:

>>> import sys 
>>> print sys.prefix

You should see something like the following:


Now type:

>>> print sys.path

You should see something like the following:


To exit the virtual Python interpreter type:

>>> quit()

(icenv) C:\Users\username\Envs\icenv>

Leave the virtual environment by typing:

(icenv) C:\Users\username\Envs\icenv> deactivate


If you made it this far then your icenv virtual Python environment is setup and ready to be used from IC-CAP.

Step 2. Start IC-CAP, then create a new model file and add a new macro

Go the the main IC-CAP menu and select File, then New. Name your model file ‘pypvisa_example’.


pyvisa example model file


Select the Macros tab and then click New… to create a new macro.


Enter _pyvisa_run for the name of the new macro.


_pyvisa_run python global macro


Step 3. Add variables to the IC-CAP Model Variable table

Select Model Variables and enter the following variables in the Model Variable table:


iccap model variable table

We'll describe each of these variables as follows.

  • The interface  variable should be set to the VISA resource string as listed under the My Instruments panel in Keysight Connection Expert or after performing a scan for instruments. This is also the string returned from PyVISA after sending the list_resources() function to the default resource manager.
  • The visaResponse variable holds the response string from the latest command sent to the instrument.
  • The error_status is a list of values to look for in the status byte register that would indicate an error.  This information should be available in the instrument's programming guide. In the case of the E5270B analyzer, the decimal value for the error status bit is 32. The error status could potentially be returned as 48 if the Set Ready bit is also active, or 128 if an emergency error is reported after the last command sent.
  • The error_command is the list of instrument specific commands necessary for returning the error code and the error message string from the instrument's message buffer. In our E5270B example, the error commands are "ERR?" and "EMG?", with "EMG?" being the command that is sent after processing the list of codes returned from the "ERR?" query. This command will return the error message string for the associated error code passed as a parameter when performing the query.  "ERR?" is the query that works with the B1500A to do extended error reporting. 


The pyvisawrapper code performs all of this detailed error checking for you!  This is incredibly handy.  Simply setting the debug variable to 1 in the Model Variable table will enable debug prints in the macro and pyvisawrapper, and output verbose debug text that is displayed in the IC-CAP Output window. This information will aid you in troubleshooting your Python code.


Step 4. Activate the virtual Python environment

Add the following two lines to your macro

activate_this = "/Users/username/Envs/icenv/Scripts/activate_this.py"
execfile(activate_this, dict(__file__=activate_this))

The "username" in the first line is the name of the current user logged into your Windows 7 machine. This generic name is a place holder for the commands listed below and represent the current user's home directory. 


_pyvisa_run activate virtual python environment


Step 5. Import the iccap.py functions and pyvisawrapper.py

Add the following two lines to your macro

from iccap import icfuncs as f, MVar 
from pyvisawrapper import *

_pyvisa_run macro python imports

Now we have access to all the functions in pyvisawrapper.py and iccap.py.


Step 6. Add some local variables and variables that access the Model Variable table

Add the following lines to your macro:

bOk = True                                          # return status of the called function 
cmd = ""                                            # command string
instr = MVar("interface").get_val()                 # visa resource to use from model var table
rsp = MVar("visaResponse")                          # visa response string from read or query
stat = MVar("error_status").get_val().split(",")    # status byte to check for error condition
err = MVar("error_command").get_val().split(",")    # error command to send to query error event
debug = MVar("debug").get_val()                     # enable/disable debug prints            
qdelay = 1.0                                        # delay for visa query

_pyvisa_run macro global variables

Here we are just reading variables from the IC-CAP model variable table and storing them to local Python variables.


Step 7. Use the high-level API function visaOpenSession to access the VISA Resource Manager and open a link to the E5270B resource

Add the following lines to your macro:

# open session and return visa resource link 
vl = visaOpenSession(instr)
if debug: print vl 

# close visa session
bOk = visaCloseSession(vl)
if debug: print "visaCloseSession: ",bOk

You should always close the VISA session when you are done with a resource. Not properly closing the session can cause errors if you attempt to re-open the same resource later.


_pyvisa_run open close session script lines


Execute your macro and you should see something like the following displayed in the IC-CAP Output window:

default source manager: Resource Manager of Visa Library at C:\Windows\system32\visa32.dll 
resources list: (u'ASRL10::INSTR', u'GPIB0::17::INSTR')

pyvisawrapper::visaOpen: True inst: GPIBInstrument at GPIB0::17::INSTR

GPIBInstrument at GPIB0::17::INSTR

pyvisawrapper::closeSession: True

visaCloseSession:  True

You did not need to import visa.py to access the VISA resources since pyvisawrapper.py handles that for you. It also handles calling the visa.ResourceManager() and visa.open() using your GPIB0:17::INSTR resource string specified in the Model Variable table.


If this step has errors, then you probably did not install and configure the GPIB VISA driver software application or the instrument is not on the bus. Otherwise the list will not return the GPIB resource with the address of your instrument. The communication drivers installed as part of the prerequisites allow you to 'scan for instruments.' National Instruments provides NI MAX (Measurement & Automation Explorer). Keysight interfaces provide Keysight Connection Expert. These software applications should be installed with your 488.2 and VISA drivers for your communications interface.


Step 8. Send your first command to the instrument to return its identifier string

Add the following lines to your macro:

cmd = "*IDN?" 
if bOk: bOk = visaQuery(vl, cmd, rsp, 10000, stat, err)
print "visaQuery: {} cmd returned {}".format(cmd, rsp.get_val().split(","))

_pyvisa_run ident query script lines

Execute your macro and you should see something like the following displayed in the IC-CAP Output window:

intr: GPIBInstrument at GPIB0::17::INSTR cmd: *IDN? rsp: <iccap.MVar instance at 0x000000000E11B608> 
timo: 10000 stat: 48 err: <iccap.MVar instance at 0x000000000E11B488>

pyvisawrapper::visaQuery() True read: Agilent Technologies,E5270B,0,B.01.10

bytes: 39 

pyvisawrapper::visaQuery: True *IDN? returned ['Agilent Technologies', 'E5270B', '0', 'B.01.10\r\n']

NOTE: The instrument was found on interface GPIB0 at address 17 and returned its identifier string in the visaQuery response.

Step 9. Do some clean up and leave the system in an initialized state

It is good practice to send a GPIB device clear before closing the interface.

To do that, add the following lines to your macro:

bOk = visaClear(vl) 

if debug: print "visaClear: ",bOK


_pyvisa_run visa clear script lines


Step 10. Test the completed _pyisa_run macro

Execute your macro and you should see something like the following displayed in the IC-CAP Output window:

default source manager: Resource Manager of Visa Library at C:\Windows\system32\visa32.dll 
resources list: (u'ASRL10::INSTR', u'GPIB0::17::INSTR')

pyvisawrapper::visaOpen: True inst: GPIBInstrument at GPIB0::17::INSTR

GPIBInstrument at GPIB0::17::INSTR
intr: GPIBInstrument at GPIB0::17::INSTR cmd: *IDN?
rsp: <iccap.MVar instance at 0x000000000C39DF08> timo: 10000 stat: 48 err: ERR?

pyvisawrapper::visaQuery() True read: Agilent Technologies,E5270B,0,B.01.10

bytes: 39 

pyvisawrapper::visaQuery: cmd *IDN? returned ['Agilent Technologies', 'E5270B', '0', 'B.01.10\r\n']

pyvisawrapper::clear: True inst: GPIBInstrument at GPIB0::17::INSTR 

visaClear: True
pyvisawrapper::closeSession: True
visaCloseSession: True

Example of pyvisawrapper's Error Processing

Now, let's look at an example of the pyvisawrapper.py error processing, which will help you find errors occurring in your code. Again, this is one of the real advantages of using the pyvisawrapper API. Without it, you would have to write instrument specific code in your Python script to detect, query and display any errors.


Let's purposely create an example of a common type of error such as sending an illegal argument or command to the instrument, and see how it is handled by the pyvisawrapper.  Let's change our macro slightly to send the command "ID?" instead of "*IDN?"


Change the following lines to your macro:

cmd = "ID?" 
if bOk: bOk = visaQuery(vl, cmd, rsp, 10000, stat, err)
print "visaQuery: {} cmd returned {}".format(cmd, rsp.get_val().split(","))

_pyvisa_run error gen script lines

See the error on line 20?

Execute your macro and you should see something like the following displayed in the IC-CAP Output window:

intr: GPIBInstrument at GPIB0::17::INSTR 
cmd: ID?
rsp: <iccap.MVar instance at 0x000000000BFF0348>
timo: 10000
stat: 48
err: ERR?
Query error VI_ERROR_TMO (-1073807339): Timeout expired before operation completed. - last command: ID?
visaQuery: cmd ID? returned ['visaError : 100 : Undefined GPIB command.\r\n']

With no error checking, we would only get the timeout error "VI_ERROR_TMO (-1073807339)".  That doesn't say much, does it?


What's Next?

If you've successfully completed all of these steps, then you should now be able to access the most common functions of PyVISA, the pyvisawrapper API from IC-CAP. And that means you can now very simply create new transforms for instrument control and data acquisition over any supported interface.

In a future article, I’ll outline the steps for using the ideas presented here to create a series of transforms to perform an Id versus Vg quasi-static measurement on a discrete NMOS device. In other forthcoming articles, I'll show you how to use more of the powerful features included in IC-CAP and exposed through the iccap.py. I'll also use the pyvisawrapper.py again to write Python code for accessing an instrument and returning measured results. I'll even show you how to access more of the internal IC-CAP functions and data structures, which are provided to enable additional analysis and plotting functions in IC-CAP.

In the meantime, I hope you find this tutorial and the pyvisawrapper utility useful in exploring the various possible ways you can extend IC-CAPs powerful framework to characterize and model your most challenging devices. For more information on IC-CAP or Keysight IO Libraries, go to www.keysight.com/find/eesof-iccap and www.keysight.com/find/IOlibraries.



About Python If you are new to Python programming, here’s some information to help you follow the steps in this blog. Python is an "interpreted" language, which means it generally executes commands typed by the user in an interactive command shell. This is convenient for testing program statements to learn the Python syntax. However, a more common means of writing a Python program is to create a Python script file with the '.py' extension. Say you created an example program and save it as 'example.py.' To run the program, you simply type 'python example.py' at the command shell prompt. Python scripts, which are often called modules, can also be used for creating libraries of functionality, and are distributed along with program resources in packages. Packages can be installed and combined with user-generated code to extend a program's functionality. PIP is the Python package installer that integrates with PyPI.org—the Python Package Index. It is a repository of numerous free Python applications, utilities and libraries. PIP allows you to download and install packages from the package index without manually downloading, extracting and installing the package via the command 'python setup.py install'. PIP also checks for package dependencies and automatically downloads and installs those as well. An environment is a folder (directory) that contains everything a Python project (application) needs to run in an organized, isolated manner. When it’s initiated, it automatically comes with its own Python interpreter—a copy of the one used to create it—alongside its very own PIP.




Extending the Power of IC-CAP with Python - PyVISA Instrument Control

Keysight IC-CAP Device Modeling Software

Keysight IO Libraries Suite

The Python Tutorial — Python 2.7.13 documentation

User Guide — virtualenv 15.1.0 documentation

PyVISA: Control your instruments with Python — PyVISA 1.8 documentation