File Coverage

blib/lib/Lab/Instrument/Yokogawa7651.pm
Criterion Covered Total %
statement 70 334 20.9
branch 8 146 5.4
condition 4 72 5.5
subroutine 14 44 31.8
pod 14 34 41.1
total 110 630 17.4


line stmt bran cond sub pod time code
1             package Lab::Instrument::Yokogawa7651;
2             #ABSTRACT: Yokogawa 7651 DC source
3             $Lab::Instrument::Yokogawa7651::VERSION = '3.881';
4 2     2   2553 use v5.20;
  2         10  
5              
6 2     2   12 use warnings;
  2         5  
  2         55  
7 2     2   10 use strict;
  2         6  
  2         44  
8 2     2   10 use Time::HiRes qw/usleep/;
  2         11  
  2         12  
9              
10              
11              
12 2     2   901 use Lab::Instrument;
  2         7  
  2         70  
13 2     2   824 use Lab::Instrument::Source;
  2         6  
  2         90  
14 2     2   17 use Data::Dumper;
  2         5  
  2         11446  
15              
16             our @ISA = ('Lab::Instrument::Source');
17              
18             our %fields = (
19             supported_connections => [ 'GPIB', 'VISA' ],
20              
21             # default settings for the supported connections
22             connection_settings => {
23             gpib_board => 0,
24             gpib_address => undef,
25             timeout => 1
26             },
27              
28             device_settings => {
29             gate_protect => 1,
30              
31             #gp_equal_level => 1e-5,
32             gp_max_units_per_second => 0.005,
33             gp_max_units_per_step => 0.001,
34             gp_max_step_per_second => 5,
35              
36             max_sweep_time => 3600,
37             min_sweep_time => 0.1,
38              
39             stepsize => 0.01,
40              
41             },
42              
43             device_cache => {
44             function => undef,
45             range => undef,
46             level => undef,
47             output => undef,
48             },
49              
50             device_cache_order => [ 'function', 'range' ],
51             request => 0
52             );
53              
54             sub new {
55 1     1 1 3 my $proto = shift;
56 1   33     7 my $class = ref($proto) || $proto;
57 1         5 my $self = $class->SUPER::new(@_);
58 1         2 $self->${ \( __PACKAGE__ . '::_construct' ) }(__PACKAGE__);
  1         8  
59              
60 1         8 return $self;
61             }
62              
63             sub _device_init {
64 1     1   3 my $self = shift;
65 1 50       4 if ( $self->get_status('setting') ) {
66 0         0 $self->end_program();
67             }
68             }
69              
70             sub set_voltage {
71 0     0 1 0 my $self = shift;
72 0         0 my ( $voltage, $tail ) = $self->_check_args( \@_, ['voltage'] );
73              
74 0         0 my $function = $self->get_function( { 'read_mode' => 'cache' }, $tail );
75              
76 0 0       0 if ( $function !~ /voltage/i ) {
77 0         0 Lab::Exception::CorruptParameter->throw( error =>
78             "Source is in mode $function. Can't set voltage level." );
79             }
80              
81 0         0 return $self->set_level( $voltage, $tail );
82             }
83              
84             sub set_current {
85 0     0 1 0 my $self = shift;
86 0         0 my ( $current, $tail ) = $self->_check_args( \@_, ['current'] );
87              
88 0         0 my $function = $self->get_function( { 'read_mode' => 'cache' }, $tail );
89              
90 0 0       0 if ( $function !~ /current/i ) {
91 0         0 Lab::Exception::CorruptParameter->throw( error =>
92             "Source is in mode $function. Can't set current level." );
93             }
94              
95 0         0 $self->set_level( $current, $tail );
96             }
97              
98             sub set_setpoint {
99 0     0 0 0 my $self = shift;
100 0         0 my ( $value, $tail ) = $self->_check_args( \@_, ['value'] );
101 0         0 my $cmd = sprintf( "S%+.4e", $value );
102 0         0 $self->write( $cmd, { error_check => 1 }, $tail );
103             }
104              
105             sub _set_level {
106 12     12   26 my $self = shift;
107 12         46 my ( $value, $tail ) = $self->_check_args( \@_, ['value'] );
108              
109 12         47 my $range = $self->get_range( { read_mode => 'cache' }, $tail );
110              
111 12 50 33     184 if ( $value > $range || $value < -$range ) {
112 0         0 Lab::Exception::CorruptParameter->throw(
113             "The desired source level $value is not within the source range $range \n"
114             );
115             }
116              
117 12         133 my $cmd = sprintf( "S%ge", $value );
118              
119 12         68 $self->write( $cmd, { error_check => 1 }, $tail );
120              
121 12         54 return $self->{'device_cache'}->{'level'} = $value;
122              
123             }
124              
125             sub start_program {
126 0     0 0 0 my $self = shift;
127 0         0 my ($tail) = $self->_check_args( \@_ );
128 0         0 my $cmd = sprintf("PRS");
129 0         0 $self->write( $cmd, $tail );
130             }
131              
132             sub end_program {
133 0     0 0 0 my $self = shift;
134 0         0 my ($tail) = $self->_check_args( \@_ );
135 0         0 my $cmd = sprintf("PRE");
136 0         0 $self->write( $cmd, $tail );
137             }
138              
139             sub execute_program {
140              
141             # 0 HALT
142             # 1 STEP
143             # 2 RUN
144             #3 Continue
145 1     1 0 2 my $self = shift;
146 1         4 my ( $value, $tail ) = $self->_check_args( \@_, ['value'] );
147 1         7 my $cmd = sprintf( "RU%d", $value );
148 1         4 $self->write( $cmd, $tail );
149             }
150              
151             sub trg {
152 0     0 0 0 my $self = shift;
153 0         0 my ($tail) = $self->_check_args( \@_ );
154 0         0 $self->execute_program( 2, $tail );
155             }
156              
157             sub config_sweep {
158 0     0 0 0 my $self = shift;
159 0         0 my ( $start, $target, $duration, $sections, $tail )
160             = $self->check_sweep_config(@_);
161              
162 0         0 $self->set_output( 1, $tail );
163 0         0 $self->set_run_mode( 'single', $tail );
164              
165 0         0 $self->start_program($tail);
166              
167 0         0 for ( my $i = 1; $i <= $sections; $i++ ) {
168 0         0 $self->set_setpoint( $start + ( $target - $start ) / $sections * $i );
169             }
170 0         0 $self->end_program($tail);
171              
172             # programming sweep duration:
173              
174 0         0 $self->set_time( $duration, $duration, $tail );
175              
176             # calculate trace
177              
178             }
179              
180             sub configure_sweep {
181 0     0 0 0 my $self = shift;
182 0         0 my ( $target, $time, $rate, $tail )
183             = $self->_check_args( \@_, [ 'points', 'time', 'rate' ] );
184              
185 0         0 $self->config_sweep( $target, $rate, $time, $tail );
186             }
187              
188             sub wait_done {
189 0     0 0 0 my $self = shift;
190 0         0 my ($tail) = $self->_check_args( \@_ );
191              
192 0         0 $self->wait($tail);
193              
194             }
195              
196             sub abort {
197 1     1 0 3 my $self = shift;
198 1         6 my ($tail) = $self->_check_args( \@_ );
199 1         15 $self->execute_program( 0, $tail );
200             }
201              
202             sub active {
203 0     0 0 0 my $self = shift;
204 0         0 my ($tail) = $self->_check_args( \@_ );
205              
206 0 0       0 if ( $self->get_status( "execution", $tail ) == 0 ) {
207 0         0 return 0;
208             }
209             else {
210 0         0 return 1;
211             }
212              
213             }
214              
215             sub wait {
216 0     0 0 0 my $self = shift;
217 0         0 my ($tail) = $self->_check_args( \@_ );
218 0         0 my $flag = 1;
219 0         0 local $| = 1;
220              
221 0         0 while (1) {
222              
223             #my $status = $self->get_status();
224 0         0 my $execution = $self->get_status('execution');
225 0         0 my $current_level = $self->get_level($tail);
226 0 0 0     0 if ( $flag <= 1.1 and $flag >= 0.9 ) {
    0          
227 0         0 print "\t\t\t\t\t\t\t\t\t\r";
228 0         0 print $self->get_id() . " is sweeping ($current_level )\r";
229              
230             #usleep(5e5);
231             }
232             elsif ( $flag <= 0 ) {
233 0         0 print "\t\t\t\t\t\t\t\t\t\r";
234 0         0 print $self->get_id() . " is ($current_level ) \r";
235 0         0 $flag = 2;
236             }
237 0         0 $flag -= 0.5;
238 0 0       0 if ( $execution == 0 ) {
239 0         0 print "\t\t\t\t\t\t\t\t\t\r";
240 0         0 $| = 0;
241 0         0 last;
242             }
243             }
244             }
245              
246             sub _sweep_to_level {
247 0     0   0 my $self = shift;
248 0         0 my ( $target, $time, $tail )
249             = $self->_check_args( \@_, [ 'points', 'time' ] );
250              
251             # print "Yokogawa7651.pm: configuring sweep $target $time\n";
252 0         0 $self->config_sweep(
253             {
254             points => $target,
255             time => $time
256             },
257             $tail
258             );
259              
260             # print "Yokogawa7651.pm: executing program\n";
261 0         0 $self->execute_program( 2, $tail );
262              
263             # print "Yokogawa7651.pm: waiting until done\n";
264 0         0 $self->wait($tail);
265              
266             # print "Yokogawa7651.pm: reading out source level\n";
267 0         0 my $current = $self->get_level($tail);
268              
269             # print "Yokogawa7651.pm: source level is $current\n";
270              
271 0         0 my $eql = $self->get_gp_equal_level();
272              
273             # my $difference=$current-$target;
274             # print "Yokogawa7651.pm: c $current t $target d $difference e $eql\n";
275              
276 0 0       0 if ( abs( $current - $target ) > $eql ) {
277 0         0 print "Yokogawa7651.pm: error current neq target\n";
278 0         0 Lab::Exception::CorruptParameter->throw(
279             "Sweep failed: $target not equal to $current. \n");
280             }
281              
282             # print "Yokogawa7651.pm: reaching return from _sweep_to_level\n";
283 0         0 return $self->device_cache()->{'level'} = $target;
284             }
285              
286             sub get_function {
287 0     0 0 0 my $self = shift;
288              
289 0         0 my ($tail) = $self->_check_args( \@_ );
290              
291 0         0 my $cmd = "OD";
292 0         0 my $result = $self->query( $cmd, $tail );
293 0 0       0 if ( $result =~ /^...([VA])/ ) {
294 0 0       0 return ( $1 eq "V" ) ? "voltage" : "current";
295             }
296             else {
297 0         0 Lab::Exception::CorruptParameter->throw(
298             "Output of command OD is not valid. \n");
299             }
300              
301             }
302              
303             sub get_level {
304 0     0 1 0 my $self = shift;
305 0         0 my $cmd = "OD";
306 0         0 my $result;
307              
308 0         0 my ($read_mode) = $self->_check_args( \@_, ['read_mode'] );
309              
310 0 0 0     0 if ( not defined $read_mode
311             or not $read_mode =~ /device|cache|request|fetch/ ) {
312 0         0 $read_mode = $self->device_settings()->{read_default};
313             }
314              
315 0 0 0     0 if ( $read_mode eq 'cache'
    0 0        
    0 0        
    0 0        
316             and defined $self->{'device_cache'}->{'level'} ) {
317 0         0 return $self->{'device_cache'}->{'level'};
318             }
319             elsif ( $read_mode eq 'request' and $self->{request} == 0 ) {
320 0         0 $self->{request} = 1;
321 0         0 $self->write($cmd);
322 0         0 return;
323             }
324             elsif ( $read_mode eq 'request' and $self->{request} == 1 ) {
325 0         0 $result = $self->read();
326 0         0 $self->write($cmd);
327 0         0 return;
328             }
329             elsif ( $read_mode eq 'fetch' and $self->{request} == 1 ) {
330 0         0 $self->{request} = 0;
331 0         0 $result = $self->read();
332             }
333             else {
334 0 0       0 if ( $self->{request} == 1 ) {
335 0         0 $result = $self->read();
336 0         0 $self->{request} = 0;
337 0         0 $result = $self->query($cmd);
338             }
339             else {
340 0         0 $result = $self->query($cmd);
341             }
342             }
343              
344 0         0 $result =~ /....([\+\-\d\.E]*)/;
345 0         0 return $self->{'device_cache'}->{'level'} = $1;
346             }
347              
348             sub get_voltage {
349 0     0 1 0 my $self = shift;
350              
351 0         0 my $function = $self->get_function();
352              
353 0 0       0 if ( $function !~ /voltage/i ) {
354 0         0 Lab::Exception::CorruptParameter->throw( error =>
355             "Source is in mode $function. Can't get voltage level." );
356             }
357              
358 0         0 return $self->get_level(@_);
359             }
360              
361             sub get_current {
362 0     0 1 0 my $self = shift;
363              
364 0         0 my $function = $self->get_function();
365              
366 0 0       0 if ( $function !~ /current/i ) {
367 0         0 Lab::Exception::CorruptParameter->throw( error =>
368             "Source is in mode $function. Can't get current level." );
369             }
370              
371 0         0 return $self->get_level(@_);
372             }
373              
374             sub set_function {
375 0     0 0 0 my $self = shift;
376 0         0 my ($function) = $self->_check_args( \@_, ['function'] );
377              
378 0 0       0 if ( $function !~ /(current|voltage)/i ) {
379 0         0 Lab::Exception::CorruptParameter->throw(
380             "$function is not a valid source mode. Choose 1 or 5 for current and voltage mode respectively. \n"
381             );
382             }
383              
384 0 0       0 if ( $self->get_function() eq $function ) {
385 0         0 return $function;
386             }
387              
388 0 0 0     0 if ( $self->get_output() and $self->device_settings()->{gate_protect} ) {
389 0         0 Lab::Exception::Warning->throw(
390             'Cannot switch function in gate-protection mode while output is activated.'
391             );
392             }
393              
394 0 0       0 my $my_function = ( $function =~ /current/i ) ? 5 : 1;
395              
396 0         0 my $cmd = sprintf( "F%de", $my_function );
397              
398 0         0 $self->write($cmd);
399 0         0 return $self->{'device_cache'}->{'function'} = $function;
400              
401             }
402              
403             sub set_range {
404 0     0 1 0 my $self = shift;
405 0         0 my ($range) = $self->_check_args( \@_, ['range'] );
406              
407 0         0 my $function = $self->get_function();
408              
409 0 0       0 if ( $function =~ /voltage/i ) {
    0          
410 0 0       0 if ( $range <= 10e-3 ) { $range = 2; }
  0 0       0  
    0          
    0          
    0          
411 0         0 elsif ( $range <= 100e-3 ) { $range = 3; }
412 0         0 elsif ( $range <= 1 ) { $range = 4; }
413 0         0 elsif ( $range <= 10 ) { $range = 5; }
414 0         0 elsif ( $range <= 30 ) { $range = 6; }
415             else {
416 0         0 Lab::Exception::CorruptParameter->throw( error =>
417             "unexpected value for RANGE in sub set_range. Expected values are between 10mV ... 30V and 1mA ... 100mA for voltage and current mode."
418             );
419             }
420             }
421             elsif ( $function =~ /current/i ) {
422 0 0       0 if ( $range <= 1e-3 ) { $range = 4; }
  0 0       0  
    0          
423 0         0 elsif ( $range <= 10e-3 ) { $range = 5; }
424 0         0 elsif ( $range <= 100e-3 ) { $range = 6; }
425             else {
426 0         0 Lab::Exception::CorruptParameter->throw( error =>
427             "unexpected value for RANGE in sub set_range. Expected values are between 10mV ... 30V and 1mA ... 100mA for voltage and current mode."
428             );
429             }
430             }
431             else {
432 0         0 Lab::Exception::CorruptParameter->throw(
433             "$range is not a valid source range. Read the documentation for a list of allowed ranges in mode $function.\n"
434             );
435             }
436              
437             #fixed voltage mode
438             # 2 10mV
439             # 3 100mV
440             # 4 1V
441             # 5 10V
442             # 6 30V
443             #fixed current mode
444             # 4 1mA
445             # 5 10mA
446             # 6 100mA
447              
448 0         0 my $cmd = sprintf( "R%ue", $range );
449              
450 0         0 $self->write($cmd);
451 0         0 return $self->{'device_cache'}->{'range'} = $self->get_range();
452             }
453              
454             sub get_info {
455 19     19 1 27 my $self = shift;
456              
457 19         57 my ($read_mode) = $self->_check_args( \@_, ['read_mode'] );
458              
459 19 50 33     58 if ( not defined $read_mode or not $read_mode =~ /device|cache/ ) {
460 19         44 $read_mode = $self->device_settings()->{read_default};
461             }
462              
463 19 50 33     51 if ( $read_mode eq 'cache' and defined $self->{'device_cache'}->{'info'} )
464             {
465 0         0 return $self->{'device_cache'}->{'info'};
466             }
467              
468 19         73 $self->write("OS");
469 19         31 my @info;
470 19         126 for ( my $i = 0; $i <= 10; $i++ ) {
471 95         429 my $line = $self->connection()->Read( read_length => 300 );
472 95 100       287 if ( $line =~ /END/ ) {last}
  19         41  
473 76         131 chomp $line;
474 76         126 $line =~ s/\r//;
475 76         281 push( @info, sprintf($line) );
476             }
477              
478 19         36 return @{ $self->{'device_cache'}->{'info'} } = @info;
  19         94  
479             }
480              
481             sub get_range {
482 0     0 1 0 my $self = shift;
483              
484 0         0 my ($read_mode) = $self->_check_args( \@_, ['read_mode'] );
485              
486 0 0 0     0 if ( not defined $read_mode or not $read_mode =~ /device|cache/ ) {
487 0         0 $read_mode = $self->device_settings()->{read_default};
488             }
489              
490 0 0 0     0 if ( $read_mode eq 'cache'
491             and defined $self->{'device_cache'}->{'range'} ) {
492 0         0 return $self->{'device_cache'}->{'range'};
493             }
494              
495 0         0 my $range = ( $self->get_info() )[1];
496 0         0 my $function = $self->get_function();
497              
498 0 0       0 if ( $range =~ /F(\d)R(\d)/ ) {
499 0         0 $range = $2;
500              
501             # printf "rangenr=$range_nr\n";
502             }
503              
504 0 0       0 if ( $function =~ /voltage/i ) {
    0          
505 0 0       0 $range =~ /2/ ? $range
    0          
    0          
    0          
    0          
506             = 0.012
507             : $range =~ /3/ ? $range
508             = 0.12
509             : $range =~ /4/ ? $range
510             = 1.2
511             : $range =~ /5/ ? $range
512             = 12
513             : $range =~ /6/ ? $range
514             = 32
515             : Lab::Exception::CorruptParameter->throw(
516             "$range is not a valid voltage range. Read the documentation for a list of allowed ranges in mode $function.\n"
517             );
518             }
519             elsif ( $function =~ /current/i ) {
520 0 0       0 $range =~ /4/ ? $range
    0          
    0          
521             = 0.0012
522             : $range =~ /5/ ? $range
523             = 0.012
524             : $range =~ /6/ ? $range
525             = 0.12
526             : Lab::Exception::CorruptParameter->throw(
527             "$range is not a valid current range. Read the documentation for a list of allowed ranges in mode $function.\n"
528             );
529             }
530             else {
531 0         0 Lab::Exception::CorruptParameter->throw(
532             "$range is not a valid source range. Read the documentation for a list of allowed ranges in mode $function.\n"
533             );
534             }
535              
536 0         0 return $self->{'device_cache'}->{'range'} = $range;
537             }
538              
539             sub set_run_mode {
540 0     0 0 0 my $self = shift;
541 0         0 my ($value) = $self->_check_args( \@_, ['value'] );
542              
543             # $value == 0 --> REPEAT-Mode
544             # $value == 1 --> SINGLE-Mode
545              
546 0 0 0     0 if ( $value eq 'repeat' or $value eq 'REPEAT' ) { $value = 0; }
  0         0  
547 0 0 0     0 if ( $value eq 'single' or $value eq 'SINGLE' ) { $value = 1; }
  0         0  
548              
549 0 0 0     0 if ( $value != 0 and $value != 1 ) {
550 0         0 Lab::Exception::CorruptParameter->throw(
551             error => "Run Mode $value not defined\n" );
552             }
553 0         0 my $cmd = sprintf( "M%u", $value );
554 0         0 $self->write($cmd);
555             }
556              
557             sub set_time { # internal use only
558 0     0 0 0 my $self = shift;
559 0         0 my ( $sweep_time, $interval_time, $tail )
560             = $self->_check_args( \@_, [ 'sweep_time', 'interval_time' ] );
561              
562 0 0       0 if ( $sweep_time < $self->device_settings()->{min_sweep_time} ) {
    0          
563 0         0 print Lab::Exception::CorruptParameter->new( error =>
564             " Sweep Time: $sweep_time smaller than $self->device_settings()->{min_sweep_time} sec!\n Sweep time set to $self->device_settings()->{min_sweep_time} sec"
565             );
566 0         0 $sweep_time = $self->device_settings()->{min_sweep_time};
567             }
568             elsif ( $sweep_time > $self->device_settings()->{max_sweep_time} ) {
569 0         0 print Lab::Exception::CorruptParameter->new( error =>
570             " Sweep Time: $sweep_time> $self->device_settings()->{max_sweep_time} sec!\n Sweep time set to $self->device_settings()->{max_sweep_time} sec"
571             );
572 0         0 $sweep_time = $self->device_settings()->{max_sweep_time};
573             }
574 0 0       0 if ( $interval_time < $self->device_settings()->{min_sweep_time} ) {
    0          
575 0         0 print Lab::Exception::CorruptParameter->new( error =>
576             " Interval Time: $interval_time smaller than $self->device_settings()->{min_sweep_time} sec!\n Interval time set to $self->device_settings()->{min_sweep_time} sec"
577             );
578 0         0 $interval_time = $self->device_settings()->{min_sweep_time};
579             }
580             elsif ( $interval_time > $self->device_settings()->{max_sweep_time} ) {
581 0         0 print Lab::Exception::CorruptParameter->new( error =>
582             " Interval Time: $interval_time> $self->device_settings()->{max_sweep_time} sec!\n Interval time set to $self->device_settings()->{max_sweep_time} sec"
583             );
584 0         0 $interval_time = $self->device_settings()->{max_sweep_time};
585             }
586 0         0 my $cmd = sprintf( "PI%.1f", $interval_time );
587 0         0 $self->write( $cmd, $tail );
588 0         0 $cmd = sprintf( "SW%.1f", $sweep_time );
589 0         0 $self->write( $cmd, $tail );
590             }
591              
592             sub set_output {
593 0     0 1 0 my $self = shift;
594 0         0 my ($value) = $self->_check_args( \@_, ['value'] );
595              
596 0         0 my $current_level = undef; # for internal use only
597              
598 0 0       0 if ( not defined $value ) {
599 0         0 return $self->get_output();
600             }
601              
602 0 0       0 if ( $self->device_settings()->{gate_protect} ) {
603 0 0 0     0 if ( $self->get_output() == 1 and $value == 0 ) {
    0 0        
604 0         0 $self->set_level(0);
605             }
606             elsif ( $self->get_output() == 0 and $value == 1 ) {
607 0         0 $current_level = $self->get_level();
608 0         0 $self->set_level(0);
609             }
610             }
611              
612 0         0 $self->wait();
613              
614 0 0       0 if ( $value == 1 ) {
    0          
615 0         0 $self->write('O1');
616 0         0 $self->write('E');
617 0 0       0 if ( defined $current_level ) {
618 0         0 $self->set_level($current_level);
619             }
620              
621             }
622             elsif ( $value == 0 ) {
623 0         0 $self->write('O0');
624 0         0 $self->write('E');
625              
626             }
627             else {
628 0         0 Lab::Exception::CorruptParameter->throw(
629             "$value is not a valid output status (on = 1 | off = 0)");
630             }
631              
632 0         0 return $self->{'device_cache'}->{'output'} = $self->get_output();
633              
634             }
635              
636             sub get_output {
637 0     0 1 0 my $self = shift;
638              
639 0         0 my ($read_mode) = $self->_check_args( \@_, ['read_mode'] );
640              
641 0 0 0     0 if ( not defined $read_mode or not $read_mode =~ /device|cache/ ) {
642 0         0 $read_mode = $self->device_settings()->{read_default};
643             }
644              
645 0 0 0     0 if ( $read_mode eq 'cache'
646             and defined $self->{'device_cache'}->{'output'} ) {
647 0         0 return $self->{'device_cache'}->{'output'};
648             }
649              
650 0         0 my $res = $self->get_status();
651 0         0 return $self->{'device_cache'}->{'output'} = $res->{'output'} / 128;
652             }
653              
654             sub initialize {
655 0     0 0 0 my $self = shift;
656 0         0 $self->reset();
657             }
658              
659             sub reset {
660 0     0 0 0 my $self = shift;
661 0         0 $self->write('RC');
662              
663 0         0 $self->_cache_init();
664             }
665              
666             sub set_voltage_limit {
667 0     0 1 0 my $self = shift;
668 0         0 my ($value) = $self->_check_args( \@_, ['value'] );
669              
670 0         0 my $cmd = sprintf( "LV%e", $value );
671 0         0 $self->write($cmd);
672              
673 0         0 $self->{'device_cache'}->{'voltage_limit'} = $value;
674             }
675              
676             sub get_voltage_limit {
677 0     0 0 0 my $self = shift;
678              
679 0         0 my ($read_mode) = $self->_check_args( \@_, ['read_mode'] );
680              
681 0 0 0     0 if ( not defined $read_mode or not $read_mode =~ /device|cache/ ) {
682 0         0 $read_mode = $self->device_settings()->{read_default};
683             }
684              
685 0 0 0     0 if ( $read_mode eq 'cache'
686             and defined $self->{'device_cache'}->{'voltage_limit'} ) {
687 0         0 return $self->{'device_cache'}->{'voltage_limit'};
688             }
689              
690             # read from device:
691 0         0 my $limit = @{ $self->get_info() }[3];
  0         0  
692              
693 0         0 my @limit = split( /LA/, $limit );
694 0         0 @limit = split( /LV/, $limit[0] );
695 0         0 return $self->{'device_cache'}->{'voltage_limit'} = $limit[1];
696              
697             }
698              
699             sub set_current_limit {
700 0     0 1 0 my $self = shift;
701 0         0 my ($value) = $self->_check_args( \@_, ['value'] );
702              
703 0         0 my $cmd = sprintf( "LA%e", $value );
704 0         0 $self->write($cmd);
705              
706 0         0 $self->{'device_cache'}->{'current_limit'} = $value;
707             }
708              
709             sub get_current_limit {
710 0     0 0 0 my $self = shift;
711              
712 0         0 my ($read_mode) = $self->_check_args( \@_, ['read_mode'] );
713              
714 0 0 0     0 if ( not defined $read_mode or not $read_mode =~ /device|cache/ ) {
715 0         0 $read_mode = $self->device_settings()->{read_default};
716             }
717              
718 0 0 0     0 if ( $read_mode eq 'cache'
719             and defined $self->{'device_cache'}->{'current_limit'} ) {
720 0         0 return $self->{'device_cache'}->{'current_limit'};
721             }
722              
723             # read from device:
724 0         0 my $limit = @{ $self->get_info() }[3];
  0         0  
725              
726 0         0 my @limit = split( /LA/, $limit );
727 0         0 return $self->{'device_cache'}->{'current_limit'} = $limit[1];
728              
729             }
730              
731             sub get_status {
732 3     3 1 6 my $self = shift;
733 3         6 my $request = shift;
734              
735 3         10 my $status = $self->query('OC');
736              
737 3         12 $status =~ /STS1=(\d*)/;
738 3         8 $status = $1;
739 3         10 my @flags = qw/
740             CAL_switch memory_card calibration_mode output
741             unstable ERROR execution setting/;
742 3         6 my $result = {};
743 3         11 for ( 0 .. 7 ) {
744 24         56 $result->{ $flags[$_] } = $status & 128;
745 24         36 $status <<= 1;
746             }
747 3 100       13 return $result->{$request} if defined $request;
748 2         6 return $result;
749             }
750              
751             #
752             # Accessor implementations
753             #
754              
755             sub autorange() {
756 0     0 0   my $self = shift;
757              
758 0 0         return $self->{'autorange'} if scalar(@_) == 0;
759 0           my $value = shift;
760              
761 0 0         if ( $value == 0 ) {
    0          
762 0           $self->{'autorange'} = 0;
763             }
764             elsif ( $value == 1 ) {
765 0           warn(
766             "Warning: Autoranging can give you some nice voltage spikes on the Yokogawa7651. You've been warned!\n"
767             );
768 0           $self->{'autorange'} = 1;
769             }
770             else {
771 0           Lab::Exception::CorruptParameter->throw( error =>
772             "Illegal value for autorange(), only 1 or 0 accepted.\n" );
773             }
774             }
775              
776             1;
777              
778             __END__
779              
780             =pod
781              
782             =encoding utf-8
783              
784             =head1 NAME
785              
786             Lab::Instrument::Yokogawa7651 - Yokogawa 7651 DC source
787              
788             =head1 VERSION
789              
790             version 3.881
791              
792             =head1 SYNOPSIS
793              
794             use Lab::Instrument::Yokogawa7651;
795            
796             my $gate14=new Lab::Instrument::Yokogawa7651(
797             connection_type => 'LinuxGPIB',
798             gpib_address => 22,
799             gate_protecet => 1,
800             level => 0.5,
801             );
802             $gate14->set_voltage(0.745);
803             print $gate14->get_voltage();
804              
805             =head1 DESCRIPTION
806              
807             The Lab::Instrument::Yokogawa7651 class implements an interface to the
808             discontinued voltage and current source 7651 by Yokogawa. This class derives from
809             L<Lab::Instrument::Source> and provides all functionality described there.
810              
811             =head1 CONSTRUCTORS
812              
813             =head2 new( %configuration_HASH )
814              
815             HASH is a list of tuples given in the format
816              
817             key => value,
818              
819             please supply at least the configuration for the connection:
820             connection_type => "LinxGPIB"
821             gpib_address =>
822              
823             you might also want to have gate protect from the start (the default values are given):
824              
825             gate_protect => 1,
826              
827             gp_equal_level => 1e-5,
828             gp_max_units_per_second => 0.05,
829             gp_max_units_per_step => 0.005,
830             gp_max_step_per_second => 10,
831             gp_max_units_per_second => 0.05,
832             gp_max_units_per_step => 0.005,
833              
834             max_sweep_time=>3600,
835             min_sweep_time=>0.1,
836              
837             If you want to use the sweep function without using gate protect, you should specify
838              
839             stepsize=>0.01
840              
841             Additinally there is support to set parameters for the device "on init":
842              
843             function => Voltage, # specify "Voltage" or "Current" mode, string is case insensitive
844             range => undef,
845             level => undef,
846             output => undef,
847              
848             If those values are not specified, the current device configuration is left unaltered.
849              
850             =head1 METHODS
851              
852             =head2 set_voltage
853              
854             $src->set_voltage($voltage)
855              
856             Sets the output voltage to $voltage.
857             Returns the newly set voltage.
858              
859             =head2 get_voltage
860              
861             Returns the currently set $voltage. The value is read from the driver cache by default. Provide the option
862              
863             device_cache => 1
864              
865             to read directly from the device.
866              
867             =head2 set_current
868              
869             $src->set_current($current)
870              
871             Sets the output current to $current.
872             Returns the newly set current.
873              
874             =head2 get_current
875              
876             Returns the currently set $current. The value is read from the driver cache by default. Provide the option
877              
878             device_cache => 1
879              
880             to read directly from the device.
881              
882             =head2 set_level
883              
884             $src->set_level($lvl)
885              
886             Sets the level $lvl in the current operation mode.
887              
888             =head2 get_level
889              
890             $lvl = $src->get_level()
891              
892             Returns the currently set level. Use
893              
894             device_cache => 1
895              
896             to enforce a reading directly from the device.
897              
898             =head2 sweep_to_level
899              
900             $src->sweep_to_level($lvl,$time)
901              
902             Sweep to the level $lvl in $time seconds.
903              
904             =head2 set_range
905              
906             $src->set_range($range)
907              
908             Set the output range for the device. $range should be either in decimal or scientific notation.
909             Returns the newly set range.
910              
911             =head2 get_info
912              
913             Returns the information provided by the instrument's 'OS' command, in the form of an array
914             with one entry per line. For display, use join(',',$yoko->get_info()); or similar.
915              
916             =head2 set_output
917              
918             $src->set_output( $onoff )
919              
920             Sets the output switch to "1" (on) or "0" (off).
921             Returns the new output state;
922              
923             =head2 get_output
924              
925             Returns the status of the output switch (0 or 1).
926              
927             =head2 set_voltage_limit($limit)
928              
929             =head2 set_current_limit($limit)
930              
931             =head2 get_status()
932              
933             Returns a hash with the following keys:
934              
935             CAL_switch
936             memory_card
937             calibration_mode
938             output
939             unstable
940             error
941             execution
942             setting
943              
944             The value for each key is either 0 or 1, indicating the status of the instrument.
945              
946             =head1 INSTRUMENT SPECIFICATIONS
947              
948             =head2 DC voltage
949              
950             The stability (24h) is the value at 23 +- 1°C. The stability (90days),
951             accuracy (90days) and accuracy (1year) are values at 23 +- 5°C.
952             The temperature coefficient is the value at 5 to 18°C and 28 to 40°C.
953              
954             Range Maximum Resolution Stability 24h Stability 90d
955             Output +-(% of setting +-(% of setting
956             + µV) + µV)
957             -------------------------------------------------------------
958             10mV +-12.0000mV 100nV 0.002 + 3 0.014 + 4
959             100mV +-120.000mV 1µV 0.003 + 3 0.014 + 5
960             1V +-1.20000V 10µV 0.001 + 10 0.008 + 50
961             10V +-12.0000V 100µV 0.001 + 20 0.008 + 100
962             30V +-32.000V 1mV 0.001 + 50 0.008 + 200
963              
964              
965              
966             Range Accuracy 90d Accuracy 1yr Temperature
967             +-(% of setting +-(% of setting Coefficient
968             +µV) +µV) +-(% of setting
969             +µV)/°C
970             -----------------------------------------------------
971             10mV 0.018 + 4 0.025 + 5 0.0018 + 0.7
972             100mV 0.018 + 10 0.025 + 10 0.0018 + 0.7
973             1V 0.01 + 100 0.016 + 120 0.0009 + 7
974             10V 0.01 + 200 0.016 + 240 0.0008 + 10
975             30V 0.01 + 500 0.016 + 600 0.0008 + 30
976              
977              
978              
979             Range Maximum Output Output Noise
980             Output Resistance DC to 10Hz DC to 10kHz
981             (typical data)
982             ----------------------------------------------------------
983             10mV - approx. 2Ohm 3µVp-p 30µVp-p
984             100mV - approx. 2Ohm 5µVp-p 30µVp-p
985             1V +-120mA less than 2mOhm 15µVp-p 60µVp-p
986             10V +-120mA less than 2mOhm 50µVp-p 100µVp-p
987             30V +-120mA less than 2mOhm 150µVp-p 200µVp-p
988              
989             Common mode rejection:
990             120dB or more (DC, 50/60Hz). (However, it is 100dB or more in the
991             30V range.)
992              
993             =head2 DC current
994              
995             Range Maximum Resolution Stability (24 h) Stability (90 days)
996             Output +-(% of setting +-(% of setting
997             + µA) + µA)
998             -----------------------------------------------------------------------
999             1mA +-1.20000mA 10nA 0.0015 + 0.03 0.016 + 0.1
1000             10mA +-12.0000mA 100nA 0.0015 + 0.3 0.016 + 0.5
1001             100mA +-120.000mA 1µA 0.004 + 3 0.016 + 5
1002              
1003              
1004             Range Accuracy (90 days) Accuracy (1 year) Temperature
1005             +-(% of setting +-(% of setting Coefficient
1006             + µA) + µA) +-(% of setting
1007             + µA)/°C
1008             ----- ------------------------------------------------------
1009             1mA 0.02 + 0.1 0.03 + 0.1 0.0015 + 0.01
1010             10mA 0.02 + 0.5 0.03 + 0.5 0.0015 + 0.1
1011             100mA 0.02 + 5 0.03 + 5 0.002 + 1
1012              
1013              
1014             Range Maximum Output Output Noise
1015             Output Resistance DC to 10Hz DC to 10kHz
1016             (typical data)
1017             -----------------------------------------------------------------
1018             1mA +-30 V more than 100MOhm 0.02µAp-p 0.1µAp-p
1019             10mA +-30 V more than 100MOhm 0.2µAp-p 0.3µAp-p
1020             100mA +-30 V more than 10MOhm 2µAp-p 3µAp-p
1021              
1022             Common mode rejection: 100nA/V or more (DC, 50/60Hz).
1023              
1024             =head1 CAVEATS
1025              
1026             probably many
1027              
1028             =head1 SEE ALSO
1029              
1030             =over 4
1031              
1032             =item * Lab::Instrument
1033              
1034             The Yokogawa7651 class is a Lab::Instrument (L<Lab::Instrument>).
1035              
1036             =item * Lab::Instrument::Source
1037              
1038             The Yokogawa7651 class is a Source (L<Lab::Instrument::Source>)
1039              
1040             =back
1041              
1042             =head1 COPYRIGHT AND LICENSE
1043              
1044             This software is copyright (c) 2023 by the Lab::Measurement team; in detail:
1045              
1046             Copyright 2005-2006 Daniel Schroeer
1047             2009 Andreas K. Huettel, Daniela Taubert
1048             2010 Andreas K. Huettel, Daniel Schroeer
1049             2011 Andreas K. Huettel, Florian Olbrich
1050             2012 Alois Dirnaichner, Andreas K. Huettel, Florian Olbrich, Stefan Geissler
1051             2013 Alois Dirnaichner, Andreas K. Huettel, Christian Butschkow, Stefan Geissler
1052             2014 Alexei Iankilevitch, Alois Dirnaichner, Christian Butschkow
1053             2015 Andreas K. Huettel, Christian Butschkow
1054             2016 Simon Reinhardt
1055             2017 Andreas K. Huettel
1056             2020 Andreas K. Huettel
1057              
1058              
1059             This is free software; you can redistribute it and/or modify it under
1060             the same terms as the Perl 5 programming language system itself.
1061              
1062             =cut