NAME
Lab::Measurement::Developer - Lab::Measurement developer tutorial
VERSION
version 3.860
Writing drivers
The driver infrastructure is based on Moose. For Moose basics see e.g.
The Modern Perl book by chromatic, available online for free, contains a chapter on Moose.
For full details, see the very well written Moose::Manual.
Code example
We start with a section of code from the Lab::Moose::Instrument::SR830 LIA driver and discuss the most important steps. This explains the most important parts of a driver, i.e. initialization, getters, setters, caching, ...
package Lab::Moose::Instrument::SR830;
use 5.010;
use Moose;
use MooseX::Params::Validate;
use Lab::Moose::Instrument qw/validated_getter validated_setter/;
use Lab::Moose::Instrument::Cache;
use Carp;
use namespace::autoclean;
our $VERSION = '3.520';
# (1)
extends 'Lab::Moose::Instrument';
# (2)
with qw/Lab::Moose::Instrument::Common/;
# (3)
sub BUILD {
my $self = shift;
$self->clear();
$self->cls();
}
# (4)
cache amplitude => (getter => 'get_amplitude');
# (5)
sub get_amplitude {
my ($self, %args) = validated_getter(\@_);
# (6)
return $self->cached_amplitude(
$self->query( command => 'SLVL?', %args ) );
}
sub set_amplitude {
# (7)
my ( $self, $value, %args ) = validated_setter(
\@_,
value => { isa => 'Num' }
);
# (8)
$self->write( command => "SLVL $value", %args );
$self->cached_amplitude($value);
}
# (9)
__PACKAGE__->meta()->make_immutable();
1;
Explanations
-
extends 'Lab::Moose::Instrument';
All drivers inherit from Lab::Moose::Instrument. This base class provides the access to the underlying connection via methods like
write
,query
andclear
. -
with qw/Lab::Moose::Instrument::Common/;
The Lab::Moose::Instrument::Common role contains methods for GPIB common commands like *IDN, *RST, *CLS, ...
-
sub BUILD { my $self = shift; $self->clear(); $self->cls(); }
This
BUILD
method (see Moose::Manual::Construction) executes a device clear and clears the error status. -
cache amplitude => (getter => 'get_amplitude');
Accessing instruments settings by querying them from the device can be slow. It is mutch faster if the setters and getters store the setting in an object attribute (See Moose::Manual::Attributes). This line creates an attribute for storing the amplitude value of the LIA's reference output.
The attribute can then be accessed with the
cached_amplitude
method.If the getter is called while the attributes is unset, the
get_amplitude
method will be called under the hood to initialize the attribute.What if the initialization should call the get_amplitude method with additional arguments, say
timeout => 10
? This can be done by overwriting the builder method of the attribute in your driver:sub cached_amplitude_builder { my $self = shift; return $self->get_amplitude( timeout => 10 ); }
See Lab::Moose::Instrument::Cache for full details.
-
sub get_amplitude { my ($self, %args) = validated_getter(\@_);
We come to the getter function, which queries the amplitude from the LIA. The
validated_getter
function (from Lab::Moose::Instrument) allows the user to pass additional options, like a timeout, to the underlying connection:my $amplitude = $self->get_amplitude(timeout => 10); my $amplitude = $self->get_amplitude(); # Use default timeout.
-
return $self->cached_amplitude( $self->query( command => 'SLVL?', %args ) );
We read the amplitude from the instrument and store it's value into the cache. Don't forget the
%args
argument toquery
! -
sub set_amplitude { my ( $self, $value, %args ) = validated_setter( \@_, value => { isa => 'Num' } );
The
validated_setter
function parses the arguments of the setter method. We require that the value argument is a number. -
$self->write( command => "SLVL $value", %args ); $self->cached_amplitude($value);
We pass the new amplitude to the instrument and update the cache.
-
__PACKAGE__->meta()->make_immutable();
Every Moose class shell end this way. See Moose::Manual::BestPractices.
Building automated instrument tests
Lab::Moose has extensive support to build automated tests for instrument drivers and this is what enables long-term maintainability of the code base.
If you are new to automated testing with Perl, consider the Modern Perl book, which covers all of the basics.
A test file t/Moose/Instrument/SR830.t for the above driver could look like this:
#!perl
use warnings;
use strict;
use lib 't';
use Lab::Test import => [qw/set_get_test/];
use Moose::Instrument::MockTest qw/mock_instrument/;
use MooseX::Params::Validate;
use File::Spec::Functions 'catfile';
my $log_file = catfile(qw/t Moose Instrument SR830.yml/);
my $lia = mock_instrument(
type => 'SR830',
log_file => $log_file,
);
isa_ok( $lia, 'Lab::Moose::Instrument::SR830' );
$lia->rst( timeout => 10 );
# Test the amplitude getter and setter
set_get_test(
instr => $lia,
values => [qw/0.004 1 2 3 5/],
getter => 'get_amplitude',
setter => 'set_amplitude',
cache => 'cached_amplitude',
);
$lia->rst();
done_testing();
First thing, we need to run the test with the real instrument, to create the connection log file t/Moose/Instrument/SR830.yml:
$ perl -Ilib t/Moose/Instrument/SR830.t --connection=LinuxGPIB --connection-options='{pad: 1}'
where the argument of --connection-options
is given as a YAML hash.
You can always print a help screen of command line options supported by the test:
$ perl -Ilib t/Moose/Instrument/SR830.t --help
Now with the connection log in place, you can run the test without the real instrument connected:
$ prove -lv t/Moose/Instrument/SR830.t
If set_get_test
is not enough for you, take a look at the other test routines in t/Lab/Test.pm which offer
Floating point number comparison (absolute error, relative error, ...)
File comparison, including basic filtering options.
git pre-commit hook: run tests for each commit
The file xt/pre-commit.pl provides a git pre-commit hook.
The hook is enabled by creating a link to .git/hooks/pre-commit:
ln -s xt/pre-commit.pl .git/hooks/pre-commit
The hook performs the following actions before a commit is finished:
Run perltidy with our configuration perltityrc on all changed files.
Run all tests in t/ with prove.
Run Perl::Critic tests in xt/critic.
Run xt/pod-manual-coverage.t, which ensures that Lab::Measurement::Manual contains links to all modules in the distribution.
If a tests fails, the commit is stopped.
Roles for SCPI instruments
TODO
Writing connections
TODO
Data files and plotting
TODO
COPYRIGHT AND LICENSE
This software is copyright (c) 2023 by the Lab::Measurement team; in detail:
Copyright 2017-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.