Communicating with your instrument

Note

If you have been using PyVISA before version 1.5, you might want to read Migrating from PyVISA < 1.5.

An example

Let’s go in medias res and have a look at a simple example:

>>> import pyvisa
>>> rm = pyvisa.ResourceManager()
>>> rm.list_resources()
('ASRL1::INSTR', 'ASRL2::INSTR', 'GPIB0::14::INSTR')
>>> my_instrument = rm.open_resource('GPIB0::14::INSTR')
>>> print(my_instrument.query('*IDN?'))

This example already shows the two main design goals of PyVISA: preferring simplicity over generality, and doing it the object-oriented way.

After importing pyvisa, we create a ResourceManager object. If called without arguments, PyVISA will prefer the default backend (IVI) which tries to find the VISA shared library for you. If it fails it will fall back to pyvisa-py if installed. You can check what backend is used and the location of the shared library used, if relevant, simply by:

>>> print(rm)
<ResourceManager('/path/to/visa.so')>

Note

In some cases, PyVISA is not able to find the library for you resulting in an OSError. To fix it, find the library path yourself and pass it to the ResourceManager constructor. You can also specify it in a configuration file as discussed in Configuring the backend.

Once that you have a ResourceManager, you can list the available resources using the list_resources method. The output is a tuple listing the VISA resource names. You can use a dedicated regular expression syntax to filter the instruments discovered by this method. The syntax is described in details in list_resources(). The default value is ‘?*::INSTR’ which means that by default only instrument whose resource name ends with ‘::INSTR’ are listed (in particular USB RAW resources and TCPIP SOCKET resources are not listed). To list all resources present, pass ‘?*’ to list_resources.

In this case, there is a GPIB instrument with instrument number 14, so you ask the ResourceManager to open “‘GPIB0::14::INSTR’” and assign the returned object to the my_instrument.

Notice open_resource has given you an instance of GPIBInstrument class (a subclass of the more generic Resource).

>>> print(my_instrument)
<GPIBInstrument('GPIB::14')>

There many Resource subclasses representing the different types of resources, but you do not have to worry as the ResourceManager will provide you with the appropriate class. You can check the methods and attributes of each class in the Resource classes

Then, you query the device with the following message: '\*IDN?'. Which is the standard GPIB message for “what are you?” or – in some cases – “what’s on your display at the moment?”. query is a short form for a write operation to send a message, followed by a read.

So:

>>> my_instrument.query("*IDN?")

is the same as:

>>> my_instrument.write('*IDN?')
>>> print(my_instrument.read())

Note

You can access all the opened resources by calling rm.list_opened_resources(). This will return a list of Resource, however note that this list is not dynamically updated.

Getting the instrument configuration right

For most instruments, you actually need to properly configure the instrument so that it understands the message sent by the computer (in particular how to identifies the end of the commands) and so that computer knows when the instrument is done talking. If you don’t you are likely to see a VisaIOError reporting a timeout.

For message based instruments (which covers most of the use cases), this usually consists in properly setting the read_termination and write_termination attribute of the resource. Resources have more attributes described in Resources, but for now we will focus on those two.

The first place to look for the values you should set for your instrument is the manual. The information you are looking is usually located close to the beginning of the IO operation section of the manual. If you cannot find the value, you can try to iterate through a couple of standard values but this is not recommended approach.

Once you have that information you can try to configure your instrument and start communicating as follows:

>>> my_instrument.read_termination = '\n'
>>> my_instrument.write_termination = '\n'
>>> my_instrument.query('*IDN?')

Here we use ‘n’ known as ‘line feed’. This is a common value, another one is ‘r’ i.e. ‘carriage return’, and in some cases the null byte ‘0’ is used.

Note

For instruments that communicate over serial, you need to ensure you configure the correct baud rate. The default baud rate is set to 9600, but you should check your instrument’s manual to verify the correct value for your use case. If you wish to configure other serial instrument parameters, see Resource classes for a full list of attributes.

You can configure PyVISA to communicate to your instrument using a different baud rate as follows:

>>> my_instrument.baud_rate = 57600

In an ideal world, this will work and you will be able to get an answer from your instrument. If it does not, it means the settings are likely wrong (the documentation does not always shine by its clarity). In the following we will discuss common debugging tricks, if nothing works feel free to post on the PyVISA issue tracker. If you do be sure to describe in detail your setup and what you already attempted.

Note

The particular case of reading back large chunk of data either in ASCII or binary format is not discussed below but in Reading and Writing values.

Making sure the instrument understand the command

When using query, we are testing both writing to and reading from the instrument. The first thing to do is to try to identify if the issue occurs during the write or the read operation.

If your instrument has a front panel, you can check for errors (some instrument will display a transient message right after the read). If an error occurs, it may mean your command string contains a mistake or the instrument is using a different set of command (some instrument supports both a legacy set of commands and SCPI commands). If you see no error it means that either the instrument did not detect the end of your message or you just cannot read it. The next step is to determine in what situation we are.

To do so, you can look for a command that would produce a visible/measurable change on the instrument and send it. In the absence of errors, if the expected change did not occur it means the instrument did not understand that the command was complete. This points out to an issue with the write_termination. At this stage, you can go back to the manual (some instruments allow to switch between the recognized values), or try standards values (such as ‘n’, ‘r’, combination of those two, ‘0’).

Assuming you were able to confirm that the instrument understood the command you sent, it means the reading part is the issue, which is easier to troubleshoot. You can try different standard values for the read_termination, but if nothing works you can use the read_bytes() method. This method will read at most the number of bytes specified. So you can try reading one byte at a time till you encounter a time out. When that happens most likely the last character you read is the termination character. Here is a quick example:

my_instrument.write('*IDN?')
while True:
    print(my_instrument.read_bytes(1))

If read_bytes() times out on the first read, it actually means that the instrument did not answer. If the instrument is old it may be because your are too fast for it, so you can try waiting a bit before reading (using time.sleep from Python standard library). Otherwise, you either use a command that does not cause any answer or actually your write does not work (go back up a couple of paragraph).

Note

Some instruments may be slow in answering and may require you to either increase the timeout or specify a delay between the write and read operation. This can be done globally using query_delay or passing delay=0.1 for example to wait 100 ms after writing before reading.

Note

When transferring large amount of data the total transfer time may exceed the timeout value in which case increasing the timeout value should fix the issue.

Note

It is possible to disable the use of the termination character to detect the end of an input message by setting read_termination to "". Care has to be taken for the case of serial instrument for which the method used to determine the end of input is controlled by the end_input attribute and is set by default to use the termination character. To fully disable the use of the termination character its value should be changed.

The above focused on using only PyVISA, if you are running Windows, or MacOS you are likely to have access to third party tools that can help. Some tips to use them are given in the next section.

Note

Some instruments do not react well to a communication error, and you may have to restart it to get it to work again.

Using third-party softwares

The implementation of VISA from National Instruments and Keysight both come with tools (NIMax, Keysight Connection Expert) that can be used to figure out what is wrong with your communication setup.

In both cases, you can open an interactive communication session to your instrument and tune the settings using a GUI (which can make things easier). The basic procedure is the one described above, if you can make it work in one of those tools you should be able, in most cases, to get it to work in PyVISA. However if it does not work using those tools, it won’t work in PyVISA.

For serial instruments (true or emulated over USB), you can also try to directly communicate with it using Putty or Tera Term on Windows, CoolTerm or Terminal / screen on macOS.

Hopefully those simple tips will allow you to get through. In some cases, it may not be the case and you are always welcome to ask for help (but realize that the maintainers are unlikely to have access to the instrument you are having trouble with).