National Instruments VISA Drivers
VISA or the Virtual Instrument Software Architecture is a set of APIs for communicating with lab equipment. The VISA interface provides an API you can use to communicate with instruments regardless of whether the instrument is connected with Ethernet, USB or GPIB. VISA provides abstractions for device addresses and allows an application send commands and receive events generated by instruments.
VISA provides primarily a C interface however there is the pyVISA library that allows you to use VISA though Python.
National Instruments provides the VISA runtime for free on a large number of platforms including Windows, Mac and Linux. Using this with Python means I can run my scripts on all three platforms.
Keysight MSO-X-2024
My oscilloscope supports automation via Ethernet. Ethernet however is an expensive ($400) option as it also provide a VGA interface to allow the instrument to display the screen on a monitor. Luckily someone figured out that all the Ethernet capability was on the motherboard so all that is required is a couple of inductors and MagJack.
Someone on the EEVBlog forum was selling surplus homebrew Ethernet boards (unpopulated) and so I bought one. It was pretty easy to assemble and the design also included STL files that can be 3D printed into a case to support the board when it is plugged into the oscilloscope.
The scope takes longer to boot and displays an error about the VGA functionality but otherwise the Ethernet works fine. The details about the board can be found here. There is also this github with KiCAD schematics etc but I think they are the same.
Here it is assembled
Siglent SDG1020 Signal Generator
This signal generator has served me quite well over the last couple of years. The unit has a USB interface that you can use to control it including uploading of custom waveforms.
Siglent provides Windows drivers and an application you can use to control the device. Initially I assumed I would have to use the Siglent driver to interface with the device and so I would have to use Windows. Siglent provide some tools to enable the signal generator to be used with NI Virtual Bench and to begin with I thought this is what I needed to talk to it via VISA.
I figured out that NI VISA can directly interface with USB devices without a driver. I found a short step-by-step guide here for doing this. The trick is the instrument must implement the USB TMC protocol which the Siglent device does.
I followed the steps but it didn't initially work. I turns out you have to tell the signal generator to support USB TMC mode. You use the utility button and then select Interface, USB Setup and select USB TMC (instead of the default with is 'RAW'). Reboot the signal generator and then you can send commands to it via NI VISA. I opened the VISA interactive control tool (provided with NI VISA), selected the Siglent instrument and used the Input/Output option to send an *IDN? command which came back with the device ID!
There is a programmers guide for the signal generator here. The device includes commands to control pretty much everything you can do from the user interface.
GPIB
I have a few instruments that provide GPIB based control interfaces. In particular this would be useful for my old HP3478A multimeter as then I could do precision voltage/current measurements between that and the Keysight 34461A. In addition my 53131A and my Rohde & Schwarz signal generator provide GPIB.
I find everything about GPIB is expensive. The cables, the interface cards and even instruments that support GPIB tend to be more expensive. But then GPIB is also quite ancient (it was originally HPIB until IEEE published it as IEEE 488.2). Amusingly the Commodore 64 spent many hours hacking on when I was growing up had a GPIB interface. GPIB is not a terribly quick protocol and for most applications you don't even need as much speed as it provides.
GPIB allows instruments to be daisy-chained together on the bus. The cable connectors have a plug on one side and a socket on the other to allow them to be chained. Each instrument has an address which is usually adjustable via the instrument interface. For the most part the computer directs everything on the bus however it is possible for an instrument to generate a service request or to raise a trigger.
The main ways people connect to GPIB seem to be these Agilent USB to GPIB modules. Recently these have become quite cheap on eBay ($100 instead of $400). The major downside of these is that they only come with Windows drivers. It is possible to make them work on Linux but it is relatively painful as you have to upload firmware onto the USB device when it connects.
Another popular option is the ProLogix GPIB modules but these are quite pricey and don't support NI VISA.
By luck I found an older ICS-8065 Ethernet to GPIB gateway going quite cheaply on ebay. What interested me about this device is it uses the VXI-11 protocol over Ethernet. This protocol is a pre-cursor to LXI and is based on RPC. This means that in the future if I can't get software for this device I can always write something using RPC. NI VISA already supports VXI-11 so there is no need for that. An added plus is that as it requires no additional software (apart from NI VISA) I can run my scripts on my Mac with pyVISA.
The downside though was my unit was a bit old so it didn't have a web interface for configuration. I had to dowload some Windows software from the ICS Electronics website to configure it. I tried to update the firmware but after a couple of emails with support it turned out my device required a major (i.e. too big to do) hardware upgrade to run the newer firmware.
There is a slight trick to configuring the gateway in NI VISA. You select the hostname of the gateway but then you somehow have to select which instrument the alias is for. In the ICS 8065 configuration you can choose a device name but the default is gpib0. The way you select what instrument connected to the bus you want to talk to is by adding the GPIB address to the LAN device name. So the instrument with GPIB address 3 has a LAN Device name of gpib0,3. See below.
Using this I was able to get my HP3478A and my HP53131A to work. The HP3478A isn't SCPI so the commands are a bit different but it is relatively simple. Even though the 53131A is SCPI I actually found it hard to use. For some reason I couldn't get the R&S signal generator to work at all. Really not sure why but it may be a fault in the unit. I will look at that another time.
Bode Plotter
So I wanted to try using this for something. Frankly the possibilities with automatic measurements are quite large but recently I've been reading about active filter design so I thought it might be fun to make a bode plot.
The basic plan is to:
- Use the USB interface to the Siglent signal generator to sweep across a frequency range.
- For each frequency, use the oscilloscope to measure the amplitude of the output and to work measure the phase between the input and output.
You can measure the amplitude easily enough with the scope using a command like
MEAS:VPP? CHAN3
Phase is pretty easy too
MEAS:PHAS? CHAN3, CHAN1
Amusingly when you do this the Peak to Peak measurement and phase get displayed in the oscilloscope screen.
The problem is to measure the amplitude and phase you need to have at least one complete cycle on the screen. We know the frequency as we are controlling the signal generator so we can set the time base of the oscilloscope. We can set the seconds per division to whatever value using something like this:
TIME:RANG 1.1e-3
To set the signal amplitude we can use this command sent to the signal generator:
C1: BSWV, FRQ, 10e3,AMP, 0.25
This sets channel 1 to a basic wave (sine wave) of frequency 10kHz and amplitude 0.25V peek to peek.
So now I started to think about how I sweep the frequency across a range logarithmically but while maintaining an even number of points per decade. While looking up maths code for Python I found this numpy library which actually has a function for it!
for freq in numpy.logspace(numpy.log10(100),numpy.log10(1e5),num=100):
This for loop iterates over a set of 100 frequencies spread evenly (in logarithmic fashion) between 100Hz and 100kHz. Neat!
Now for frequency I
- Change the signal generator frequency,
- Move the scope time base to match the frequency,
- Measure the peak to peak voltage of the input and the output
- Measure the phase difference between the input and the output.
gain = 20 * numpy.log10(output/input)
For each frequency I add the frequency, gain and phase to an array. But now what can I do with the data? I found this Python library called Matplotlib. This has loads of capability include log plots.
I use Matplotlib to graph the gain (in dbM on a linear scale) vs frequency (on a log scale).
When I tried this a bunch of things didn't work:
- I found that if I sent commands to the signal generator too quickly it would just ignore them! I had to add sleep commands to slow things down enough for this not to happen.
- At very low frequencies the scope automatically goes into 'roll' mode and is not able to make phase measurements.
- The output impedance of the signal generator would cause the signal at the input to drop at some frequencies. If the input impedance of the circuit under test is low at some frequencies the input amplitude drops and throws out the gain measurements. Instead I used the second signal generator channel to generate an identical input waveform and measured between this and the output.
- numpy.log() is the *natural* logarithm. I accidentally used this instead of log10() initially which threw all my gain calculations out (facepalm).
- I am manually setting the scope vertical adjustments but at regions of very low or very large gain I can't get phase or amplitude readings. I didn't fix this but ideally the script would adjust the scope's vertical range to correct for this.
Bode Plotting Things...
What can I plot? What about a bilinear active filter - like this:
So to understand what is going on imagine C1 and R1 are combined into an impedance (Z1) and C2 and R2 are combined into Z2. Then it is a simple inverting amplifier and the gain is just Z2/Z1,
At DC the capacitors are open circuits so the gain is 1 (0dBm) but at the peak the gain will be C2/C1 = 10 or 20dBm.
So because the gain is Z1/Z2 then we get a zero due to Z1 and a pole due to Z2. The corner frequency of the zero is 1/2 * pi * r1 * c1 which is 234Hz. Then the pole is calculated similarly and is at 2.3K Hz.
Here is the LTSpice Bode plot. There is an extra pole and zero created by the input capacitance of the of the op amp (I think). The actual amp I am using is a LM14588N so this will be different.
Here is the output of the bode-plotter:
It's not a totally silly approximation. Unfortunate that the phase wraps but no matter. Still much study to do...