line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#$Id: Source.pm 650 2010-04-22 19:09:27Z schroeer $
|
2
|
|
|
|
|
|
|
package Lab::Instrument::Source;
|
3
|
2
|
|
|
2
|
|
23252
|
use strict;
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
74
|
|
4
|
2
|
|
|
2
|
|
821
|
use Time::HiRes qw(usleep gettimeofday);
|
|
2
|
|
|
|
|
1942
|
|
|
2
|
|
|
|
|
12
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = sprintf("1.%04d", q$Revision: 650 $ =~ / (\d+) /);
|
7
|
|
|
|
|
|
|
our $maxchannels = 16;
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
sub new {
|
10
|
2
|
|
|
2
|
0
|
22
|
my $proto = shift;
|
11
|
2
|
|
33
|
|
|
16
|
my $class = ref($proto) || $proto;
|
12
|
|
|
|
|
|
|
|
13
|
2
|
|
|
|
|
7
|
my $self = bless {}, $class;
|
14
|
|
|
|
|
|
|
|
15
|
2
|
|
|
|
|
8
|
my $type=ref $_[0];
|
16
|
|
|
|
|
|
|
|
17
|
2
|
50
|
0
|
|
|
12
|
if ($type =~ /HASH/) {
|
|
|
0
|
|
|
|
|
|
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# Source gets as parameters 1) the default config of a particular
|
20
|
|
|
|
|
|
|
# source class and 2) the config with which the source was instantiated
|
21
|
|
|
|
|
|
|
|
22
|
2
|
|
|
|
|
5
|
%{$self->{default_config}}=%{shift @_};
|
|
2
|
|
|
|
|
21
|
|
|
2
|
|
|
|
|
10
|
|
23
|
2
|
|
|
|
|
6
|
%{$self->{config}}=%{$self->{default_config}};
|
|
2
|
|
|
|
|
10
|
|
|
2
|
|
|
|
|
8
|
|
24
|
2
|
|
|
|
|
16
|
$self->configure(@_);
|
25
|
|
|
|
|
|
|
|
26
|
2
|
|
|
|
|
10
|
for (my $i=1; $i<=$maxchannels; $i++) {
|
27
|
32
|
|
|
|
|
50
|
my $tmp="last_voltage_$i";
|
28
|
32
|
|
|
|
|
69
|
$self->{_gp}->{$tmp}=undef;
|
29
|
32
|
|
|
|
|
42
|
$tmp="last_settime_mus_$i";
|
30
|
32
|
|
|
|
|
951
|
$self->{_gp}->{$tmp}=undef;
|
31
|
|
|
|
|
|
|
}
|
32
|
|
|
|
|
|
|
|
33
|
2
|
|
|
|
|
9
|
$self->{subsource}=0;
|
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
} elsif (($type =~ /^Lab::Instrument/) && ($_[0]->{IamaSource})) {
|
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
# Whenever the first parameter is not a default config hash but a
|
38
|
|
|
|
|
|
|
# class object inherited from Lab::Instrument with IamaSource set,
|
39
|
|
|
|
|
|
|
# we are instantiating a subsource of a multichannel source.
|
40
|
|
|
|
|
|
|
|
41
|
0
|
|
|
|
|
0
|
print "Hey great! Someone is testing subchannel sources...\n";
|
42
|
0
|
|
|
|
|
0
|
$self->{multisource}=shift;
|
43
|
0
|
|
|
|
|
0
|
$self->{channel}=shift;
|
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
# the default config is in this case the actual config of the
|
46
|
|
|
|
|
|
|
# multisource object
|
47
|
0
|
|
|
|
|
0
|
%{$self->{default_config}}=%{$self->{multisource}->{config}};
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
48
|
0
|
|
|
|
|
0
|
%{$self->{config}}=%{$self->{default_config}};
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
49
|
0
|
|
|
|
|
0
|
$self->configure(@_);
|
50
|
|
|
|
|
|
|
|
51
|
0
|
|
|
|
|
0
|
$self->{subsource}=1;
|
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
};
|
54
|
|
|
|
|
|
|
|
55
|
2
|
|
|
|
|
4
|
$self->{IamaSource}=1;
|
56
|
2
|
|
|
|
|
15
|
return $self;
|
57
|
|
|
|
|
|
|
}
|
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
sub configure {
|
60
|
22
|
|
|
22
|
1
|
36
|
my $self=shift;
|
61
|
|
|
|
|
|
|
#supported config options are (so far)
|
62
|
|
|
|
|
|
|
# gate_protect
|
63
|
|
|
|
|
|
|
# gp_max_volt_per_second
|
64
|
|
|
|
|
|
|
# gp_max_volt_per_step
|
65
|
|
|
|
|
|
|
# gp_max_step_per_second
|
66
|
|
|
|
|
|
|
# gp_min_volt
|
67
|
|
|
|
|
|
|
# gp_max_volt
|
68
|
|
|
|
|
|
|
# qp_equal_level
|
69
|
|
|
|
|
|
|
# fast_set
|
70
|
22
|
|
|
|
|
33
|
my $config=shift;
|
71
|
22
|
100
|
|
|
|
76
|
if ((ref $config) =~ /HASH/) {
|
|
|
100
|
|
|
|
|
|
72
|
9
|
|
|
|
|
16
|
for my $conf_name (keys %{$self->{default_config}}) {
|
|
9
|
|
|
|
|
40
|
|
73
|
|
|
|
|
|
|
#print "Key: $conf_name, default: ",$self->{default_config}->{$conf_name},", old config: ",$self->{config}->{$conf_name},", new config: ",$config->{$conf_name},"\n";
|
74
|
55
|
50
|
33
|
|
|
413
|
unless ((defined($self->{config}->{$conf_name})) || (defined($config->{$conf_name}))) {
|
|
|
100
|
|
|
|
|
|
75
|
0
|
|
|
|
|
0
|
$self->{config}->{$conf_name}=$self->{default_config}->{$conf_name};
|
76
|
|
|
|
|
|
|
} elsif (defined($config->{$conf_name})) {
|
77
|
15
|
|
|
|
|
38
|
$self->{config}->{$conf_name}=$config->{$conf_name};
|
78
|
|
|
|
|
|
|
}
|
79
|
|
|
|
|
|
|
}
|
80
|
9
|
|
|
|
|
35
|
return $self;
|
81
|
|
|
|
|
|
|
} elsif($config) {
|
82
|
5
|
|
|
|
|
27
|
return $self->{config}->{$config};
|
83
|
|
|
|
|
|
|
} else {
|
84
|
8
|
|
|
|
|
39
|
return $self->{config};
|
85
|
|
|
|
|
|
|
}
|
86
|
|
|
|
|
|
|
}
|
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
sub set_voltage {
|
89
|
5
|
|
|
5
|
1
|
161
|
my $self=shift;
|
90
|
5
|
|
|
|
|
9
|
my $voltage=shift;
|
91
|
5
|
|
|
|
|
8
|
my $channel=shift;
|
92
|
|
|
|
|
|
|
|
93
|
5
|
50
|
|
|
|
16
|
$channel = 1 unless defined($channel);
|
94
|
|
|
|
|
|
|
|
95
|
5
|
50
|
|
|
|
14
|
die "Channel must not be negative! Did you swap voltage and channel number? Aborting..." if $channel < 0;
|
96
|
5
|
50
|
|
|
|
12
|
die "Channel must be an integer! Did you swap voltage and channel number? Aborting..." if int($channel) != $channel;
|
97
|
|
|
|
|
|
|
|
98
|
5
|
100
|
|
|
|
18
|
if ($self->{config}->{gate_protect}) {
|
99
|
3
|
|
|
|
|
8
|
$voltage=$self->sweep_to_voltage($voltage,$channel);
|
100
|
|
|
|
|
|
|
} else {
|
101
|
2
|
|
|
|
|
7
|
$self->_set_voltage($voltage,$channel);
|
102
|
|
|
|
|
|
|
}
|
103
|
|
|
|
|
|
|
|
104
|
5
|
|
|
|
|
12
|
my $result;
|
105
|
5
|
50
|
|
|
|
19
|
if ($self->{config}->{fast_set}) {
|
106
|
0
|
|
|
|
|
0
|
$result=$voltage;
|
107
|
|
|
|
|
|
|
} else {
|
108
|
5
|
|
|
|
|
34
|
$result=$self->get_voltage($channel);
|
109
|
|
|
|
|
|
|
};
|
110
|
|
|
|
|
|
|
|
111
|
5
|
|
|
|
|
11
|
my $tmp="last_voltage_$channel";
|
112
|
5
|
|
|
|
|
9
|
$self->{_gp}->{$tmp}=$result;
|
113
|
5
|
|
|
|
|
27
|
return $result;
|
114
|
|
|
|
|
|
|
}
|
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
sub set_voltage_auto {
|
117
|
0
|
|
|
0
|
0
|
0
|
my $self=shift;
|
118
|
0
|
|
|
|
|
0
|
my $voltage=shift;
|
119
|
0
|
|
|
|
|
0
|
my $channel=shift;
|
120
|
|
|
|
|
|
|
|
121
|
0
|
0
|
|
|
|
0
|
$channel = 1 unless defined($channel);
|
122
|
|
|
|
|
|
|
|
123
|
0
|
0
|
|
|
|
0
|
die "Channel must not be negative! Did you swap voltage and channel number? Aborting..." if $channel < 0;
|
124
|
0
|
0
|
|
|
|
0
|
die "Channel must be an integer! Did you swap voltage and channel number? Aborting..." if int($channel) != $channel;
|
125
|
|
|
|
|
|
|
|
126
|
0
|
0
|
|
|
|
0
|
if ($self->{config}->{gate_protect}) {
|
127
|
0
|
|
|
|
|
0
|
$voltage=$self->sweep_to_voltage_auto($voltage,$channel);
|
128
|
|
|
|
|
|
|
} else {
|
129
|
0
|
|
|
|
|
0
|
$self->_set_voltage_auto($voltage,$channel);
|
130
|
|
|
|
|
|
|
}
|
131
|
|
|
|
|
|
|
|
132
|
0
|
|
|
|
|
0
|
my $result;
|
133
|
0
|
0
|
|
|
|
0
|
if ($self->{config}->{fast_set}) {
|
134
|
0
|
|
|
|
|
0
|
$result=$voltage;
|
135
|
|
|
|
|
|
|
} else {
|
136
|
0
|
|
|
|
|
0
|
$result=$self->get_voltage($channel);
|
137
|
|
|
|
|
|
|
};
|
138
|
|
|
|
|
|
|
|
139
|
0
|
|
|
|
|
0
|
my $tmp="last_voltage_$channel";
|
140
|
0
|
|
|
|
|
0
|
$self->{_gp}->{$tmp}=$result;
|
141
|
0
|
|
|
|
|
0
|
return $result;
|
142
|
|
|
|
|
|
|
}
|
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
sub step_to_voltage {
|
146
|
1222
|
|
|
1222
|
1
|
1520
|
my $self=shift;
|
147
|
1222
|
|
|
|
|
1317
|
my $voltage=shift;
|
148
|
1222
|
|
|
|
|
1646
|
my $channel=shift;
|
149
|
1222
|
|
|
|
|
2688
|
my $voltpersec=abs($self->{config}->{gp_max_volt_per_second});
|
150
|
1222
|
|
|
|
|
1705
|
my $voltperstep=abs($self->{config}->{gp_max_volt_per_step});
|
151
|
1222
|
|
|
|
|
1621
|
my $steppersec=abs($self->{config}->{gp_max_step_per_second});
|
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
#read output voltage from instrument (only at the beginning)
|
154
|
1222
|
|
|
|
|
2141
|
my $last_voltage_channel="last_voltage_$channel";
|
155
|
|
|
|
|
|
|
|
156
|
1222
|
|
|
|
|
1806
|
my $last_v=$self->{_gp}->{$last_voltage_channel};
|
157
|
1222
|
100
|
|
|
|
2487
|
unless (defined $last_v) {
|
158
|
1
|
|
|
|
|
4
|
$last_v=$self->get_voltage($channel);
|
159
|
1
|
|
|
|
|
4
|
$self->{_gp}->{$last_voltage_channel}=$last_v;
|
160
|
|
|
|
|
|
|
}
|
161
|
|
|
|
|
|
|
|
162
|
1222
|
50
|
33
|
|
|
5753
|
if (defined($self->{config}->{gp_max_volt}) && ($voltage > $self->{config}->{gp_max_volt})) {
|
163
|
0
|
|
|
|
|
0
|
$voltage = $self->{config}->{gp_max_volt};
|
164
|
|
|
|
|
|
|
}
|
165
|
1222
|
50
|
33
|
|
|
5143
|
if (defined($self->{config}->{gp_min_volt}) && ($voltage < $self->{config}->{gp_min_volt})) {
|
166
|
0
|
|
|
|
|
0
|
$voltage = $self->{config}->{gp_min_volt};
|
167
|
|
|
|
|
|
|
}
|
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
#already there
|
170
|
1222
|
100
|
|
|
|
2972
|
return $voltage if (abs($voltage - $last_v) < $self->{config}->{gp_equal_level});
|
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
#are we already close enough? if so, screw the waiting time...
|
173
|
1215
|
100
|
66
|
|
|
4701
|
if ((defined $voltperstep) && (abs($voltage - $last_v) < $voltperstep)) {
|
174
|
1
|
|
|
|
|
10
|
$self->_set_voltage($voltage,$channel);
|
175
|
1
|
|
|
|
|
3
|
$self->{_gp}->{$last_voltage_channel}=$voltage;
|
176
|
1
|
|
|
|
|
3
|
return $voltage;
|
177
|
|
|
|
|
|
|
}
|
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
#do the magic step calculation
|
180
|
1214
|
100
|
|
|
|
2717
|
my $wait = ($voltpersec < $voltperstep * $steppersec) ?
|
181
|
|
|
|
|
|
|
$voltperstep/$voltpersec : # ignore $steppersec
|
182
|
|
|
|
|
|
|
1/$steppersec; # ignore $voltpersec
|
183
|
1214
|
|
|
|
|
1557
|
my $step=$voltperstep * ($voltage <=> $last_v);
|
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
#wait if necessary
|
186
|
1214
|
|
|
|
|
3311
|
my ($ns,$nmu)=gettimeofday();
|
187
|
1214
|
|
|
|
|
1923
|
my $now=$ns*1e6+$nmu;
|
188
|
|
|
|
|
|
|
|
189
|
1214
|
|
|
|
|
2064
|
my $last_settime_mus_channel="last_settime_mus_$channel";
|
190
|
|
|
|
|
|
|
|
191
|
1214
|
50
|
|
|
|
2929
|
unless (defined (my $last_t=$self->{_gp}->{last_settime_mus})) {
|
|
|
0
|
|
|
|
|
|
192
|
1214
|
|
|
|
|
2004
|
$self->{_gp}->{$last_settime_mus_channel}=$now;
|
193
|
|
|
|
|
|
|
} elsif ( $now-$last_t < 1e6*$wait ) {
|
194
|
0
|
|
|
|
|
0
|
usleep ( ( 1e6*$wait+$last_t-$now ) );
|
195
|
0
|
|
|
|
|
0
|
($ns,$nmu)=gettimeofday();
|
196
|
0
|
|
|
|
|
0
|
$now=$ns*1e6+$nmu;
|
197
|
|
|
|
|
|
|
}
|
198
|
1214
|
|
|
|
|
1756
|
$self->{_gp}->{$last_settime_mus_channel}=$now;
|
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
#do one step
|
201
|
1214
|
100
|
|
|
|
2861
|
if (abs($voltage-$last_v) > abs($step)) {
|
202
|
1213
|
|
|
|
|
1472
|
$voltage=$last_v+$step;
|
203
|
|
|
|
|
|
|
}
|
204
|
1214
|
|
|
|
|
5690
|
$voltage=0+sprintf("%.10f",$voltage);
|
205
|
|
|
|
|
|
|
|
206
|
1214
|
|
|
|
|
4367
|
$self->_set_voltage($voltage,$channel);
|
207
|
1214
|
|
|
|
|
2353
|
$self->{_gp}->{$last_voltage_channel}=$voltage;
|
208
|
1214
|
|
|
|
|
2678
|
return $voltage;
|
209
|
|
|
|
|
|
|
}
|
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
sub step_to_voltage_auto {
|
212
|
0
|
|
|
0
|
0
|
0
|
my $self=shift;
|
213
|
0
|
|
|
|
|
0
|
my $voltage=shift;
|
214
|
0
|
|
|
|
|
0
|
my $channel=shift;
|
215
|
0
|
|
|
|
|
0
|
my $voltpersec=abs($self->{config}->{gp_max_volt_per_second});
|
216
|
0
|
|
|
|
|
0
|
my $voltperstep=abs($self->{config}->{gp_max_volt_per_step});
|
217
|
0
|
|
|
|
|
0
|
my $steppersec=abs($self->{config}->{gp_max_step_per_second});
|
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
#read output voltage from instrument (only at the beginning)
|
220
|
0
|
|
|
|
|
0
|
my $last_voltage_channel="last_voltage_$channel";
|
221
|
|
|
|
|
|
|
|
222
|
0
|
|
|
|
|
0
|
my $last_v=$self->{_gp}->{$last_voltage_channel};
|
223
|
0
|
0
|
|
|
|
0
|
unless (defined $last_v) {
|
224
|
0
|
|
|
|
|
0
|
$last_v=$self->get_voltage($channel);
|
225
|
0
|
|
|
|
|
0
|
$self->{_gp}->{$last_voltage_channel}=$last_v;
|
226
|
|
|
|
|
|
|
}
|
227
|
|
|
|
|
|
|
|
228
|
0
|
0
|
0
|
|
|
0
|
if (defined($self->{config}->{gp_max_volt}) && ($voltage > $self->{config}->{gp_max_volt})) {
|
229
|
0
|
|
|
|
|
0
|
$voltage = $self->{config}->{gp_max_volt};
|
230
|
|
|
|
|
|
|
}
|
231
|
0
|
0
|
0
|
|
|
0
|
if (defined($self->{config}->{gp_min_volt}) && ($voltage < $self->{config}->{gp_min_volt})) {
|
232
|
0
|
|
|
|
|
0
|
$voltage = $self->{config}->{gp_min_volt};
|
233
|
|
|
|
|
|
|
}
|
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
#already there
|
236
|
0
|
0
|
|
|
|
0
|
return $voltage if (abs($voltage - $last_v) < $self->{config}->{gp_equal_level});
|
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
#do the magic step calculation
|
239
|
0
|
0
|
|
|
|
0
|
my $wait = ($voltpersec < $voltperstep * $steppersec) ?
|
240
|
|
|
|
|
|
|
$voltperstep/$voltpersec : # ignore $steppersec
|
241
|
|
|
|
|
|
|
1/$steppersec; # ignore $voltpersec
|
242
|
0
|
|
|
|
|
0
|
my $step=$voltperstep * ($voltage <=> $last_v);
|
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
#wait if necessary
|
245
|
0
|
|
|
|
|
0
|
my ($ns,$nmu)=gettimeofday();
|
246
|
0
|
|
|
|
|
0
|
my $now=$ns*1e6+$nmu;
|
247
|
|
|
|
|
|
|
|
248
|
0
|
|
|
|
|
0
|
my $last_settime_mus_channel="last_settime_mus_$channel";
|
249
|
|
|
|
|
|
|
|
250
|
0
|
0
|
|
|
|
0
|
unless (defined (my $last_t=$self->{_gp}->{last_settime_mus})) {
|
|
|
0
|
|
|
|
|
|
251
|
0
|
|
|
|
|
0
|
$self->{_gp}->{last_settime_mus_channel}=$now;
|
252
|
|
|
|
|
|
|
} elsif ( $now-$last_t < 1e6*$wait ) {
|
253
|
0
|
|
|
|
|
0
|
usleep ( ( 1e6*$wait+$last_t-$now ) );
|
254
|
0
|
|
|
|
|
0
|
($ns,$nmu)=gettimeofday();
|
255
|
0
|
|
|
|
|
0
|
$now=$ns*1e6+$nmu;
|
256
|
|
|
|
|
|
|
}
|
257
|
0
|
|
|
|
|
0
|
$self->{_gp}->{$last_settime_mus_channel}=$now;
|
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
#do one step
|
260
|
0
|
0
|
|
|
|
0
|
if (abs($voltage-$last_v) > abs($step)) {
|
261
|
0
|
|
|
|
|
0
|
$voltage=$last_v+$step;
|
262
|
|
|
|
|
|
|
}
|
263
|
0
|
|
|
|
|
0
|
$voltage=0+sprintf("%.10f",$voltage);
|
264
|
|
|
|
|
|
|
|
265
|
0
|
|
|
|
|
0
|
$self->_set_voltage_auto($voltage,$channel);
|
266
|
0
|
|
|
|
|
0
|
$self->{_gp}->{$last_voltage_channel}=$voltage;
|
267
|
0
|
|
|
|
|
0
|
return $voltage;
|
268
|
|
|
|
|
|
|
}
|
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
sub sweep_to_voltage {
|
272
|
7
|
|
|
7
|
1
|
13
|
my $self=shift;
|
273
|
7
|
|
|
|
|
20
|
my $voltage=shift;
|
274
|
7
|
|
|
|
|
11
|
my $channel=shift;
|
275
|
|
|
|
|
|
|
|
276
|
7
|
|
|
|
|
7
|
my $last;
|
277
|
7
|
|
|
|
|
11
|
my $cont=1;
|
278
|
7
|
|
|
|
|
16
|
while($cont) {
|
279
|
1212
|
|
|
|
|
1310
|
$cont=0;
|
280
|
1212
|
|
|
|
|
2410
|
my $this=$self->step_to_voltage($voltage,$channel);
|
281
|
1212
|
100
|
100
|
|
|
6383
|
unless ((defined $last) && (abs($last-$this) < $self->{config}->{gp_equal_level})) {
|
282
|
1205
|
|
|
|
|
1459
|
$last=$this;
|
283
|
1205
|
|
|
|
|
2538
|
$cont++;
|
284
|
|
|
|
|
|
|
}
|
285
|
|
|
|
|
|
|
}; #ugly
|
286
|
7
|
|
|
|
|
37
|
return $voltage;
|
287
|
|
|
|
|
|
|
}
|
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
sub _set_voltage {
|
290
|
0
|
|
|
0
|
|
0
|
my $self=shift;
|
291
|
0
|
|
|
|
|
0
|
my $voltage=shift;
|
292
|
|
|
|
|
|
|
|
293
|
0
|
0
|
|
|
|
0
|
if ($self->{subsource}) {
|
294
|
0
|
|
|
|
|
0
|
return $self->{multisource}->_set_voltage($voltage, $self->{channel});
|
295
|
|
|
|
|
|
|
} else {
|
296
|
0
|
|
|
|
|
0
|
warn '_set_voltage not implemented for this instrument';
|
297
|
|
|
|
|
|
|
};
|
298
|
|
|
|
|
|
|
}
|
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
sub _set_voltage_auto {
|
301
|
0
|
|
|
0
|
|
0
|
my $self=shift;
|
302
|
0
|
|
|
|
|
0
|
my $voltage=shift;
|
303
|
|
|
|
|
|
|
|
304
|
0
|
0
|
|
|
|
0
|
if ($self->{subsource}) {
|
305
|
0
|
|
|
|
|
0
|
return $self->{multisource}->_set_voltage_auto($voltage, $self->{channel});
|
306
|
|
|
|
|
|
|
} else {
|
307
|
0
|
|
|
|
|
0
|
warn '_set_voltage_auto not implemented for this instrument';
|
308
|
|
|
|
|
|
|
};
|
309
|
|
|
|
|
|
|
}
|
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
sub get_voltage {
|
312
|
8
|
|
|
8
|
1
|
14
|
my $self=shift;
|
313
|
8
|
|
|
|
|
12
|
my $channel=shift;
|
314
|
8
|
100
|
|
|
|
21
|
$channel = 1 unless defined($channel);
|
315
|
8
|
|
|
|
|
29
|
my $voltage=$self->_get_voltage($channel);
|
316
|
8
|
|
|
|
|
16
|
my $tmp="last_voltage_$channel";
|
317
|
8
|
|
|
|
|
17
|
$self->{_gp}->{$tmp}=$voltage;
|
318
|
8
|
|
|
|
|
21
|
return $voltage;
|
319
|
|
|
|
|
|
|
}
|
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
sub _get_voltage {
|
322
|
0
|
|
|
0
|
|
|
my $self=shift;
|
323
|
|
|
|
|
|
|
|
324
|
0
|
0
|
|
|
|
|
if ($self->{subsource}) {
|
325
|
0
|
|
|
|
|
|
return $self->{multisource}->_get_voltage($self->{channel});
|
326
|
|
|
|
|
|
|
} else {
|
327
|
0
|
|
|
|
|
|
warn '_get_voltage not implemented for this instrument';
|
328
|
|
|
|
|
|
|
};
|
329
|
|
|
|
|
|
|
}
|
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
sub get_range() {
|
332
|
0
|
|
|
0
|
0
|
|
my $self=shift;
|
333
|
0
|
0
|
|
|
|
|
if ($self->{subsource}) {
|
334
|
0
|
|
|
|
|
|
return $self->{multisource}->get_range($self->{channel});
|
335
|
|
|
|
|
|
|
} else {
|
336
|
0
|
|
|
|
|
|
warn 'get_range not implemented for this instrument';
|
337
|
|
|
|
|
|
|
};
|
338
|
|
|
|
|
|
|
}
|
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
sub set_range() {
|
341
|
0
|
|
|
0
|
0
|
|
my $self=shift;
|
342
|
0
|
|
|
|
|
|
my $range=shift;
|
343
|
0
|
0
|
|
|
|
|
if ($self->{subsource}) {
|
344
|
0
|
|
|
|
|
|
return $self->{multisource}->set_range($range, $self->{channel});
|
345
|
|
|
|
|
|
|
} else {
|
346
|
0
|
|
|
|
|
|
warn 'set_range not implemented for this instrument';
|
347
|
|
|
|
|
|
|
};
|
348
|
|
|
|
|
|
|
}
|
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
1;
|
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
=head1 NAME
|
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
Lab::Instrument::Source - Base class for voltage source instruments
|
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
This class implements a general voltage source, if necessary with several channels.
|
361
|
|
|
|
|
|
|
It is meant to be inherited by instrument classes (virtual instruments) that implement
|
362
|
|
|
|
|
|
|
real voltage sources (e.g. the L class).
|
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
The class provides a unified user interface for those virtual voltage sources
|
365
|
|
|
|
|
|
|
to support the exchangeability of instruments.
|
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
Additionally, this class provides a safety mechanism called C
|
368
|
|
|
|
|
|
|
to protect delicate samples. It includes automatic limitations of sweep rates,
|
369
|
|
|
|
|
|
|
voltage step sizes, minimal and maximal voltages.
|
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
The only user application of this class is to define a voltage source object
|
372
|
|
|
|
|
|
|
which represents a single channel of a multi-channel voltage source.
|
373
|
|
|
|
|
|
|
Otherwise, you will always have to instantiate classes derived from Lab::Instrument::Source.
|
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
=head1 CONSTRUCTOR
|
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
$self=new Lab::Instrument::Source($multisource, $channel);
|
378
|
|
|
|
|
|
|
$self=new Lab::Instrument::Source($multisource, $channel, \%config);
|
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
This constructor can be used to create a source object which represents
|
381
|
|
|
|
|
|
|
channel C<$channel> of the multi-channel voltage source C<$multisource>.
|
382
|
|
|
|
|
|
|
The default configuration of this source is the configuration of C<$multisource>;
|
383
|
|
|
|
|
|
|
it can be partially or entirely overridden with an additional C<\%config> hash.
|
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
$self=new Lab::Instrument::Source(\%default_config,\%config);
|
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
This constructor will only be used by instrument drivers that inherit this class,
|
389
|
|
|
|
|
|
|
not by the user.
|
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
The instrument driver (e.g. L)
|
392
|
|
|
|
|
|
|
has a constructor like this:
|
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
$knick=new Lab::Instrument::KnickS252({
|
395
|
|
|
|
|
|
|
GPIB_board => $board,
|
396
|
|
|
|
|
|
|
GPIB_address => $address,
|
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
gate_protect => $gp,
|
399
|
|
|
|
|
|
|
[...]
|
400
|
|
|
|
|
|
|
});
|
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
=head1 METHODS
|
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
=head2 configure
|
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
$self->configure(\%config);
|
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
Supported configure options:
|
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
=over 2
|
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
=item fast_set
|
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
This parameter controls the return value of the set_voltage function and can be set to 0 (off,
|
415
|
|
|
|
|
|
|
default) or 1 (on). For fast_set off, set_voltage first requests the hardware to set the voltage,
|
416
|
|
|
|
|
|
|
and then reads out the actually set voltage via get_voltage. The resulting number is returned.
|
417
|
|
|
|
|
|
|
For fast_set on, set_voltage requests the hardware to set the voltage and returns without double-check
|
418
|
|
|
|
|
|
|
the requested value. This, albeit less secure, may speed up measurements a lot.
|
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
=item gate_protect
|
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
Whether to use the automatic sweep speed limitation. Can be set to 0 (off) or 1 (on).
|
423
|
|
|
|
|
|
|
If it is turned on, the output voltage will not be changed faster than allowed
|
424
|
|
|
|
|
|
|
by the C, C and C
|
425
|
|
|
|
|
|
|
values. These three parameters overdefine the allowed speed. Only two
|
426
|
|
|
|
|
|
|
parameters are necessary. If all three are set, the smallest allowed sweep rate
|
427
|
|
|
|
|
|
|
is chosen.
|
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
Additionally the maximal and minimal output voltages are limited.
|
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
This mechanism is useful to protect sensible samples that are destroyed by
|
432
|
|
|
|
|
|
|
abrupt voltage changes. One example is gate electrodes on semiconductor electronics
|
433
|
|
|
|
|
|
|
samples, hence the name.
|
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
=item gp_max_volt_per_second
|
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
How much the output voltage is allowed to change per second.
|
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
=item gp_max_volt_per_step
|
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
How much the output voltage is allowed to change per step.
|
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
=item gp_max_step_per_second
|
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
How many steps are allowed per second.
|
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
=item gp_min_volt
|
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
The smallest allowed output voltage.
|
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
=item gp_max_volt
|
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
The largest allowed output voltage.
|
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
=item qp_equal_level
|
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
Voltages with a difference less than this value are considered equal.
|
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
=back
|
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
=head2 set_voltage
|
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
$new_volt=$self->set_voltage($voltage);
|
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
Sets the output to C<$voltage> (in Volts). If the configure option C is set
|
466
|
|
|
|
|
|
|
to a true value, the safety mechanism takes into account the C,
|
467
|
|
|
|
|
|
|
C etc. settings, by employing the C method.
|
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
Returns for C off the actually set output voltage. This can be different
|
470
|
|
|
|
|
|
|
from C<$voltage>, due to the C, C settings. For C on,
|
471
|
|
|
|
|
|
|
C returns always C<$voltage>.
|
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
For a multi-channel device, add the channel number as a parameter:
|
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
$new_volt=$self->set_voltage($voltage,$channel);
|
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
=head2 step_to_voltage
|
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
$new_volt=$self->step_to_voltage($voltage);
|
481
|
|
|
|
|
|
|
$new_volt=$self->step_to_voltage($voltage,$channel);
|
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
Makes one safe step in direction to C<$voltage>. The output voltage is not changed by more
|
484
|
|
|
|
|
|
|
than C. Before the voltage is changed, the methods waits if not
|
485
|
|
|
|
|
|
|
enough times has passed since the last voltage change. For step voltage and waiting time
|
486
|
|
|
|
|
|
|
calculation, the larger of C or C is ignored
|
487
|
|
|
|
|
|
|
(see code).
|
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
Returns the actually set output voltage. This can be different from C<$voltage>, due
|
490
|
|
|
|
|
|
|
to the C, C settings.
|
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
=head2 sweep_to_voltage
|
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
$new_volt=$self->sweep_to_voltage($voltage);
|
495
|
|
|
|
|
|
|
$new_volt=$self->sweep_to_voltage($voltage,$channel);
|
496
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
This method sweeps the output voltage to the desired value and only returns then.
|
498
|
|
|
|
|
|
|
Uses the L method internally, so all discussions of config options
|
499
|
|
|
|
|
|
|
from there apply too.
|
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
Returns the actually set output voltage. This can be different from C<$voltage>, due
|
502
|
|
|
|
|
|
|
to the C, C settings.
|
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
=head2 get_voltage
|
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
$new_volt=$self->get_voltage();
|
507
|
|
|
|
|
|
|
$new_volt=$self->get_voltage($channel);
|
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
Returns the voltage currently set.
|
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
=head1 CAVEATS/BUGS
|
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
Probably many.
|
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
=head1 SEE ALSO
|
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
=over 4
|
518
|
|
|
|
|
|
|
|
519
|
|
|
|
|
|
|
=item L
|
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
Used internally for the sweep timing.
|
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
=item L
|
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
This class inherits the gate protection mechanism.
|
526
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
=item L
|
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
This class inherits the gate protection mechanism.
|
530
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
=back
|
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
=head1 AUTHOR/COPYRIGHT
|
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
This is $Id: Source.pm 650 2010-04-22 19:09:27Z schroeer $
|
536
|
|
|
|
|
|
|
|
537
|
|
|
|
|
|
|
Copyright 2004-2008 Daniel Schröer ()
|
538
|
|
|
|
|
|
|
2009-2010 Daniel Schröer, Andreas K. Hüttel (L) and Daniela Taubert
|
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
|
541
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
=cut
|