++ed by:
AMBA

1 PAUSE user
1 non-PAUSE user.

Andreas K. Hüttel
and 4 contributors

Implementing a current/voltage source driver

This document is ment as a guideline to and a help with the implementation of drivers for current and voltage sources. Since the complexity of the Lab::Instrument and Lab::Instrument::Source classes increases, it becomes more and more cumbersome to carefully read the (sometimes outdated) class documentation to keep track of correct interfaces, i.e., required methods and return values, to provide source device drivers.

The config hash

Let us start with what comes first, the config hash. It is used to provide default values for parameters that control the higher level functionality, namely gate_protect and to define the device parameters that should be stored internally (e.g. the range or the current output mode). At the moment when this documentation is written, an example for a correct config hash can be found in the class definition of the YokogawaGS200:

  our %fields = (
        supported_connections => [ 'VISA_GPIB', 'GPIB', 'VISA', 'DEBUG' ],

        # default settings for the supported connections
        connection_settings => {
                gpib_board => 0,
                gpib_address => 22,
        },


        device_settings => {
        
                gate_protect            => 1,
                gp_equal_level          => 1e-5,
                gp_max_units_per_second  => 0.05,
                gp_max_units_per_step    => 0.005,
                gp_max_step_per_second  => 10,
                
                stepsize                => 0.01,  # default stepsize for sweep without gate protect
        
         
                max_sweep_time=>3600,
                min_sweep_time=>0.1,
        },
        
        # If class does not provide set_$var for those, AUTOLOAD will take care.
        device_cache => {
                function                        => "VOLT", # 'VOLT' - voltage, 'CURR' - current
                range                   => undef,
                level                   => undef,
                output                                  => undef,
        },
        
        device_cache_order => ['function','range'],
  );
  

Let me introduce the objects in this hash. connection_settings is more or less self-explanatory and should be overwritten by the user anyway.

The device_settings hash

The device_settings hash contains, in the case of a source driver, all the settings that are important to use the gate_protect feature of the Lab::Instrument::Source class. The values given are a careful choice, the user who wants to use gate protect will redefine them anyway. For a new driver, the hash can just be copy/pasted.

The device_cache hash

The device_cache hash contains all device parameters, i.e., parameters that can be set and read to and from the device, which should be stored on the software side. It is your decision what variables you add to the list, but make sure you

1. implement getter and setter for all these variables except the Current/Voltage level.
2. use undef as default if it is likely that this parameter is given on init. If it is not given, it will be read from the device.

The device_cache_order array

If the order of initializing parameters on the device is important, you should specify the order in this array.

The getter methods

The default for the getter should be to return the cached variable, i.e. the variable which is stored on the computer. If the option

  from_device => 1
  

is given, the variable should be read from the device.

The setter methods

should always set both on device and in the software cache. You can also use a

  error_check=>1
  

in the $self-write> command, then a possible error which appears on the device will automatically be set. Read also the section on error checking.

Default values

Best is to use undef.

Methods that MUST be provided by the device class

Please make sure you implement the following:

1. get/set for each variable in the device_cache with one exception: set_level. The setter should return the set value.
2. The sub _set_level($target) which will be called from Lab::Instrument::Source to use gate protect. Implement instead of set_level().
3. A function get_status().

The status sub

The sub get_status should read out the status byte of the device and create a hash with a descriptive flag and the state of the corresponding bit. The error bit should have the key "ERROR".

Methods that should be implemented

It is convenient to implement the follwoing functions if possible:

1. A sub _sweep_to_level($target,$time).
2. A sub get_error().

The sweep function

_sweep_to_level($target,$time) is given a target level $target and a sweep time $time. If the device supports this functionality, it should be implemented here. It should return $target.

get_error()

should read out the device's error stack. It should return ONE error at once in a single array with

  [$errorcode,$errormessage]
  

The error checking framework

It is possible to wrap every write($cmd) call by an error checking routine. This can be invoked by providing the option error_check. For example:

  $self->write($cmd,'error_check' => 1)
  

After sending the command in $cmd to the device, the framework will use get_status() to read out the ERROR status bit. If it is set, get_error() will be used to fetch the error from the device.

General remarks on device driver developement

Allow pass-through of commands in set & get

The advanced user should be given the possibility to do dirty workarounds when using the driver. To do this, he can provide options in the write() call, that are interpreted on connection level. This should in general also be possible when using set_level or any command that involves a write() call.