Skip to content
BenchMesh

Connectors · MATLAB · LabVIEW · PyVISA

Virtual SCPI instruments for VISA programs

Every instrument on your bench can answer SCPI on its own port, like a LAN instrument on port 5025 - also a serial supply or a USB meter that speaks no SCPI at all. MATLAB, LabVIEW, PyVISA and TestStand open it with a VISA address, and the bench keeps showing what happens.

What it is

BenchMesh already knows each instrument from its definition: what it can set, what it reports, the limits and allowed values. The virtual SCPI port puts that in front of the tools labs already use. Each configured instrument gets a raw SCPI socket on this computer, the kind LAN instruments offer, so VISA addresses it as TCPIP0::127.0.0.1::5025::SOCKET:

  • Any instrument, one language. A Tenma or OWON supply on a USB-serial cable, a USBTMC meter or a LAN scope: all answer *IDN?, VOLTAGE 5 and FETCH:VOUT? the same way.
  • Through BenchMesh, not around it. Commands go through the same connection as the panels, so the bench, recordings and the instrument console show every change, and values are checked against the instrument’s limits before anything is sent.
  • Nothing to install in your tool. No driver, no IVI package - a VISA resource name, or even a plain TCP connection.

Switch it on

Open Instruments → Connectors in the app and choose the access:

AccessPrograms may
offNothing - no port is open. The default.
readQuery instruments and read their latest values. Setters answer error -203.
controlAlso set instruments, including switching outputs on - as your own scripts on the REST API can.

The first instrument gets port 5025 (the usual SCPI port; change it under First port), the others the next free ports. A port stays with its instrument, so addresses in your scripts keep working. The Connectors tab lists every address with a Copy button and ready code for MATLAB, PyVISA and LabVIEW.

MATLAB

With the Instrument Control Toolbox, visadev opens the address like any LAN instrument:

MATLAB
% Instrument Control Toolbox
psu = visadev("TCPIP0::127.0.0.1::5025::SOCKET");          % Tenma 72-2540, a serial supply
writeline(psu, "*IDN?"); disp(readline(psu))
% BenchMesh,72-2540,tenma-72-2540,0.1.12

writeline(psu, "VOLTAGE 5.0");
writeline(psu, "OUTPUT ON");
dmm = visadev("TCPIP0::127.0.0.1::5026::SOCKET");
writeline(dmm, "FETCH:MEAS?"); v = str2double(readline(dmm))

Without a toolbox, base MATLAB’s tcpclient does the same:

MATLAB, no toolbox
% Base MATLAB, no toolbox: a plain TCP client
t = tcpclient("127.0.0.1", 5025);
configureTerminator(t, "LF");
writeline(t, "FETCH:VOUT?"); vout = str2double(readline(t))

A load sweep with the supply’s voltage measured by a separate meter, straight into a plot:

MATLAB sweep
% Sweep the load and log the meter, then plot
load = visadev("TCPIP0::127.0.0.1::5027::SOCKET");
dmm  = visadev("TCPIP0::127.0.0.1::5026::SOCKET");
writeline(load, "MODE CURR"); writeline(load, "INPUT ON");
i = 0:0.1:2; v = zeros(size(i));
for k = 1:numel(i)
    writeline(load, sprintf("CURR %.3f", i(k))); pause(1)
    writeline(dmm, "FETCH:MEAS?"); v(k) = str2double(readline(dmm));
end
writeline(load, "INPUT OFF");
plot(i, v); xlabel("Load current [A]"); ylabel("Output voltage [V]")

Python (PyVISA)

Existing PyVISA scripts work with any VISA backend, including the pure-Python pyvisa-py (pip install pyvisa pyvisa-py):

Python
import pyvisa

rm = pyvisa.ResourceManager()          # NI-VISA, Keysight VISA, or "@py" for pyvisa-py
psu = rm.open_resource("TCPIP0::127.0.0.1::5025::SOCKET",
                       read_termination="\n", write_termination="\n")
print(psu.query("*IDN?"))
psu.write("VOLTAGE 3.3")
print(psu.query_ascii_values("FETCH:VOUT?")[0])
print(psu.query("SYST:ERR?"))           # 0,"No error"

Operations that return binary data answer an IEEE 488.2 block, which PyVISA reads with query_binary_values(..., datatype="B", container=bytes).

