TcpInstruments.jl
TcpInstruments allows you to control a variety of internet-enabled instruments
SCPI is supported on almost all modern pieces of lab equipment and this code has during development been tested on the following devices:
- Oscilloscope Keysight DSOX4034A
- Oscilloscope Keysight DSOX4024A
- Multimeter Keysight DMM34465A
- Signal generator Keysight 33612A
- Power supply Agilent E36312A
- HV power supply SRS PS310 via Prologix GPIB to Ethernet adaptor
- Power supply Versatile Power 100-10 XR
- Impedance analyzer Agilent 4294A
- SourceMeasureUnit Agilent B2910BL
Installation
TcpInstruments can be installed using the Julia package manager. From the Julia REPL, type ] to enter the Pkg REPL mode and run
pkg> add TcpInstruments
To see the different types of devices you can interface with, run:
julia> ?
help?> Instrument
General Usage
To connect to an instrument you must know its model and IP address:
using TcpInstruments
instrument_handle = initialize(AgilentDSOX4034A, "10.1.30.32")
info(instrument_handle)
data = get_data(instrument_handle)
save(data)
When you are done you can close your connection:
terminate(instrument_handle)
If you do not know the ip address of any devices on your network:
scan_network()
By default scan_network
will check the addresses between 10.1.30.1 to 10.1.30.255 but you may need to scan a different range, say: 10.1.150.1-255
scan_network(; ip_network="10.1.150.")
Units
This package uses Unitful.jl for units. All of Unitful.jl's exports are reexported by this package along with the commonly used units of this package, specifically:
- s, ms, μs, ns, ps
- MΩ, kΩ, Ω, mΩ, µΩ, nΩ, pΩ
- V, mV, µV, nV, pV
- A, mA, µA, nA, pA
- GHz, MHz, kHz, Hz
Most users should therefore be able to interact with this package without specifically loading Unitful.jl.
Commands such as:
set_voltage_offset(psu, 0)
will not work, the unit needs to be specified:
set_voltage_offset(psu, 0V)
Examples
Continious sine wave with a signal generator (in this case the Keysight 33612A):
sg = initialize(Keysight33612A, "10.1.30.36")
set_mode_cw(sg) # Set to continuous waveform mode
set_function(sg, "SIN")
set_frequency(sg, 1kHz)
set_amplitude(sg, 0.1V)
set_voltage_offset(sg, 100mV)
enable_output(sg) # sine output starts here
Power Supplies
VersatilePower
# Initialize automatically puts this power supply in remote mode
pwr = initialize(VersatilePower)
set_voltage(pwr, 20V)
set_current_limit(pwr, 4A)
enable_output(pwr)
# Closes connection as with other devices but also puts this
# device back into local mode
terminate(pwr)
AgilentE36312A
pwr = initialize(AgilentE36312A)
set_channel(pwr, 1)
set_current_limit(pwr, 1)
set_voltage(pwr, 2V)
enable_output(pwr) # Enables output on channel 1
set_channel(pwr, 2)
set_voltage(pwr, 10V)
enable_output(pwr) # Enables output on channel 2
set_channel(pwr, 3)
set_voltage(pwr, 10V)
set_voltage(pwr, 0V; chan=1) # Changes voltage of channel 1
get_voltage(pwr) # Get voltage channel 3
get_voltage(pwr; chan=2)
get_voltage(pwr; chan=1)
enable_output(pwr) # Enables output on channel 3
GPIB Power Supply (SRSPS310) used with Prologix Controller
To a initialize a device that is connected with a prologix controller you must specify what prologix channel the device is on. At this moment the prologix adapter is the only supported GPIB to Ethernet adapter.
p = initialize(SRSPS310, "10.1.30.37:1234"; GPIB_ID=2)
If you don't know the channel you can figure it out and configure it manually:
julia> using TcpInstruments
julia> p = initialize(SRSPS310, "10.1.30.37:1234")
julia> scan_prologix(p)
2 => "PS310"
julia> set_prologix(p, 2)
julia> get_prologix(p)
2
Using SRSPS310 Power Supply:
p = initialize(SRSPS310, "10.1.30.37:1234"; GPIB_ID=2)
set_voltage_limit(p, 1250V)
set_voltage(p, 1250V)
set_current_limit(p, 0.021A) # equivalent to set_current_limit(p, 21mA)
enable_output(p)
Oscilloscopes
AgilentDSOX4034A
scope = initialize(AgilentDSOX4034A)
# Turn on Low Pass Filter 25MHz
lpf_on(scope)
# See that low pass filter is on
get_lpf_state(scope)
# Turn Off Low Pass Filter 25MHz
lpf_off(scope)
# See that low pass filter is off
get_lpf_state(scope)
set_impedance_1Mohm(scope)
@info get_impedance(scope)
set_impedance_50ohm(scope)
@info get_impedance(scope)
# Get data from channel 1
data = get_data(scope, 1)
# Get data from channel 1, 2, & 4
# Returns 3 element array of data from each channel
multi_data = get_data(scope, [1,2, 4])
using Plots
plot(data)
# Plots channel 1
plot(multi_data[1])
# Plots channel 2
plot(multi_data[2])
# Plots channel 4
plot(multi_data[3])
# Saves data to a file
save(multi_data)
Additionally you can grab data from all open channels (Let's say only channels 1 & 2 are activated for now)
scope = initialize(AgilentDSOX4034A)
data = get_data(scope)
Since the only activated channels are now only 1 & 2 this returns an array of waves (equivalent to `get_data(scope, [1,2]))
You can also plot multiple waves at once:
plot(data)
Impedance Analyzers
TODO: example with the Agilent4294A.
Multiple devices
Lets say you want to use a signal generator, power supply and oscilloscope all at once.
using TcpInstruments
using Plots; plotly()
scope = initialize(AgilentDSOX4034A)
pwr = initialize(VersatilePower)
sg = initialize(Keysight33612A)
set_mode_cw(sg)
set_function(sg, "SIN")
set_frequency(sg, 1000Hz)
set_amplitude(sg, 0.1A)
set_voltage_offset(sg, 0V)
enable_output(sg)
set_voltage(pwr, 20V)
set_current_limit(pwr, 4A)
enable_output(pwr)
data_array = get_data(scope, [1,2])
plot(data_array)
Custom Commands
To send custom commands where no return response is expected use the write()
function:
julia> write(instr, "<SCPI command>")
If the device is sending a response to the command use query()
instead:
julia> response = query(instr, "<SCPI command>")
The convenience functions f_query()
and i_query()
parse the response string to a Float64
and Int64
, respectively.