Diving into SCPI

christophChristoph wrote 09/10/2022 at 19:41 • 4 min read • Like

Setting up instruments (like an oscilloscope or a signal generator) can be quite tedious. For me, that is when

The second point has (at least) two flavors:

Until now I thought that controlling them via USB or LAN would be quite a steep learning curve, but one day I was just so fed up with all that button pushing (especially when the rotary knobs jump over to the next value when you push...) that I gave it a try. And it was easier than I thought!

Simple test

As a simple test, I configured a signal generator (Rigol DG1022Z) to output a 1 MHz, 10 Vpp square wave into a 50 Ohm load, and the scope accordingly. Both instruments are connected to my computer via USB, and I'm using pyvisa to control them with a python script.

The signal generator feeds its output into a coax cable which is terminated with 50 Ohm on the scope side.

pyvisa offers a resource manager that can discover instruments:

import pyvisa as visa
rm = visa.ResourceManager()
# let's see what we have connected:

The output of list_resources containts a string for each instrument that was found, and this string includes an instrument's serial number, like so:


So we can go through that list and look for a specific instrument:

resources = rm.list_resources()
for i in range(len(resources)):
    r_name = resources[i]
    if (r_name.split("::")[3] == DS1054_Serial):
        # now do something with the instrument

To do something with the instrument, it must be opened before we can send commands or query values.

Example: reset the instrument


Starting with a freshly reset instrument, it's just a matter of looking up the correct commands in the instrument's programming manual and writing them all down:

import pyvisa as visa
import sys
rm = visa.ResourceManager()

DG1022_Serial = "DG1ZA23530xxxx"
DS1054_Serial = "DS1ZA20180xxxx"


resources = rm.list_resources()

scope_done = False
siggen_done = False

# find scope, reset to defaults and apply only those changes that deviate from those defaults
for i in range(len(resources)):
    r_name = resources[i]
    if (r_name.split("::")[3] == DS1054_Serial):
        instr = rm.open_resource(r_name)
        # resourceReply = instr.query('*IDN?').upper()
        # timebase
        # Ch1 coupling AC/DC
        # Ch1 attenuation
        # Ch1 V/Div
        # trigger
        # run
        instr.write("TIM:MAIN:SCAL 50e-9")
        instr.write("CHAN1:COUP DC")
        instr.write("CHAN1:PROB 1")
        instr.write("CHAN1:SCAL 2")
        instr.write("CHAN1:DISP ON")
        scope_done = True

if not scope_done:
  print("Could not find scope. Check connection and retry.")
#  exit()

# find signal generator, reset to defaults and apply only those changes that deviate from those defaults
for i in range(len(resources)):
    r_name = resources[i]
    if (r_name.split("::")[3] == DG1022_Serial):
        instr = rm.open_resource(r_name)
        # resourceReply = instr.query('*IDN?').upper()
        instr.write(":OUTP1:LOAD 50")
        instr.write(":OUTP1:IMPEDANCE 50")
        instr.write(":SOURCE1:APPL:SQU 1e6,10")
        instr.write(":OUTP1 ON")
        # instr.control_ren(visa.constants.RENLineOperation.address_gtl)
        siggen_done = True

if not siggen_done:
  print("Could not find signal generator. Check connection and retry.")
#  sys.exit()

print("All done.")

 The signal generator has a little caveat. Once the setup via USB is done, it remains in "remote mode", and the buttons can't be used. We can see that it's in remote mode when there is a little arrow symbol in the top right corner:

That's inconvenient if further tweaks are to be done with the buttons. Instead, it shows a message

Instrument is locked for VISA,
Press the "Local" to unlock.

 However, there is no "Local" button. A look at the manual reveals that they actually meant to point us towards the "Help" button, and that indeed helps. The instrument is in local mode again.

The picture above also shows that the signal generator is indeed configured as per the script. Scope, too:

If you just have the scope, remove the signal generator part. And of course also put in the serial numbers of your own devices!

Check out pyvisa here:

There's probably a ton of caveats I haven't discovered yet, but for now this does the job - make instrument setup faster and more repeatable.