There was a time when instruments sporting a GPIB connector (General Purpose Interface Bus) for computer control on their back panels were expensive and exotic devices, unlikely to be found on the bench of a hardware hacker. Your employer or university would have had them, but you’d have been more likely to own an all-analogue bench that would have been familiar to your parents’ generation.
The affordable instruments in front of you today may not have a physical GPIB port, but the chances are they will have a USB port or even Ethernet over which you can exert the same control. The manufacturer will provide some software to allow you to use it, but if it doesn’t cost anything you’ll be lucky if it is either any good, or available for a platform other than Microsoft Windows.
So there you are, with an instrument that speaks a fully documented protocol through a physical interface you have plenty of spare sockets for, but if you’re a Linux user and especially if you don’t have an x86 processor, you’re a bit out of luck on the software front. Surely there must be a way to make your computer talk to it!
Let’s give it a try — I’ll be using a Linux machine and a popular brand of oscilloscope but the technique is widely applicable.
It’s easy with a VISA
We are fortunate in that National Instruments have produced a standard bringing together the various physical protocols and interfaces used, and their VISA (Virtual Instrument Software Architecture) is available as precompiled libraries for both Windows and Linux(x86). Talking to VISA is a well-trodden path, for example if you are a Python coder there is a wrapper called PyVISA through which you can command your instruments to your heart’s content. And if you’ve spotted the glaring gap for architectures with no NI VISA library, they’ve got that covered too. PyVISA-py is a pure Python implementation of VISA that replaces it.
As a demonstration, we’ll take you through the process of using PyVISA-py and PyVISA on a Raspberry Pi for basic communication with an instrument over USB. We’ve used both a Raspberry Pi Zero and a Raspberry Pi 3 each running the latest Raspbian distro, but a similar path should apply to most other Linux environments and like instruments. Our instrument here is a Rigol DS1054z oscilloscope.
We start by installing the Python libraries for USB, PyVISA-py, and PyVISA. We’re assuming you already have python and pip, if not here’s a page detailing their installation. Type the following lines at the command prompt:
sudo pip install pyusb
sudo pip install pyvisa
sudo pip install pyvisa-py
You should now be able to test the installation from the Python interpreter. Make sure the instrument is both turned on and connected via USB, and type the following:
This should give you a version and copyright message for Python, followed by a three-arrow >>> Python interpreter prompt. Type the following lines of Python:
resources = visa.ResourceManager('@py')
The first line imports the VISA library, the second loads a resource manager into a variable, and the third queries a list of connected instruments. The ‘@py’ in line 2 tells the resource manager to look for PyVISA-py, if the brackets are empty it will look for the NI VISA libraries instead.
If all is well, you will see it return a list of resource names for the instruments you have connected. If you only have one instrument it should be similar to the one that follows for our Rigol:
The part in the single quotes, starting with USB0:: is the VISA resource name for your instrument. It is how you will identify it and connect to it in further code you write, so you will either need to run the Python code above in your scripts and retrieve the resource name before you connect, or as we are doing in this demonstration copy it from the prompt and hard-code it in the script. Hard-coding is not in any way portable as the script may only work with your particular instrument, however it does provide a convenient way to demonstrate the principle in this case.
If you are still within the Python interpreter at this point, you can leave it and return to the command prompt by typing a control-D end-of-file character.
Towards Something More Useful
Assuming all the steps in the previous paragraphs went smoothly, you should now be ready to write your own code. We’ll give you a simple example, but first there are a couple of pieces of documentation you’ll want to become familiar with. The first is the PyVISA documentation, the same as we linked to earlier, and the second should be the programming reference for your instrument. The manufacturer’s website should have it available for download, in the case of our Rigol it can be found as a PDF file (Click on the “Product manuals” link at the top).
The PyVISA manual details all the wrapper functions and has a set of tutorials, while the product manual lists all the commands supported by the instrument. In the product manual you’ll find commands to replicate all the interface controls and functions, but the ones we are most interested in are the measurement (MEAS) set of commands.
For our example, we’ll be measuring the RMS voltage on channel 1 of our Rigol. We’ll connect to the instrument directly using its resource name and querying it for its model identifier, before selecting channel 1 and querying it for an RMS voltage reading.
Copy the following code into a text editor, replacing the resource identifier with that of your own instrument, and save it as a .py file. In our case, we saved it as query_rigol.py.
#Bring in the VISA library import visa #Create a resource manager resources = visa.ResourceManager('@py') #Open the Rigol by name. (Change this to the string for your instrument) oscilloscope = resources.open_resource('USB0::6833::1230::DS1ZA123456789::0::INSTR') #Return the Rigol's ID string to tell us it's there print(oscilloscope.query('*IDN?')) #Select channel 1 oscilloscope.query(':MEAS:SOUR:CHAN1') #Read the RMS voltage on that channel fullreading = oscilloscope.query(':MEAS:ITEM? VRMS,CHAN1') #Extract the reading from the resulting string... readinglines = fullreading.splitlines() # ...and convert it to a floating point value. reading = float(readinglines) #Send the reading to the terminal print reading #Close the connection oscilloscope.close()
Enable the channel on the instrument – when you are familiar with the API you can do this with your software – and connect it to a signal. We used the ‘scope calibration terminal as a handy square wave source. You can then run the script as follows, and if all is well you will be rewarded with the instrument ID string and a voltage reading:
sudo python query_rigol.py
It’s worth noting, we have just run Python as root through the sudo command to use the USB device for the purposes of this demonstration. It’s beyond the scope of this page, but you will want to look at udev rules to allow its use as a non superuser.
With luck on this page we will have demystified the process of controlling your USB-connected instruments, and you should be emboldened to give it a go yourself. We’re not quite done yet though, the second part of this article will present a more complete example with a practical purpose; we’ll use our Raspberry Pi and Rigol to measure the bandwidth of an RF filter.