NAME
Lab::Measurement::Tutorial - Lab::Measurement tutorial
VERSION
version 3.831
How to read the documentation
The documentation of Lab::Measurement can be read both on MetaCPAN and by using perldoc. The most important starting points are
Lab::Measurement::Installation
Detailed installation instructions.
-
Overview of available back-ends.
-
The table of contents referencing all manual pages.
-
This tutorial.
A separate tutorial for the historical interfaces Lab::Instrument and Lab::XPRESS is provided in Lab::Measurement::Legacy::Tutorial. These interfaces as well as the tutorial are not updated anymore, and included for compatibility with existing measurement scripts. They will be removed with Lab::Measurement release 4.
Quickstart
In this quickstart section we demonstrate how to connect to instruments and do simple communication to change instrument settings and perform data acquisition. In the examples we use two comparatively simple instruments, the HP (later Agilent, now Keysight) 34410A digital multimeter (DMM) and the Stanford Research SR830 lock-in amplifier.
We cover the most important connection types and show how to use them on Linux and Windows:
USB
This uses the USB-TMC protocol, which emulates IEEE 488.2 features over a USB cable. Instruments are connected directly to the measurement PC or via a hub. Depending on your USB hardware data transfer can be very fast.
Ethernet / VXI11
This is the recommended protocol, if supported by the device; instruments are connected via a local area ethernet network with the measurement PC. (Raw TCP sockets are also supported by Lab::Measurement, but do not provide the IEEE 488.2 style control commands of VXI11, such as device clear. This is why VXI11 will be more seamless.) We recommend to create a private, firewalled or non-routed LAN to separate you lab devices from the internet. Naturally then you will have to take care of IP address assignment yourself.
GPIB
This is the IEEE 488 bus, also called GPIB or HPIB. It is robust and often the only option for older equipment in the lab.
Connecting instruments on Linux
Let's use the Agilent DMM with USB on Linux. This requires the USB::TMC driver module and the libusb system library to be installed. libusb should be available for every modern Linux distribution.
use 5.010;
use Lab::Moose;
my $multimeter = instrument(
type => 'Agilent34410A',
connection_type => 'USB',
);
Note that the connection type USB assumes that we have a USB Test & Measurement class device. Devices that emulate a serial port or other USB classes (video, audio, ...) are not supported (yet).
When connecting multiple devices of the same model via USB, we have to provide serial numbers, which are unique for each device:
my $multimeter1 = instrument(
type => 'Agilent34410A',
connection_type => 'USB',
connection_options => {serial => '...'}
);
my $multimeter2 = instrument(
type => 'Agilent34410A',
connection_type => 'USB',
connection_options => {serial => '...'}
);
To use the LAN interface, set the connection_type
to VXI11 and provide the instrument's IP address with the connection_options
hash:
my $multimeter = instrument(
type => 'Agilent34410A',
connection_type => 'VXI11',
connection_options => {host => '192.168.2.20'},
);
The SR830 lock-in amplifier only has a GPIB interface. This means that our measurement PC needs a GPIB host adaptor. The LinuxGPIB kernel driver and perl bindings have to be installed and configured as described in Lab::Measurement::Backends. Note that the kernel driver consists of Linux kernel modules, which may have to be compiled specific for the running kernel.
The GPIB address (primary address, short pad) of our lock-in amplifier is provided in the connection_options
hash:
my $lia = instrument(
type => 'SR830',
connection_type => 'LinuxGPIB',
connection_options => {pad => 1},
);
Connecting instruments on Windows
First, make sure that both National Instruments (NI) VISA and the Lab::VISA package are installed, see Lab::VISA::Installation. The VISA interactive control, part of the NI VISA installation, can be used to get a list of connected equipment.
We first connect the DMM via USB. The serial number can be found using VISA interactive control or from the utility menu of the instrument.
use 5.010;
use Lab::Moose;
my $multimeter = instrument(
type => 'Agilent34410A',
connection_type => 'VISA::USB',
connection_options => {serial => '00B50DAE'},
);
To use the LAN interface, set the connection_type
to VISA::VXI11 and provide the instrument's IP address with the connection_options
hash:
my $multimeter = instrument(
type => 'Agilent34410A',
connection_type => 'VISA::VXI11',
connection_options => {host => '192.168.2.20'},
);
Finally, we connect the SR830 lock-in amplifier via GPIB. This requires that the National Instruments NI-488 driver is installed in addition to VISA. The GPIB address (primary address, short pad), is provided in the connection_options
hash:
my $lia = instrument(
type => 'SR830',
connection_type => 'VISA::GPIB',
connection_options => {pad => 1},
);
Listening and talking to the devices
After initializing the multimeter with the instrument
function, let us perform some basic operations
# Perform *IDN? query, prints instrument manufacturer, model, serial number
say $multimeter->idn();
# Set range to 10 Volts (if multimeter is in voltage mode)
$multimeter->sense_range(value => 10);
# Perform voltage measurement (if multimeter is in voltage mode)
my $voltage = $multimeter->get_value();
And for the SR830 lock-in amplifier:
# Set reference frequeny to 10kHz
$lia->set_frq(value => 10e3);
# Set output voltage amplitude to 0.5 V
$lia->set_amplitude(value => 0.5);
# Set sensitivity to 1mV
$lia->set_sens(value => 1e-3);
# Set filter slope to 18dB/oct
$lia->set_filter_slope(value => 18);
# Read x/y measurement data
my $xy = $lia->get_xy();
# Print contents of $xy hashref
say "x = $xy->{x}, y = $xy->{y}";
Connection logging
We can monitor the commands sent to the instrument by specifying a log file in the constructor:
my $lia = instrument(
type => 'SR830',
connection_type => 'VISA::GPIB',
connection_options => {pad => 1},
log_file => 'some_file.yml'
);
All communication will be logged in the human readable file some_file.yml.
Types of instrument drivers
Here we show some examples of more advanced types of instruments.
Note that when using sources (voltage, magnetic field, temperature) we often do not call the instrument object directly. Instead, we use the high-level sweep interfaces as described below. These provide a common API for creating both discrete and continuous sweeps of output parameters.
Voltage / current source drivers
For a voltage or current source, the instrument initialization requires several additional parameters which enforce step size and rate limits. The intention here is that often sensitive devices can be destroyed by large and sudden jumps in input voltage; by providing limits at initialization, the later script follows these limits automatically without further programming effort.
my $yoko = instrument(
type => 'YokogawaGS200',
connection_type => 'USB',
max_units_per_step => 0.001,
max_units_per_second => 0.01,
min_units => -10,
max_units => 10,
);
We assume that the Yokogawa GS200 source is in voltage output mode. Now we use set_level
to set output level to 9V. The source will sweep with step size and speed given by the max_units_per_step / max_units_per_second parameters; unit is Volt (the corresponding SI unit).
$yoko->set_level(value => 9);
Once this has finished, we can read the new level from the cache that is automatically kept by Lab::Measurement:
my $level = $yoko->cached_level();
Superconducting magnet power supplies
my $ips = instrument(
type => 'OI_Mercury::Magnet',
connection_type => 'Socket',
connection_options => {host => '192.168.3.15'},
);
The following commands perform a continuous sweep of the magnetic field from 0T to 0.5T with a rate of 0.1T/min:
# Set field setpoint and rate
$ips->config_sweep(point => 0.5, rate => 0.1);
# Start (trigger) sweep
$ips->trg();
# Show progress until sweep is finished
$ips->wait();
A high-level interface for creating continuous sweeps and measuring while the sweep is running is described below.
Spectrum analyzers
Typically, a spectrum analyzer performs a frequency sweep in hardware. The resulting spectrum data, i.e., power as function of frequency, is returned as a 2D PDL object. Here is the corresponding code at the example of a Rohde & Schwarz FSV spectrum analyzer:
my $analyzer = instrument(
type => 'RS_FSV',
connection_type => 'VXI11',
connection_options => {host => '...'},
);
# Set sweep start/stop frequencies
$analyzer->sense_frequency_start(value => 1e9);
$analyzer->sense_frequency_stop(value => 1e9);
# Perform sweep, get data as PDL
my $data = $analyzer->get_spectrum(timeout => 100);
# Print data
say $data;
You can always convert a PDL into an ordinary nested arrayref with unpdl
:
my $arrayref_2D = $data->unpdl();
Sweeps, datafiles, and datafolders
Quick start: Measuring an IV-curve
As a basic example of a one-dimensional sweep, we measure an I(V) curve. A Yokogawa voltage source is combined with an Agilent multimeter.
# file: IV.pl
use Lab::Moose; # you get 'use warnings; use strict;' for free
my $source = instrument(
type => 'YokogawaGS200',
connection_type => 'USB',
# Safety limits:
max_units => 10, min_units => -10,
max_units_per_step => 0.1, max_units_per_second => 1
);
my $dmm = instrument(type => 'Agilent34410A', connection_type => 'USB');
my $sweep = sweep(
type => 'Step::Voltage',
instrument => $source,
from => -5, to => 5, step => 0.01
);
my $datafile = sweep_datafile(columns => [qw/voltage current/]);
my $meas = sub {
my $sweep = shift;
$sweep->log(
voltage => $source->cached_level(),
current => $dmm->get_value(),
);
};
$sweep->start(
measurement => $meas,
datafile => $datafile,
);
Running this script repeatedly creates output folders MEAS_000, MEAS_001, ... Each of these folders contains the following files:
IV.pl
A copy of the measurement script.
META.yml
A YAML file with various automatically collected metadata (the time of the script run, the user name, the host name, the used command line, the Lab::Measurement version, ...).
data.dat
A Gnuplot-style datafile:
# voltage current -5 42 -4.99 43 ...
Backsweeps
To also measure the IV in the reverse direction from -5 to 5 volts, we add the backsweep
option:
my $sweep = sweep(
type => 'Step::Voltage',
instrument => $source,
from => -5, to => 5, step => 0.01,
backsweep => 1,
);
The data folder
You can change the name of the data folder by providing a folder
argument to the start
method:
$sweep->start(
measurement => $meas,
datafile => $datafile,
folder => 'IV_curve'
);
This will create output folders with names YYYY-MM-DD_HH-MM-SS_IV_curve_xxx If you do not want to use the date/time prefixes use
$sweep->start(
measurement => $meas,
datafile => $datafile,
folder => 'IV_curve',
date_prefix => 0,
time_prefix => 0
);
Multiple datafiles
The following example creates multiple data files:
my $datafile1 = sweep_datafile(
filename => 'data1',
columns => [qw/voltage current/]
);
my $datafile2 = sweep_datafile(
filename => 'data2',
columns => [qw/voltage current/]
);
$sweep->start(
measurement => $meas,
datafiles => [$datafile1, $datafile2],
folder => 'IV_curve'
);
In the $meas
subroutine, we now call the log
method for both data files:
my $meas = sub {
my $sweep = shift;
my $voltage = $source->cached_level();
$sweep->log(
datafile => $datafile1,
voltage => $voltage,
current => $dmm1->get_value(),
);
$sweep->log(
datafile => $datafile2,
voltage => $voltage,
current => $dmm2->get_value()
);
};
Multiple instruments executing the same sweep
If you are working with multiple Lock-In amplifiers for example and you want to sweep the lock-in-frequency, it is of course necessary to change the frequency of every involved Lock-In amplifier to keep them synchronous. To do that, you simply replace the single instrument with an array referrence of multiple devices when defining the sweep:
my $frq_sweep = sweep(
type => 'Step::Frequency',
instrument => [$LOCKIN_REF, $LOCKIN_DUT, $LOCKIN_OUT],
from => 105, to => 2005, step => 100
);
Multi-dimensional sweeps: Data file dimensions and file name extensions
2D sweeps
We start with a simple 2D sweep: we sweep a gate voltage (outer sweep) and a bias voltage (inner sweep) and again measure a current:
use Lab::Moose;
# As we use two Yokogawas, we need to provide serial numbers to identify them
# on the USB bus.
my $gate_source = instrument(
type => 'YokogawaGS200',
connection_type => 'USB',
connection_options => {serial => '...'},
# Safety limits:
max_units => 10, min_units => -10,
max_units_per_step => 0.1, max_units_per_second => 1
);
my $bias_source = instrument(
type => 'YokogawaGS200',
connection_type => 'USB',
connection_options => {serial => '...'},
# Safety limits:
max_units => 10, min_units => -10,
max_units_per_step => 0.1, max_units_per_second => 1
);
my $dmm = instrument(type => 'Agilent34410A', connection_type => 'USB');
my $gate_sweep = sweep(
type => 'Step::Voltage',
instrument => $gate_source,
from => 0, to => 1, step => 0.1
);
my $bias_sweep = sweep(
type => 'Step::Voltage',
instrument => $bias_source,
from => 0, to => 1, step => 0.1
);
my $datafile = sweep_datafile(columns => [qw/gate bias current/]);
# We use cached_level since that speeds up measurement a LOT.
my $meas = sub {
my $sweep = shift;
my $v_gate = $gate_source->cached_level();
my $v_bias = $bias_source->cached_level();
$sweep->log(
gate => $v_gate,
bias => $v_bias,
current => $dmm->get_value(),
);
};
$gate_sweep->start(
slave => $bias_sweep,
measurement => $meas,
datafile => $datafile,
);
By default, this will create a 2D block data file in the typical gnuplot format, i.e., with each bias sweep followed by a blank line as separator.
# gate bias current
0 0 x
0 0.1 x
0 0.2 x
...
0 1 x
0.1 0 x
0.1 0.1 x
0.1 0.2 x
...
...
1 0 x
...
1 1 x
Alternatively, we can create multiple 1D data files, one for each value of the gate voltage. We do this by setting the datafile_dim
parameter to 1:
$gate_sweep->start(
slave => $bias_sweep,
measurement => $meas,
datafile => $datafile,
datafile_dim => 1
);
The output files will be <data_Voltage=0.dat, data_Voltage=0.1.dat, ..., data_Voltage=1.dat> We can customize the Voltage= part in the data file names by providing a filename extension in the gate sweep:
my $gate_sweep = sweep(
type => 'Step::Voltage',
instrument => $gate_source,
from => 0, to => 1, step => 0.1,
filename_extension => 'Gate=',
);
Higher dimensional sweeps
Sweeps setups with dimension > 2 can be created by using a slaves
array parameter in sweep_start
instead of slave
:
$outer_sweep->start(
slaves => [$middle_sweep, $inner_sweep],
datafile => ...
);
The maximum data file dimension remains 2. E.g. if we create a 3D sweep [Temperature, Gate, Bias], a 2D data file will be created for each value of the temperature sweep. If we set datafile_dim
to 1, a subfolder will be created for each value of the temperature and the subfolders contain 1D data files for each gate voltage value.
Live plotting
Line plots
Let us add a simple line plot to our IV measurement:
my $datafile = sweep_datafile(columns => [qw/voltage current/]);
$datafile->add_plot(
x => 'voltage',
y => 'current',
);
This will create a live line plot, which will be updated for each new data point. A copy of the plot will be saved in the output folder in png format with file name "$datafile.png"
. You can change this file name with the hard_copy
option:
$datafile->add_plot(
x => 'voltage',
y => 'current',
hard_copy => 'data.png',
);
The hard_copy
attribute is mandatory if you add multiple plots to one datafile.
Connection problems associated with persistent plot windows
Some gnuplot terminals like qt are always persistent, i.e. the live plot windows persist after the measurement script is finished. Some connection types like LinuxGPIB only work after closing all plot windows. This might be caused by file locks which are inherited by the forked gnuplot processes even when the main perl process is finished. As an alternative to close the plot windows yourself, one can use terminals like x11 where one can set persist => 0
in the terminal_options
attribute (see below).
Labeling lines for different blocks
Assume the following 2d sweep setup:
# outer sweep
my $gate_sweep = sweep(
type => 'Step::Voltage',
instrument => $gate_source,
list => [10, 20, 30],
);
# inner (fast) sweep
my $bias_sweep = sweep(
type => 'Step::Voltage',
from => -1,
to => 1,
step => 0.01
);
my $datafile = datafile(columns => [qw/gate bias current/]);
We create a current vs. bias plot with one curve for each value of the gate:
$datafile->add_plot(
x => 'bias',
y => 'current',
legend => 'gate',
);
Setting the 'legend'
attribute will create a key where each curve is labeled by its value of the gate parameter.
Conversely, if we do not need different plotting styles for each block, we can set
$datafile->add_plot(
x => 'bias',
y => 'current',
curve_options => {linetype => 1},
);
Multiple curves per plot
We can draw multiple curves in a single plot window:
$datafile->add_plot(
curves => [{x => 'voltage', y => 'current1'}, {x => 'voltage', y =>
'current2'}],
hard_copy_ => 'data.png'
);
Color maps (3D plots)
Let us add a color plot to the gate/bias 2D sweep:
my $datafile = sweep_datafile(columns => [qw/gate bias current/]);
$datafile->add_plot(
type => 'pm3d',
x => 'gate',
y => 'bias',
z => 'current'
);
The designation 'pm3d' comes from the gnuplot plot type of this name. By default, the live plot will be updated after each bias sweep is completed.
Terminal options
If we don't want to use gnuplot's default terminal for the live plot or hardcopy, we use the terminal
, hard_copy_terminal
, terminal_options
and hard_copy_terminal_options
options:
$datafile->add_plot(
type => 'pm3d',
x => 'gate',
y => 'bias',
z => 'current',
terminal => 'x11',
terminal_options => {linewidth => 3},
hard_copy => 'data.jpg',
hard_copy_terminal => 'jpeg',
hard_copy_terminal_options => {linewidth => 0.5}
);
Plot and curve options
PDL::Graphics::Gnuplot separates between plot options and curve options.
$datafile->add_plot(
type => 'pm3d',
x => 'gate',
y => 'bias',
z => 'current',
plot_options => {
title => 'x - y plot',
xlabel => 'x (V)',
ylabel => 'y (V)',
cblabel => 'current (A)', # label for color box
format => {x => "'%.2e'", y => "'%.2e'"},
clut => 'sepia',
grid => 0, # disable grid
},
curve_options => {
with => 'lines', # default is 'points'
linetype => 2, # color
linewidth => 2,
},
);
More plot and curve options are documented in PDL::Graphics::Gnuplot.
Live plots in higher dimensional sweeps
Live plotting is also supported for higher dimensional sweeps. When the sweep creates multiple subfolders with datafiles, add_plot
will be called each time a new datafile is created. In this case, the hard_copy
argument to add_plot
cannot be used, as the hard copies of each datafile plot need to have unique names. Instead we use hard_copy_suffix
:
# plot current versus voltage
$datafile->add_plot(
x => 'voltage',
y => 'current',
hard_copy_suffix => '_IV',
);
# plot voltage versus current
$datafile->add_plot(
x => 'current',
y => 'voltage',
hard_copy_suffix => '_VI',
);
Refresh type 'block' for 2D plots
By default, 2D plots will be refreshed after every new point that is appended to the datafile. For pm3d
plots, the default is to refresh after every new block/line of data. When using datafile_dim = 2
with a 2D plot, as shown above, it is often useful to refresh only after each finished block:
$datafile->add_plot(
...
refresh => 'block',
);
As more and more data points are contained in a plot, refreshing the plot becomes slower. Without the refresh => 'block'
this would lead to a increasing delay of the measurement.
Refresh interval
We can set a mininum time between redraws of the live plot. This becomes handy for large plot, where the redrawing the plot is slow.
# Wait at least 10 minutes before redraw:
$datafile->add_plot(
...
refresh_interval => 600,
);
To ensure that the whole data is plotted at the end of the measurement, we force a redraw of all plots:
$sweep->refresh_plots(force => 1);
Block data
There are types of instruments which return more than a single data. Examples are spectrum and network analyzers, which perform a frequency sweep and return an array of data after each sweep.
FIXME: We need to link to a good introduction to PDL here.
The sparam_sweep
method provided, e.g., by the Lab::Moose::Instrument::RS_ZVA returns a 2D PDL with the following format:
[
[freq1 , freq2 , ..., freqN ],
[Re(S11)_1, Re(S11)_2, ..., Re(S11)_N],
[Im(S11)_1, Im(S11)_2, ..., Im(S11)_N],
[Amp_1 , Amp_2 , ..., Amp_N ],
[phase_1 , phase_2 , ..., phase_N ],
]
The following script sweeps a voltage source and performs a frequency sweep with the VNA for each level of the voltage source. Each VNA sweep is logged into a separate datafile which contains one line of data for each frequency point.
use Lab::Moose;
my $source = instrument(
type => 'YokogawaGS200',
connection_type => 'USB',
# Safety limits:
max_units => 10, min_units => -10,
max_units_per_step => 0.1, max_units_per_second => 1
);
my $vna = instrument(
type => 'RS_ZVA',
connection_type => 'VXI11',
connection_options => {host => '192.168.x.x'},
);
my $sweep = sweep(
type => 'Step::Voltage',
instrument => $source,
from => -5, to => 5, step => 0.01
);
my $datafile = sweep_datafile(
columns => [qw/voltage freq Re_S21 Im_S21 amplitude phase/]);
my $meas = sub {
my $sweep = shift;
my $voltage = $source->cached_level();
my $block = $vna->sparam_sweep(timeout => 10, average => 100);
$sweep->log_block(
prefix => {voltage => $voltage},
block => $block
);
};
$sweep->start(
measurement => $meas,
datafile => $datafile,
datafile_dim => 1, # each VNA trace in a separate file
point_dim => 1, # the measurement sub logs blocks, not points
);
Without the point_dim => 1
setting, only one datafile would be generated. One could also log all blocks into a single 2D datafile by setting datafile_dim => 2
.
log_block with single-point sweeps
Assume that we use the VNA to measure transmission at a single fixed frequency. In this case sparam_sweep
returns a 2D PDL where the first dimension has length one. One can still use log_block
for logging. By default log_block
does not trigger a refresh of live plots. This can be changed by adding refresh_plots => 1
to the log_block
arguments.
Continuous sweeps
With continuous sweeps, the sweep parameter is ramped in the background while data is recorded. This is in constrast with step/list sweeps where the sweep parameter is kept constant during data acquisition. The rate of measurement points taken is controlled by the interval
sweep attribute.
For example, the following time sweep records data every 0.5 seconds and finishes after 60 seconds:
use Lab::Moose;
my $sweep = sweep(
type => 'Continuous::Time',
interval => 0.5,
duration => 60
);
Configuration of continuous sweeps
In this example we sweep a magnet field with the Continuous::Magnet
sweep class. All subclasses of Continuous
work like this.
Note that the rate is given in Tesla/min.
my $sweep = sweep(
type => 'Continuous::Magnet',
instrument => $ips,
from => -1, # Tesla
to => 1,
rate => 0.1, # (Tesla/min, always positive)
start_rate => 1, # (optional, rate to approach start point)
interval => 0.5, # one measurement every 0.5 seconds
);
If the sweep should use different rates in different sections, use the points
, rates
, and intervals
arguments:
my $sweep = sweep(
type => 'Continuous::Magnet',
instrument => $ips,
points => [-1, -0.1, 0.1, 1],
# start rate: 1
# use slow rate 0.01 between points -0.1 and 0.1
rates => [1, 0.1, 0.01, 0.1],
intervals => [0.5], # one measurement every 0.5 seconds
);
If the rates
array contains fewer elements than the points
array, it will be filled with the last value.
If no interval
or intervals
parameter is provided a default of 0 is used. With an interval of 0, as many data points as possible are recorded without any delay between the measurement points.
Further sweep customizations
The delay_before_loop, delay_in_loop, and delay_after_loop attributes
These attributes can be used to introduce delays into a sweep:
my $sweep = sweep(
type => 'Step::Voltage',
instrument => $source,
from => -5, to => 5, step => 0.01,
delay_before_loop => 1.5,
delay_in_loop => 0.1,
delay_after_loop => 2.5,
);
With delay_before_loop
set, the sweep will sleep 1.5 seconds before starting the sweep (after going to the start point of the sweep). With delay_in_loop
set, there is a sleep between going to the setpoint and calling the measurement subroutine. The delay_after_loop
causes a delay between finishing the sweep and going back to the start point.
The before_loop coderef
The before_loop
coderef is used to execute arbitrary code at the start of a sweep:
my $before_loop = sub {
print("will start loop now\n");
};
my $sweep = sweep(
type => 'Step::Voltage',
instrument => $source,
from => -5, to => 5, step => 0.01,
before_loop => $before_loop,
);
The $before_loop
code is called after a possible delay_before_loop
delay.
Adding entries to META.yml
An arbitray hash of metadata can be added to META.yml my providing a meta_data
attribute to the start
method:
$sweep->start(
measurement => $meas,
datafile => $datafile,
meta_data => {foo_string => "123", bar_array => [1, 2, 3]},
);
Custom measurement control without the Sweep layer
Here we describe measurement control without the Sweep API. One can still use the Datafolder, Datafile, and live plotting features, as they are implemented independently of the Sweep layer. For example, the 2D sweep example from above could be rewritten like this:
use Lab::Moose; # get instrument, datafolder, datafile, linspace
use Lab::Moose::Countdown; # get countdown
my $gate_source = instrument(
type => 'DummySource',
connection_type => 'Debug',
connection_options => {verbose => 0},
# Safety limits:
max_units => 10, min_units => -10,
max_units_per_step => 0.11, max_units_per_second => 10
);
my $bias_source = instrument(
type => 'DummySource',
connection_type => 'Debug',
connection_options => {verbose => 0},
# Safety limits:
max_units => 10, min_units => -10,
max_units_per_step => 0.11, max_units_per_second => 10
);
my $folder = datafolder();
my $datafile = datafile(folder => $folder, filename => 'data.dat',
columns => [qw/gate bias current/]);
$datafile->add_plot(
type => 'pm3d',
x => 'gate',
y => 'bias',
z => 'current'
);
my @gate_values = linspace(from => 0, to => 1, step => 0.1);
my @bias_values = linspace(from => -1, to => 1, step => 0.1);
for my $gate_value (@gate_values) {
$gate_source->set_level(value => $gate_value);
# go to bias sweep start point and wait 5 sec
$bias_source->set_level(value => $bias_values[0]);
countdown(5);
for my $bias_value (@bias_values) {
$bias_source->set_level(value => $bias_value);
$datafile->log(
gate => $gate_value,
bias => $bias_value,
current => $bias_value + $gate_value,
);
}
$datafile->new_block();
}
$bias_source->set_level(value => 0);
One can also use the stabilization routines used by some sweep types like the Step::Temperature sweep:
use Lab::Moose;
use Lab::Moose::Stabilizer;
my $instrument = instrument(type => 'OI_ITC503', ...);
# Set temp and stabilize
$instrument->set_T(value => $temp);
stabilize(
instrument => $instrument,
setpoint => $temp,
getter => 'get_T',
tolerance_setpoint => 0.1,
tolerance_std_dev => 0.1,
measurement_interval => 10,
observation_time => 100,
);
Writing new instrument drivers
Detailed instructions for writing new instrument drivers are provided in Lab::Measurement::Developer.
COPYRIGHT AND LICENSE
This software is copyright (c) 2022 by the Lab::Measurement team; in detail:
Copyright 2006 Daniel Schroeer
2010 Daniel Schroeer
2011-2012 Andreas K. Huettel
2016 Andreas K. Huettel, Simon Reinhardt
2017 Andreas K. Huettel
2018 Andreas K. Huettel, Simon Reinhardt
2019-2020 Simon Reinhardt
2021 Fabian Weinelt, Simon Reinhardt
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.