Lab::Measurement::Legacy::Tutorial - Old Tutorial on using the historical/deprecated API of the Lab::Measurement package stack


version 3.701


The Lab::Measurement package stack allows to perform test and measurement tasks with Perl scripts. It provides an interface several hardware driver backends. Dedicated instrument driver classes relieve the user from taking care for internal details and make measurements as easy as


The Lab::Measurement software stack consists of several parts that are built on top of each other. This modularization allows support for a wide range of hardware on different operating systems. As hardware drivers vary in API details, each supported one is encapsulated into perl modules of types Lab::Bus and Lab::Connection. Normally you won't have to care about this; at most, your Instrument object (see below) gets different initialization parameters.

A typical measurement script is based on the high-level interface provided by the modules Lab::Instrument and Lab::Measurement. The former silently handles all the protocol overhead. You can write commands to an instrument and read the result. Drivers for specific devices are included, implementing their specific command syntax; more can easily be added to provide high-level functions. The latter includes tools for metadata handling (what was that amplifier setting in the measurement again?!), data plotting, and similar.

This tutorial will explain how to write measurement scripts. However, this tutorial does not intend to teach the Perl language itself. Some introduction into VISA and GPIB terminology is given, but then some familarity also with these concepts is assumed. If you feel the need for more information on Perl or VISA/GPIB, please see the "References" section [1-6].

Measurement automation basics

This section provides a very brief introduction to various ways of connecting measurement instruments to your control PC. We focus on the methods not so well-known to average PC users, i.e. VISA and GPIB programming. Usage of the higher level modules from the Lab::Instrument package requires almost no knowledge about VISA and GPIB at all, though.


Traditionally, test and measurement instruments can be connected and controlled via various standards and protocols. VISA, the Virtual Instrument Software Architecture [1,2], is an effort to provide a single standarised interface to communicate with instruments via several protocols. It was developed by the VXIplug&play Systems Alliance[4] and is currently maintained by the IVI foundation [5]. VISA can control VXI, GPIB, serial, or computer-based instruments and makes the appropriate driver calls depending on the type of instrument used. Hence, VISA is located in the application layer. The National Instruments NI-VISA library is one implementation of the VISA standard.

In one word: VISA tries to make it unimportant, how an instrument is connected physically.


GPIB (IEEE488)[3] is a lower lying standard invented by Hewlett-Packard. It describes a way of connecting instruments. The standard is divided into the physical layer IEEE488.1 that defines cables and signals and the command layer IEEE488.2 that describes a syntax for messages between communicating instruments. SCPI (Standard Commands for Programmable Instruments) is an extension of IEEE488.2 and refines the available commands further, with the goal of obtaining a language that is independent of the exact model of the instruments in use. This could be very useful, as, in theory, it would allow you to exchange one instrument in your setup with a similar one from another manufacturer, without having to change your measurement software. In practise however, not many instruments support this standard, and even if, small differences make things a pain. As described below, the Lab::Instrument package follows another route to achieve interchangeability by providing common interfaces for similar instruments at a much higher level (e.g. the Lab::Instrument::Source interface).

In one word: GPIB tries to make communication with various instruments more similar.


RS232 is the abbreviation for the serial port that used to be built into each PC. It provides a point-to-point connection to one instrument.


A schematic view of the various software layers between your perl measurement script and the instrument hardware is depicted in the graphics

The lowermost layer is provided by the hardware driver library and its Perl binding. One option for this is under Linux the package LinuxGPIB, which comes wth its own Perl bindings module. Alternatively, National Instruments NI-VISA can be used. In that case, the module Lab::VISA is required to access the library functions from Perl; it makes the standard VISA calls available from within Perl programs. This layer is not part of the Lab::Measurement distribution, but must be installed separately.

Each hardware backend is encapsulated into a class of the Lab::Bus type. A Bus can be imagined as a cable, connecting your control computer with several measurement hardware components. On top of the Bus classes, classes of type Lab::Connection operate. Each connection, well, connects one measurement instrument with your script. Usually, the handling of Bus and Connection is transparent; as long as you dont want to add more backends or enhance the functionality, you will never have any need to directly address these levels.

