The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Lab::Instrument - Instrument base class

SYNOPSIS

Lab::Instrument is meant to be used as a base class for inheriting instruments. For very simple applications it can also be used directly, like

  $generic_instrument = new Lab::Instrument ( connection_type => VISA_GPIB, gpib_address => 14 );
  my $idn = $generic_instrument->query('*IDN?');

Every inheriting class constructor should start as follows:

  sub new {
    my $proto = shift;
    my $class = ref($proto) || $proto;
    my $self = $class->SUPER::new(@_);
    $self->${\(__PACKAGE__.'::_construct')}(__PACKAGE__);  # check for supported connections, initialize fields etc.
    ...
  }

Beware that only the first set of parameters specific to an individual GPIB board or any other bus hardware gets used. Settings for EOI assertion for example.

If you know what you're doing or you have an exotic scenario you can use the connection parameter "ignore_twins => 1" to force the creation of a new bus object, but this is discouraged - it will kill bus management and you might run into hardware/resource sharing issues.

DESCRIPTION

Lab::Instrument is the base class for Instruments. It doesn't do much by itself, but is meant to be inherited in specific instrument drivers. It provides general read, write and query methods and basic connection handling (internally, _set_connection, _check_connection).

CONSTRUCTOR

new

This blesses $self (don't do it yourself in an inheriting class!), initializes the basic "fields" to be accessed via AUTOLOAD and puts the configuration hash in $self->config to be accessed in methods and inherited classes.

Arguments: just the configuration hash (or even-sized list) passed along from a child class constructor.

METHODS

write

 $instrument->write($command <, {optional hashref/hash}> );
 

Sends the command $command to the instrument. An option hash can be supplied as second or also as only argument. Generally, all options are passed to the connection/bus, so additional named options may be supported based on the connection and bus and can be passed as a hashref or hash. See Lab::Connection.

Optional named parameters for hash:

 error_check => 1/0

Invoke $instrument->check_errors after write. Defaults to off.

read

 $result=$instrument->read({ read_length => <max length>, brutal => <1/0>);

Reads a result of ReadLength from the instrument and returns it. Returns an exception on error.

If the parameter brutal is set, a timeout in the connection will not result in an Exception thrown, but will return the data obtained until the timeout without further comment. Be aware that this data is also contained in the the timeout exception object (see Lab::Exception).

Generally, all options are passed to the connection/bus, so additional named options may be supported based on the connection and bus and can be passed as a hashref or hash. See Lab::Connection.

query

 $result=$instrument->query({ command => $command,
                                  wait_query => $wait_query,
                              read_length => $read_length);

Sends the command $command to the instrument and reads a result from the instrument and returns it. The length of the read buffer is set to read_length or to the default set in the connection.

Waits for wait_query microseconds before trying to read the answer.

Generally, all options are passed to the connection/bus, so additional named options may be supported based on the connection and bus and can be passed as a hashref or hash. See Lab::Connection.

get_error

        ($errcode, $errmsg) = $instrument->get_error();

Method stub to be overwritten. Implementations read one error (and message, if available) from the device.

get_status

        $status = $instrument->get_status();
        if( $instrument->get_status('ERROR') ) {...}
        

Method stub to be overwritten. This returns the status reported by the device (e.g. the status byte retrieved via serial poll from GPIB devices). When implementing, use only information which can be retrieved very fast from the device, as this may be used often.

Without parameters, has to return a hashref with named status bits, e.g.

 $status => {
        ERROR => 1,
        DATA => 0,
        READY => 1
 }

If present, the first argument is interpreted as a key and the corresponding value of the hash above is returned directly.

The 'ERROR'-key has to be implemented in every device driver!

check_errors

        $instrument->check_errors($last_command);
        
        # try
        eval { $instrument->check_errors($last_command) };
        # catch
        if ( my $e = Exception::Class->caught('Lab::Exception::DeviceError')) {
                warn "Errors from device!";
                @errors = $e->error_list();
                @devtype = $e->device_class();
                $command = $e->command();               
        }

Uses get_error() to check the device for occured errors. Reads all present errors and throws a Lab::Exception::DeviceError. The list of errors, the device class and the last issued command(s) (if the script provided them) are enclosed.

_check_args

Parse the arguments given to a method. The typical use is like this:

 sub my_method () {
     my $self = shift;
     my ($arg_1, $arg_2, $tail) = $self->_check_args(\@_, ['arg1', 'arg2']);
     ...
 }

There are now two ways, how a user can give arguments to my_method. Both of the following calls will assign $value1 to $arg1 and $value2 to $arg2.

old style:
 $instrument->my_method($value1, $value2, $tail);
new style:
 $instrument->my_method({arg1 => $value1, arg2 => $value2});

Remaining key-value pairs will be consumed by $tail. For example, after

 $instrument->my_method({arg1 => $value1, arg2 => $value2, x => $value_x});

$tail will hold the hashref {x => $value_x}.

Multiple hashrefs given to my_method are concatenated.

For a method without named arguments, you can either use

 my ($tail) = $self->_check_args(\@_, []);

or

 my ($tail) = $self->_check_args(\@);

_check_args_strict

Like _check_args, but makes all declared arguments mandatory.

If an argument does not receive a non-undef value, this will throw an exception. Thus, the returned array will never contain undefined values.

CAVEATS/BUGS

Probably many, with all the porting. This will get better.

SEE ALSO

AUTHOR/COPYRIGHT

 Copyright 2004-2006 Daniel Schröer <schroeer@cpan.org>, 
           2009-2010 Daniel Schröer, Andreas K. Hüttel (L<http://www.akhuettel.de/>) and David Kalok,
           2010      Matthias Völker <mvoelker@cpan.org>
           2011      Florian Olbrich, Andreas K. Hüttel
           2012      Andreas K. Hüttel
           2013      Stefan Geissler, Christian Butschkow, Andreas K. Hüttel

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