For new Python code the benchmesh package is simpler: names instead of strings, live values, recordings as pandas tables.

LabVIEW and TestStand

Use the address as the VISA resource name in VISA Open (or type it into the resource control). Set the termination character to line feed (0x0A) with Enable Termination Char on - a raw socket needs it, as with any SCPI instrument on port 5025. Then VISA Write / VISA Read as usual. TestStand steps and other VISA programs (NI MAX, Keysight Connection Expert, IVI-less test executives) work the same way.

Commands

Lines end with a line feed. Case does not matter. Several commands can share a line separated by ;; the answers of its queries come back in one line, separated by ;.

CommandDoes
*IDN?BenchMesh,<model>,<instrument id>,<app version>
*CLSClears the error queue.
*OPC?1 - commands run in order, so everything before it is done.
SYST:ERR?The oldest error, or 0,"No error".
SYST:HELP:HEAD?Every command this instrument understands, in one line.
VOLTAGE?Runs the instrument’s query operation - asks the instrument now.
VOLTAGE 5Runs its setter. Text values may be quoted: MODE "VOLT DC".
FETCH:VOUT?The latest reading BenchMesh polled - nothing is sent to the instrument, so it is fast and safe to call often.
  • Operation and field names are those of the instrument’s definition - the same as in the app’s API and flows. SYST:HELP:HEAD? lists them; SCPI short forms are not used.
  • Channels: CH2:VOLTAGE 5 (also CHAN2, CHANNEL2); without one, channel 1.
  • Classes: an instrument with two classes, such as a supply with a built-in meter, takes PSU:VOLTAGE? and DMM:MEASUREMENT?. The class can be left out when only one class knows the name.
A session
> *IDN?
BenchMesh,SPM3103,owon-spm3103,0.1.12
> SYST:HELP:HEAD?
*IDN?,*CLS,*OPC?,SYSTem:ERRor?,SYSTem:HELP:HEADers?,DMM:MEASUREMENT?,DMM:MODE <value>,DMM:FETCh:MEAS?,PSU:VOLTAGE?,PSU:VOLTAGE <value>,PSU:OUTPUT <value>,PSU:FETCh:VOUT?,...
> PSU:VOLTAGE 5;*OPC?;PSU:VOLTAGE?
1;5
> MODE VOLT
> SYST:ERR?
-113,"Undefined header; give the class: DMM or PSU:MODE"
> VOLTAGE 99
> SYST:ERR?
-222,"Data out of range; 99 is outside the setter's limits"

Replies

  • Numbers in base units: 4.94, 1E-6 (V, A, W, Hz, F, Ω).
  • Text as the instrument reports it (ON, VOLT_DC); booleans 1 / 0.
  • Binary data as a definite-length block #<digits><length><bytes>.
  • A query that fails answers an empty line, instead of leaving your program waiting for a timeout. SYST:ERR? then tells you why.

Errors

Each connection has its own error queue (20 entries) with the standard SCPI codes and a message that says what to change:

CodeWhen
-102Syntax error: an empty or malformed header.
-108Parameter not allowed: a value after a query.
-109Missing parameter: a setter without a value.
-113Undefined header: an unknown command, operation or field; a query on an operation that cannot be read (or the other way round); the class is ambiguous.
-114Header suffix out of range: a channel above what the instrument has.
-203Command protected: a setter while access is read.
-221Settings conflict: refused by the instrument definition (for example a mode it needs), the instrument is parked, or the running flow uses it.
-222 / -224Data out of range / illegal value: refused against the setter’s limits or allowed values before anything is sent.
-230Data stale: no fresh reading for FETCh (instrument offline) or a malformed reply.
-240 / -241The instrument timed out / is not reachable.
-200Any other execution error.

Safety

  • Off by default, read before control. No port is open until you choose an access.
  • This computer only. The ports listen on 127.0.0.1; other computers cannot connect. To work from another computer, use remote access (HTTPS with a password) or the Python package through it.
  • Web pages cannot use it. A web page can make your browser send a request to a local port. BenchMesh closes any connection that looks like web traffic before a single command runs.
  • Limits first. Every value is checked against the instrument’s limits and allowed values before anything is sent.
  • Flows keep their instruments. While a flow runs, setters for the instruments it uses are refused (-221); queries still work.