The Perl and Raku Conference 2025: Greenville, South Carolina - June 27-29 Learn more

$Lab::Moose::Instrument::Keithley2450::VERSION = '3.930';
#ABSTRACT: Keithley 2450 voltage/current sourcemeter.
use v5.20;
use Moose;
qw/validated_getter validated_setter setter_params/;
use Carp;
around default_connection_options => sub {
my $orig = shift;
my $self = shift;
my $options = $self->$orig();
my $usb_opts = { vid => 0x05e6, pid => 0x2450 }; # FIXME
$options->{USB} = $usb_opts;
$options->{'VISA::USB'} = $usb_opts;
return $options;
};
has [qw/max_units_per_second max_units_per_step min_units max_units/] =>
( is => 'ro', isa => 'Num', required => 1 );
has source_level_timestamp => (
is => 'rw',
isa => 'Num',
init_arg => undef,
);
has verbose => (
is => 'ro',
isa => 'Bool',
default => 1
);
sub BUILD {
my $self = shift;
$self->clear();
$self->cls();
}
sub set_level {
my ( $self, $value, %args ) = validated_setter(
\@_,
value => { isa => 'Num' },
);
return $self->linear_step_sweep(
to => $value, verbose => $self->verbose,
%args
);
}
sub get_value {
my ( $self, %args ) = validated_getter( \@_ );
return $self->query( command => 'READ?', %args );
}
sub source_limit {
my ( $self, $value, %args ) = validated_setter(
\@_,
value => { isa => 'Num' },
);
my $func = $self->cached_source_function();
my $lim_func;
if ( $func eq 'VOLT' ) {
$lim_func = 'I';
}
elsif ( $func eq 'CURR' ) {
$lim_func = 'V';
}
else {
croak("unknown source function $func (must one of VOLT or CURR)");
}
$self->write( command => "SOUR:${func}:${lim_func}LIM $value", %args );
}
sub source_limit_query {
my ( $self, %args ) = validated_getter( \@_ );
my $func = $self->cached_source_function();
my $lim_func;
if ( $func eq 'VOLT' ) {
$lim_func = 'I';
}
elsif ( $func eq 'CURR' ) {
$lim_func = 'V';
}
else {
croak("unknown source function $func (must one of VOLT or CURR)");
}
return $self->query( command => "SOUR:${func}:${lim_func}LIM?", %args );
}
#
# Aliases for Lab::XPRESS::Sweep API
#
sub cached_level {
my $self = shift;
return $self->cached_source_level(@_);
}
sub get_level {
my $self = shift;
return $self->source_level_query(@_);
}
sub set_voltage {
my $self = shift;
my $value = shift;
return $self->set_level( value => $value );
}
with qw(
Lab::Moose::Instrument::SCPI::Output::State
Lab::Moose::Instrument::SCPI::Sense::Function
Lab::Moose::Instrument::SCPI::Sense::Range
Lab::Moose::Instrument::SCPI::Sense::NPLC
Lab::Moose::Instrument::SCPI::Source::Function
Lab::Moose::Instrument::SCPI::Source::Level
Lab::Moose::Instrument::SCPI::Source::Range
Lab::Moose::Instrument::LinearStepSweep
);
__PACKAGE__->meta()->make_immutable();
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
Lab::Moose::Instrument::Keithley2450 - Keithley 2450 voltage/current sourcemeter.
=head1 VERSION
version 3.930
=head1 SYNOPSIS
use Lab::Moose;
my $smu = instrument(
type => 'Keithley2450',
connection_type => 'LinuxGPIB',
connection_options => {gpib_address => 15},
# mandatory protection settings
max_units_per_step => 0.001, # max step is 1mV/1mA
max_units_per_second => 0.01,
min_units => -10,
max_units => 10,
);
### Sourcing
# Source voltage
$smu->source_function(value => 'VOLT');
$smu->source_range(value => 210);
# Step-sweep to new level.
# Stepsize and speed is given by (max|min)_units* settings.
$smu->set_level(value => 9);
# Get current level from device cache (without sending a query to the
# instrument):
my $level = $smu->cached_level();
### Measurement
# Measure current
$smu->sense_function(value => 'CURR');
$smu->sense_nplc(value => 2);
# Get value of current
my $current = $smu->get_value();
=head1 METHODS
Used roles:
=over
=item L<Lab::Moose::Instrument::Common>
=item L<Lab::Moose::Instrument::SCPI::Output::State>
=item L<Lab::Moose::Instrument::SCPI::Sense::Range>
=item L<Lab::Moose::Instrument::SCPI::Sense::NPLC>
=item L<Lab::Moose::Instrument::SCPI::Source::Function>
=item L<Lab::Moose::Instrument::SCPI::Source::Level>
=item L<Lab::Moose::Instrument::SCPI::Source::Range>
=item L<Lab::Moose::Instrument::LinearStepSweep>
=back
=head2 set_level
$smu->set_level(value => $new_level);
Go to new level. Sweep with multiple steps if the distance between current and
new level is larger than C<max_units_per_step>.
=head2 get_value
my $value = $smu->get_value();
Perform measurement of value defined by C<sense_function>.
=head2 source_limit/source_limit_query
Set current compliance limit of voltage source to 1mA
$smu->source_function(value => 'VOLT');
$smu->source_limit(value => 1e-3);
Set voltage compliance limit of current source to 1V
$smu->source_function(value => 'CURR');
$smu->source_limit(value => 1);
Get current source limit
my $limit = $smu->source_limit_query();
=head2 cached_level
my $current_level = $smu->cached_level();
Get current value from device cache.
=head2 get_level
my $current_level = $smu->get_level();
Query current level.
=head2 set_voltage
$smu->set_voltage($value);
For XPRESS voltage sweep. Equivalent to C<< set_level(value => $value) >>.
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2025 by the Lab::Measurement team; in detail:
Copyright 2021 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.
=cut