Build an instrument-control library for Python

Article By : Marc van Veenhuizen & Jinbo Wan

Downloadable code provides examples for a Keithley 2400 source-measure unit.

Python is powerful, extendable, intuitive programming language that you can use to automate test equipment. PyVISA is one of Python’s many libraries that extend its power to communicate with electronic instruments over interfaces such as GPIB, USB, and Ethernet. At NXP we’ve automated many tests using Python and we’ll show you, through downloadable code samples, how to set up tests using a source-measure unit (SMU) as an example.

As electrical failure-analysis engineers, we found ourselves spending considerable time arranging, tuning, and testing test setups before applying them to verify ICs reported to have failed. After the measurements, the setup would typically be broken down because a next IC failure would likely need a completely different configuration. We often found that we’d need a similar setup for another failure and needed to store the setup information and reuse it. That’s when we decided to build an instrument control library in python.

Most test instruments use the Standard Commands for Programmable Instruments (SCPI) communication protocol. Two EDN articles, from Fabrizio Guerrieri and Martin Rowe, both described applications of PyVISA for automating measurements. In this article, we discuss how to build a python library on top of PyVISA with features that facilitate arranging and reusing measurement setups.

We built an instrument-control library using object-oriented programming, with each instrument forming an individual object. These objects are represented by classes whose member functions in this case implement the various SCPI commands and combinations of commands. Consider the following code snippet for the class for the Keithley 2400 SMU (Listing 1).

textListing 1

In this code, Keithley2400 is an instrument class specifically for the 2400 SMU, inheriting member functions from the generic scpi class ScpiGeneric. We wrote the ScpiGeneric class to implement the standard commands that most instruments support, such as querying the instrument ID or resetting the instrument. Many of the Keithley2400 class member functions are straightforward so-called getters and setters. These can be optimized to also do some value checking, which minimizes errors on the instrument. In an actual program, these functions can configure the instrument according to user-specified input. A great way to define such input is by using xml-files, as in Listing 2.

Listing 2

The various markup elements such as “<address>” can be used to store values for corresponding variables in the actual python program. The program would then parse the xml, extract the values, and pass them to the instrument. The python function in Listing 3 does just that.

textListing 3

The function initKeithley2400 receives as input an element node in an xml-tree, i.e. “child”, and an instance of a Keithley2400 class, i.e. “smu”. It then finds the address element of the instrument in the xml-file. In the last line, it initializes the instrument according to the values found from the xml.

Apart from xml, there are other ways to provide input to the program such as by using Excel or INI files. With xml, the input data can easily be structured hierarchically, improving its readability and robustness.

We recommend that when the measurement program parses the xml file, you save the parsed xml as a new file with similar name as that of the output data file. In that way, you store instrument settings for easy inspection and use. Doing so preserves the information about the setup, which is reflected by the input xml.

In our lab, instruments are in use all the time. At many times, no Keithley 2400 is available. Instead, an SMU of a different type is free. The instrument class of the latter will be different that that of the 2400. Fortunately, we have several options for handling this complication. The program could, for example, query the interface to find which instruments are available. Based on that information, the program can initiate the appropriate instrument class. This technique works because most instruments support asking for the instrument ID is a standard command. Another way to make the program work for different types of instruments is to employ metaclasses. An object is an instance of a class. The class “smu” is a class is in fact an instance of a metaclass. For increased flexibility we represent instruments by metaclasses, which are instantiated at runtime to a particular instrument class type as defined in the xml-file. Listing 4 shows how we define such a metaclass.

textListing 4

The following snippet (Listing 5) shows how the instrument type, i.e. class, can be defined in xml:

Listing 5

The python code in Listing 6 instantiates the metaclass and class.

Listing 6

Software code for test sutomation is typically checked for bugs before launch through unit testing. Doing so means running individual functions and checking their results against expected outcomes. If you see a deviation while testing, let the software developer know where to find the function causing the fail. When applying unit testing for developing instrument-control software, you need to simulate the instruments to get a response. This can be done with the PyVISA-sim Back-end. Namely, PyVISA does not talk directly to instruments, but uses a back-end for that, such as NI-VISA, the VISA library from National Instruments, or PyVISA-py, the linux VISA library, both of which implement direct communication to instruments. PyVISA-sim is a different back-end that basically simulates instruments. As input PyVISA-sim expects a yaml-file that lists the queries to and responses from the instrument. A yaml fragment for a simulated Keithley 2400 is shown in Listing 7.

Listing 7

The xml-file then would specify that the instrument is being simulated, as in Listing 8.

Listing 8

These simulated instruments not only help with unit testing, but for demonstration purposes as well.

Following the above described approach, we’ve developed a complete program that applies a Keithley 2400 to measure the resistance of a DUT and a Keithley 2000 to measure the temperature with a thermocouple. You can use this program to run a resistance vs temperature sweep measurement as schematically depicted in Figure 1.

textFigure 1. A Keithley 2400 SMU provides excitation and measurements for the DUT while a Keithley 2000 DMM measures the temperature.

You can further improve the automation by adding control over the hot chuck. The initialization of the instruments can be extended to rely less on the default instruments’ default parameters.

In summary, we have shown how to develop a python instrument control library using the following approach:

  • Object-oriented programming to define classes for instruments
  • xml-files to pass instrument settings
  • metaclasses to generalize the actual measurement program
  • Simulated instruments for unit testing of the software code

All files related to this work are available in You can use them to further develop a python instrument control library for your lab.


We are indebted to Oliver Dial and Gary Steele who originated many of these ideas.

Marc van Veenhuizen is principal failure analysis engineer at NXP Semiconductors, and Jinbo Wan is a failure analysis engineer at NXP Semiconductors.

Leave a comment