The Lab::Instrument classes build on top and simplify the routine tasks of opening a connection to an instrument, sending and receiving messages. This is the level where usually customized measurement scripts access the protocol stack. Classes derived from Lab::Instrument as e.g. Lab::Instrument::KnickS252 are specialized modules for certain instruments. Most other measurement software packages would call this a virtual instruments or an instrument drivers. Each such class provides methods that are specific for one instrument. The Lab::Instrument::IPS120_10 class for example class is dedicated to a certain magnet power supply and therefore provides methods like set_target_field. Similar instruments (e.g. various voltage sources) can share common interfaces (e.g. Lab::Instrument::Source) to make interchangeability of similar instruments possible.

The highest abstraction layer is provided by the Lab::Measurement class, which contains methods for data and metadata handling, plotting and rudimentary keyboard control.

Using the Lab::Instrument class

The Lab::Instrument class can do for us the routine work of connecting to an instrument.

  use strict;
  use Lab::Instrument;
  unless (@ARGV > 0) {
        print "Usage: $0 GPIB-address\n";
  my $gpib=$ARGV[0];
  print "Querying ID of instrument at GPIB address $gpib\n";
  my $i=new Lab::Instrument(
        gpib_address => $gpib,
  my $id=$i->query('*IDN?');
  print "Query result: \"$id\"\n";

This program opens a GPIB instrument for communication, sends the command *IDN? and reads out its response, the identification string of the instrument. All handling of GPIB boards, resource managers etc. is done within the Lab::Instrument class; we don't have to care about string lengths and cleaning up. Lab::Instrument does it for us. Now that's already quite nice, eh?

By only using Lab::Instrument you should already be able to do about everything that can be done with the instruments in your lab.

Using Lab::Instrument::xxx virtual instruments

Many common tasks, like reading a voltage from a digital multimeter, require that a series of GPIB commands is sent to an instrument. These commands are different for similar instruments from different manufacturers.

The virtual instrument classes in the Lab::Instrument package attempt to hide these details from the user by providing high level methods like set_voltage($voltage) and get_voltage().

Additionally they provide an optional safety mechanism for voltage sources. This is used to protect sensitive samples which could be destoyed by sudden voltage changes. See the documentation of the Lab::Instrument::Source module for details.

  use strict;
  use Lab::Instrument::HP34401A;
  unless (@ARGV > 0) {
        print "Usage: $0 GPIB-address\n";
  my $hp_gpib=$ARGV[0];
  print "Reading voltage from HP34401A at GPIB address $hp_gpib\n";
  my $hp=new Lab::Instrument::HP34401A(
        gpib_address => $hp_gpib,
  my $volt=$hp->$get_voltage_dc(10,0.00001);
  print "Result: $volt V\n";

This example show the usage of a dedicated virtual instrument class, namely Lab::Instrument::HP34401A, the driver for a Hewlett-Packard/Agilent 34401A digital multimeter. An instance of this class is created that is connected to one certain instrument. We use the get_voltage_dc() method that configures the multimeter for dc voltage measurement in the range given by the parameters, triggers one measurement, and returns the measured voltage value.

Next we show an example on how to use the safety mechanism of Lab::Instrument::Source that is inherited by voltage sources like Lab::Instrument::Yokogawa7651.

  use strict;
  use Lab::Instrument::Yokogawa7651;
  unless (@ARGV > 0) {
        print "Usage: $0 GPIB-address [Target-voltage]\n";
  my ($gpib,$goto)=@ARGV;
  my $source=new Lab::Instrument::Yokogawa7651(
        gpib_address => $gpib,
  if (defined $goto) {
  } else {
        print $source->get_voltage();

Here the gate_protect mechanism limits the step size of the voltage source to 0.005mV, and the sweep speed to at most 10 such steps per second. This is implemented automatically within the set_voltage($goto) command; after we have set the parameters in the initialization phase, we do not have to take care of it anymore.

Using the high-level Lab::Measurement and related classes

With the tools introduced so far you should be able to easily write short individual scripts for your measurement tasks. These scripts will probably serve as well as all other home grown solutions using LabView or whatever. The Lab::Measurement class together with the related Lab::Data:... classes now provide additional tools to write better measurement scripts.

One main goal is to provide means to keep additional information stored along with the raw measured data. Additional information means all the notes that you would usually write down in your laboratory book, like date and time, settings of additional instruments, the environment temperature, the color of the shirt you were wearing while recording the data and everything else that might be of importance for a later interpretation of the data. In my experience, having to write these things in a book by hand is tedious and error-prone. It's the kind of job that computers were made for.

Another goal is to free the experimenter from having to repeat himself all the time when the data is used for analysis or presentation. Let us assume that, for example, you are measuring a very small current with the help of a current amplifier. This current amplifier will output a voltage that is proportional to the original current, so in fact you will be measuring a voltage that can be converted to the original current by multiplying it with a certain factor. But as long as the precise formula for this transformation is not stored together with the data, you will still find yourself repeatedly typing in the same expressions, whenever you work with the data. This is where the axis concept comes into play. Already at the time you are preparing your measurement script, you define an axis named current that stores the expression to calculate the current from the voltage. From there you work with the current-axis and will never have to care about the conversion again. And of course you can define many different axes. Read on!

The concept of sweeps

The Sweep classes provide a high-level interface for measurement automation. The following script explains the basic use of sweeps. This example shows a two-dimensional Voltage Sweep: The master sweep controls the gate voltage. For each value of the gate voltage we perform a slave sweep of the source-drain voltage.

We perform a measurement task at each grid point. This is done by providing a callback subroutine. In our example, the callback reads the value of a multimeter and logs to a DataFile object.

  #-------- 1. Import Lab::Measurement -------
  use warnings;
  use strict;
  use 5.010;
  use Lab::Measurement;
  #-------- 2. Some constants ----------------
  my $gain = -1e-9;         # A/V amplifier sensit.
  my $stepwidthbias = 0.05; # step width bias
  my $stepwidthgate = 0.1;  # step width gate
  my $NPLC=2;               # integration time, 2*20ms
  #-------- 3. Initialize Instruments --------
  my $gate_source = Instrument('YokogawaGS200', 
      connection_type => 'VISA_GPIB',
      gpib_address => 2,
      gate_protect => 0
  my $bias_source = Instrument('YokogawaGS200', 
      connection_type => 'VISA_GPIB',
      gpib_address => 6,
      gate_protect => 0
  my $DMM_I = Instrument('HP34401A', 
      connection_type => 'VISA_GPIB',
      gpib_address => 14,
      nplc => $NPLC
  #-------- 4. Define the Sweeps -------------
  my $bias_sweep = Sweep('Voltage', 
      mode => 'step',                # step, list, sweep/continuous
      instrument => $bias_source,
      points => [-1,1],              # starting point, end point
      stepwidth => [$stepwidthbias],
      rate => [1, 0.005],            # rate to approach start, sweep rate 
                                     #  for measurement (unused), V/s
      jump => 1,                     # jump to next point, no sweep
      delay_before_loop => 3         # settle 3s before starting
  my $gate_sweep = Sweep('Voltage', 
      mode => 'step',                # step, list, sweep/continuous
      instrument => $gate_source,
      points => [-0.5,0.5],          # starting point, end point
      stepwidth => [$stepwidthgate],
      rate => [0.03, 0.03],          # rate to approach start, sweep rate
                                     #  for measurement (unused), V/s
      jump => 1                      # jump to next point, no sweep
  #-------- 5. Create a DataFile -------------
  my $DataFile = DataFile('DCDiamond');
      'type' => 'pm3d',
      'x-axis' => 'Gate',
      'y-axis' => 'Bias', 
      'cb-axis' => 'Current',
      'refresh' => 'block'
  #-------- 6. Measurement Instructions -------

  # Define the callback. This subroutine will be called at each point of the
  # parameter grid.
  my $my_measurement = sub {
      # this is run for each measurement point
      my $sweep = shift;

      # read_mode => 'cache' means use the value last written by Perl to the
      # device, but do not query the instrument.
      my $value1 = $gate_source->get_value({read_mode => 'cache'});
      my $value2 = $bias_source->get_value({read_mode => 'cache'});

      my $value3 = $DMM_I->get_value() * $gain;
          Gate => $value1,
          Bias => $value2,
          Current => $value3,
  #-------- 7. Put everything together -------
  my $frame=Frame();
  #-------- 8. And GO! -----------------------

For full details, see the documentation of the various sweep classes.


To be done


[1] NI-VISA User Manual (
[2] NI-VISA Programmer Manual (
[3] NI 488.2 User Manual (


This software is copyright (c) 2020 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

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.