File Coverage

blib/lib/Lab/Instrument/Agilent34410A.pm
Criterion Covered Total %
statement 52 279 18.6
branch 6 92 6.5
condition 1 53 1.8
subroutine 16 45 35.5
pod 29 29 100.0
total 104 498 20.8


line stmt bran cond sub pod time code
1             package Lab::Instrument::Agilent34410A;
2             #ABSTRACT: HP/Agilent/Keysight 34410A or 34411A digital multimeter
3             $Lab::Instrument::Agilent34410A::VERSION = '3.880';
4 2     2   2531 use v5.20;
  2         8  
5              
6              
7              
8 2     2   11 use warnings;
  2         5  
  2         58  
9 2     2   10 use strict;
  2         4  
  2         47  
10              
11 2     2   12 use Time::HiRes qw (usleep);
  2         18  
  2         17  
12 2     2   979 use Lab::Instrument;
  2         10  
  2         85  
13 2     2   567 use Lab::Instrument::Multimeter;
  2         5  
  2         67  
14 2     2   518 use Lab::SCPI qw(scpi_match);
  2         5  
  2         141  
15 2     2   18 use Data::Dumper;
  2         5  
  2         8721  
16             our @ISA = ("Lab::Instrument::Multimeter");
17              
18             our %fields = (
19             supported_connections => [ 'VISA_GPIB', 'GPIB', 'DEBUG', 'DUMMY' ],
20              
21             # default settings for the supported connections
22             connection_settings => {
23             gpib_board => 0,
24             gpib_address => undef,
25             timeout => 2,
26             read_default => "device",
27             termchar => "\n"
28             },
29              
30             device_settings => {
31             pl_freq => 50,
32             },
33              
34             device_cache => {
35             'function' => undef,
36             'range' => undef,
37             'nplc' => undef,
38             'resolution' => undef,
39             'tc' => undef,
40             'bw' => undef,
41             },
42              
43             device_cache_order =>
44             [ 'function', 'range', 'nplc', 'resolution', 'tc', 'bw' ],
45              
46             );
47              
48              
49             sub new {
50 1     1 1 3 my $proto = shift;
51 1   33     13 my $class = ref($proto) || $proto;
52 1         8 my $self = $class->SUPER::new(@_);
53 1         6 $self->_construct($class);
54              
55             # Perform initial device clear.
56 1         9 $self->clear();
57              
58 1         8 return $self;
59             }
60              
61              
62             sub get_value {
63 1     1 1 1065 my ( $self, $tail ) = _init_getter(@_);
64              
65 1         40 return $self->request( ":read?", $tail );
66             }
67              
68              
69             sub get_error {
70 0     0 1 0 my $self = shift;
71 0         0 chomp( my $err = $self->query("SYSTem:ERRor?") );
72 0         0 my ( $err_num, $err_msg ) = split ",", $err;
73 0         0 $err_msg =~ s/\"//g;
74 0         0 return ( $err_num, $err_msg );
75             }
76              
77              
78             sub reset { # basic
79 1     1 1 21 my $self = shift;
80 1         5 $self->write("*RST");
81 1         12 $self->reset_device_cache();
82             }
83              
84              
85             # to be moved into Lab::Instrument::Multimeter??
86             sub assert_function {
87 29     29 1 45 my $self = shift;
88 29         48 my $keyword = shift;
89              
90 29         95 my $function = $self->get_function( { read_mode => 'cache' } );
91 29 50       388 if ( scpi_match( $function, $keyword ) == 0 ) {
92 0         0 Lab::Exception::CorruptParameter->throw(
93             "invalid function '$function': allowed choices are: $keyword");
94             }
95 29         75 return $function;
96             }
97              
98             # ------------------------------- SENSE ---------------------------------
99              
100             my $valid_functions
101             = 'current[:dc]|current:ac|voltage[:dc]|voltage[:ac]|resistance|fresistance';
102              
103              
104             sub set_function { # basic
105 0     0 1 0 my $self = shift;
106              
107 0         0 my ( $function, $tail ) = $self->_check_args_strict( \@_, ['function'] );
108              
109 0 0       0 if ( not scpi_match( $function, $valid_functions ) ) {
110 0         0 Lab::Exception::CorruptParameter->throw( error =>
111             "Agilent 34410A:\n\nAgilent 34410A:\nunexpected value for FUNCTION in sub set_function. Expected values are VOLTAGE:DC, VOLTAGE:AC, CURRENT:DC, CURRENT:AC, RESISTANCE or FRESISTANCE.\n"
112             );
113             }
114              
115 0         0 $self->write( "FUNCTION '$function'", $tail );
116              
117             }
118              
119              
120             sub get_function {
121 0     0 1 0 my $self = shift;
122              
123             # read from cache or from device?
124 0         0 my ($tail) = $self->_check_args( \@_, [] );
125              
126             # read from device:
127 0         0 my $function = $self->query( "FUNCTION?", $tail );
128 0 0       0 if ( $function =~ /([\w:]+)/ ) {
129 0         0 return $1;
130             }
131              
132             # FIXME: throw here?
133             }
134              
135              
136             sub _invalid_range {
137 0     0   0 my $range = shift;
138 0         0 Lab::Exception::CorruptParameter->throw( error =>
139             "set_range: unexpected value '$range' for RANGE. Expected values are for CURRENT, VOLTAGE and RESISTANCE mode -3...+3A, 0.1...1000V or 0...1e9 Ohms respectivly"
140             );
141             }
142              
143             sub _check_range {
144 6     6   10 my $function = shift;
145 6         13 my $range = shift;
146              
147 6 100       16 if ( scpi_match( $function, 'voltage[:dc]|voltage:ac' ) ) {
    50          
    0          
148 3 50       13 if ( abs($range) > 1000 ) {
149 0         0 _invalid_range($range);
150             }
151             }
152             elsif ( scpi_match( $function, 'current[:dc]|current:ac' ) ) {
153 3 50       13 if ( abs($range) > 3 ) {
154 0         0 _invalid_range($range);
155             }
156             }
157             elsif ( scpi_match( $function, 'resistance|fresistance' ) ) {
158 0 0 0     0 if ( $range < 0 or $range > 1e9 ) {
159 0         0 _invalid_range($range);
160             }
161             }
162             else {
163 0         0 Lab::Exception::CorruptParameter->throw( error =>
164             "set_range: Unexpected function '$function'. Expected values are VOLTAGE:DC, VOLTAGE:AC, CURRENT:DC, CURRENT:AC, RESISTANCE or FRESISTANCE."
165             );
166             }
167             }
168              
169             sub set_range { # basic
170 0     0 1 0 my $self = shift;
171              
172 0         0 my ( $range, $tail ) = $self->_check_args_strict( \@_, ['range'] );
173 0         0 my $function = $self->get_function( { read_mode => 'cache' } );
174              
175             # check if value of paramter 'range' is valid:
176              
177 0 0       0 if ( not scpi_match( $range, 'min|max|def|auto' ) ) {
178 0         0 _check_range( $function, $range );
179             }
180              
181             # set range
182 0 0 0     0 if ( scpi_match( $range, 'min|max|def' )
    0          
183             or $range =~ /\b\d+(e\d+|E\d+|exp\d+|EXP\d+)?\b/ ) {
184 0         0 $self->write( "$function:RANGE $range", $tail );
185             }
186             elsif ( scpi_match( $range, 'auto' ) ) {
187 0         0 $self->write( sprintf( "%s:RANGE:AUTO ON", $function ), $tail );
188             }
189             else {
190 0         0 Lab::Exception::CorruptParameter->throw(
191             error => "anything's wrong in sub set_range!!" );
192             }
193             }
194              
195             sub _init_getter {
196 27     27   43 my $self = shift;
197 27         96 my ($tail) = $self->_check_args( \@_, [] );
198 27         87 return ( $self, $tail );
199             }
200              
201              
202             sub get_range {
203 0     0 1 0 my ( $self, $tail ) = _init_getter(@_);
204              
205 0         0 my $function = $self->assert_function($valid_functions);
206              
207 0         0 return $self->query( "$function:RANGE?", $tail );
208             }
209              
210              
211             sub get_autorange {
212 2     2 1 38 my ( $self, $tail ) = _init_getter(@_);
213 2         12 my $function = $self->assert_function($valid_functions);
214              
215 2         11 return $self->query("$function:RANGE:AUTO?");
216             }
217              
218             my $valid_dc_functions = 'current[:dc]|voltage[:dc]|resistance|fresistance';
219              
220              
221             sub set_nplc { # basic
222 0     0 1 0 my $self = shift;
223              
224 0         0 my ( $nplc, $tail ) = $self->_check_args_strict( \@_, ['nplc'] );
225              
226             # check if value of paramter 'nplc' is valid:
227 0 0 0     0 if ( ( $nplc < 0.006 or $nplc > 100 ) and not $nplc =~ /^(min|max|def)$/ )
      0        
228             {
229 0         0 Lab::Exception::CorruptParameter->throw( error =>
230             "unexpected value for NPLC in sub set_nplc. Expected values are between 0.006 ... 100 power-line-cycles (50Hz)."
231             );
232             }
233              
234             # set nplc:
235 0         0 my $function = $self->assert_function($valid_dc_functions);
236              
237 0         0 $self->write( "$function:NPLC $nplc", $tail );
238             }
239              
240              
241             sub get_nplc {
242 0     0 1 0 my ( $self, $tail ) = _init_getter(@_);
243              
244 0         0 my $function = $self->assert_function($valid_dc_functions);
245              
246 0         0 return $self->query( "$function:NPLC?", $tail );
247             }
248              
249              
250             sub set_resolution { # basic
251 0     0 1 0 my $self = shift;
252 0         0 my ( $resolution, $tail )
253             = $self->_check_args_strict( \@_, ['resolution'] );
254 0         0 my $function = $self->assert_function($valid_dc_functions);
255              
256             # check if value of paramter 'resolution' is valid:
257             # FIXME: wiso read_mode 'device' ???
258 0         0 my $range = $self->get_range( { read_mode => 'device' } );
259              
260 0 0 0     0 if ( $resolution < 0.3e-6 * $range
261             and not $resolution =~ /^(min|max|def)$/ ) {
262 0         0 Lab::Exception::CorruptParameter->throw( error =>
263             "\nAgilent 34410A:\nunexpected value for RESOLUTION in sub set_resolution. Expected values have to be greater than 0.3e-6*RANGE."
264             );
265             }
266              
267             # switch off autorange function if activated.
268 0         0 $self->set_range($range);
269 0         0 $self->write( "$function:RES $resolution", $tail );
270              
271             }
272              
273              
274             sub get_resolution {
275 0     0 1 0 my ( $self, $tail ) = _init_getter(@_);
276              
277 0         0 my $function = $self->assert_function($valid_functions);
278              
279 0         0 return $self->query( "$function:RES?", $tail );
280             }
281              
282              
283             sub set_tc { # basic
284 0     0 1 0 my $self = shift;
285              
286 0         0 my ( $tc, $tail ) = $self->_check_args_strict( \@_, ['tc'] );
287              
288 0         0 my $function = $self->assert_function($valid_dc_functions);
289              
290             # check if value of paramter 'tc' is valid:
291 0 0 0     0 if ( ( $tc < 1e-4 or $tc > 1 ) and not $tc =~ /^(min|max|def)$/ ) {
      0        
292 0         0 Lab::Exception::CorruptParameter->throw( error =>
293             "unexpected value for APERTURE in sub set_tc. Expected values are between 1e-4 ... 1 sec."
294             );
295             }
296              
297             # set tc:
298 0         0 $self->write( ":$function:APERTURE $tc; APERTURE:ENABLED 1", $tail );
299             }
300              
301              
302             sub get_tc {
303 0     0 1 0 my ( $self, $tail ) = _init_getter(@_);
304              
305 0         0 my $function = $self->assert_function($valid_dc_functions);
306              
307 0         0 return $self->query( "$function:APERTURE?", $tail );
308             }
309              
310             my $valid_ac_functions = 'current:ac|voltage:ac';
311              
312              
313             sub set_bw { # basic
314 0     0 1 0 my $self = shift;
315 0         0 my ( $bw, $tail ) = $self->_check_args_strict( \@_, ['bandwidth'] );
316              
317 0         0 my $function = $self->assert_function($valid_ac_functions);
318              
319             # check if value of paramter 'bw' is valid:
320 0 0 0     0 if ( ( $bw < 3 or $bw > 200 ) and not $bw =~ /^(min|max|def)$/ ) {
      0        
321 0         0 Lab::Exception::CorruptParameter->throw( error =>
322             "\nAgilent 34410A:\nunexpected value for BANDWIDTH in sub set_bw. Expected values are between 3 ... 200 Hz."
323             );
324             }
325              
326             # set bw:
327 0         0 $self->write( "$function:BANDWIDTH $bw", $tail );
328             }
329              
330              
331             sub get_bw {
332 0     0 1 0 my ( $self, $tail ) = _init_getter(@_);
333              
334 0         0 my $function = $self->assert_function($valid_ac_functions);
335              
336 0         0 return $self->query( "$function:BANDWIDTH?", $tail );
337             }
338              
339             # ----------------------------- TAKE DATA ---------------------------------------------------------
340              
341              
342             sub config_measurement { # basic
343 0     0 1 0 my $self = shift;
344              
345             # parameter == hash??
346 0         0 my ( $function, $nop, $time, $range, $trigger ) = $self->_check_args(
347             \@_,
348             [ 'function', 'nop', 'time', 'range', 'trigger' ]
349             );
350              
351             # check input data
352 0 0       0 if ( not defined $trigger ) {
353 0         0 $trigger = 'BUS';
354             }
355 0 0       0 if ( not defined $range ) {
356 0         0 $range = 'DEF';
357             }
358 0 0       0 if ( not defined $time ) {
359 0         0 Lab::Exception::CorruptParameter->throw( error =>
360             "too view arguments given in sub config_measurement. Expected arguments are FUNCTION, #POINTS, TIME, <RANGE>, <TRIGGERSOURCE>"
361             );
362             }
363              
364 0         0 print "--------------------------------------\n";
365 0         0 print "Agilent34410A: sub config_measurement:\n";
366              
367             # clear buffer
368 0         0 my $points = $self->query( "DATA:POINTS?", { read_mode => 'device' } );
369 0 0       0 if ( $points > 0 ) {
370 0         0 $points = $self->connection()
371             ->LongQuery( command => "DATA:REMOVE? $points" );
372             }
373              
374             # set function
375 0         0 print "set_function: " . $self->set_function($function) . "\n";
376              
377             # set range
378 0         0 print "set_range: " . $self->set_range($range) . "\n";
379              
380             # set integration time
381 0         0 my $tc = $time / $nop;
382 0         0 print "set_tc: " . $self->set_tc($tc) . "\n";
383              
384             # set auto high impedance (>10GOhm) for VOLTAGE:DC for ranges 100mV, 1V, 10V
385 0 0       0 if ( $function
386             =~ /^(VOLTAGE|voltage|VOLT|volt|VOLTAGE:DC|voltage:dc|VOLT:DC|volt:dc)$/
387             ) {
388 0         0 print "set_auto_high_impedance\n";
389 0         0 $self->write("SENS:VOLTAGE:DC:IMPEDANCE:AUTO ON");
390             }
391              
392             # perfome AUTOZERO and then disable
393 0 0       0 if ( $function
394             =~ /^(CURRENT|current|CURR|curr|CURRENT:DC|current:dc|CURR:DC|curr:dc|VOLTAGE|voltage|VOLT|volt|VOLTAGE:DC|voltage:dc|VOLT:DC|volt:dc|RESISTANCE|resistance|RES|res|FRESISTANCE|fresistance|FRES|fres)$/
395             ) {
396 0         0 print "set_AUTOZERO OFF\n";
397 0         0 $self->write( sprintf( "SENS:%s:ZERO:AUTO OFF", $function ) );
398             }
399              
400             # triggering
401 0         0 print "set Trigger Source: " . $self->_set_triggersource("BUS") . "\n";
402 0         0 print "set Trigger Count: " . $self->_set_triggercount(1) . "\n";
403 0         0 print "set Trigger Delay: " . $self->_set_triggerdelay("MIN") . "\n";
404              
405 0         0 print "set Sample Count: " . $self->_set_samplecount($nop) . "\n";
406 0         0 print "set Sample Delay: " . $self->_set_sampledelay(0) . "\n";
407              
408 0         0 print "init()\n";
409 0         0 $self->write("INIT");
410 0         0 usleep(5e5);
411              
412 0         0 print "Agilent34410A: sub config_measurement complete\n";
413 0         0 print "--------------------------------------\n";
414              
415             }
416              
417              
418             sub trg { # basic
419 0     0 1 0 my $self = shift;
420 0         0 $self->write("*TRG");
421             }
422              
423              
424             sub get_data { # basic
425 0     0 1 0 my $self = shift;
426 0         0 my $data;
427             my @data;
428              
429             # parameter == hash??
430 0         0 my ($readings) = $self->_check_args( \@_, ['readings'] );
431              
432 0 0       0 if ( not defined $readings ) { $readings = "ALL"; }
  0         0  
433              
434 0 0 0     0 if ( $readings >= 1 and $readings <= 50000 ) {
    0 0        
435 0 0       0 if ( $readings > $self->query("SAMPLE:COUNT?") ) {
436 0         0 $readings = $self->query("SAMPLE:COUNT?");
437             }
438 0         0 for ( my $i = 1; $i <= $readings; $i++ ) {
439 0         0 my $break = 1;
440 0         0 while ($break) {
441 0         0 $data = $self->connection()->LongQuery( command => "R? 1" );
442              
443 0         0 my $index;
444 0 0       0 if ( index( $data, "+" ) == -1 ) {
    0          
445 0         0 $index = index( $data, "-" );
446             }
447             elsif ( index( $data, "-" ) == -1 ) {
448 0         0 $index = index( $data, "+" );
449             }
450             else {
451 0 0       0 $index
452             = ( index( $data, "-" ) < index( $data, "+" ) )
453             ? index( $data, "-" )
454             : index( $data, "+" );
455             }
456 0         0 $data = substr( $data, $index, length($data) - $index );
457 0 0       0 if ( $data != 0 ) { $break = 0; }
  0         0  
458 0         0 else { usleep(1e5); }
459             }
460 0         0 push( @data, $data );
461             }
462 0 0       0 if ( $readings == 1 ) { return $data; }
  0         0  
463 0         0 else { return @data; }
464             }
465             elsif ( $readings eq "ALL" or $readings = "all" ) {
466              
467             # wait until data are available
468 0         0 $self->wait();
469 0         0 $data = $self->connection()->LongQuery( command => "FETC?" );
470              
471 0         0 @data = split( ",", $data );
472 0         0 return @data;
473             }
474             else {
475 0         0 Lab::Exception::CorruptParameter->throw( error =>
476             "unexpected value for number of readINGS in sub get_data. Expected values are from 1 ... 50000 or ALL."
477             );
478             }
479              
480             }
481              
482              
483             sub abort { # basic
484 1     1 1 4 my $self = shift;
485 1         5 $self->write("ABOR");
486             }
487              
488              
489             sub wait { # basic
490 0     0 1   my $self = shift;
491              
492 0           while (1) {
493 0 0         if ( $self->active() ) { usleep(1e3); }
  0            
494 0           else { last; }
495             }
496              
497 0           return 0;
498              
499             }
500              
501              
502             sub active { # basic
503 0     0 1   my $self = shift;
504              
505 0           my $status = sprintf(
506             "%.15b",
507             $self->query( "STAT:OPER:COND?", { read_mode => 'device' } )
508             );
509 0           my @status = split( "", $status );
510 0 0 0       if ( $status[5] == 1 && $status[10] == 0 ) {
511 0           return 0;
512             }
513             else {
514 0           return 1;
515             }
516              
517             }
518              
519             # ------------------ TRIGGER and SAMPLE settings ---------------------- #
520              
521             sub _set_triggersource { # internal
522 0     0     my $self = shift;
523              
524             # parameter == hash??
525 0           my ($source) = $self->_check_args( \@_, ['trigger_source'] );
526              
527 0 0         if ( not defined $source ) {
528 0           $source = $self->query( sprintf("TRIGGER:SOURCE?") );
529              
530 0           $self->{config}->{triggersource} = $source;
531 0           return $source;
532             }
533              
534 0 0         if ( $source =~ /^(IMM|imm|EXT|ext|BUS|bus|INT|int)$/ ) {
535 0           $source = $self->query(
536             sprintf( "TRIGGER:SOURCE %s; SOURCE?", $source ) );
537 0           $self->{config}->{triggersource} = $source;
538 0           return $source;
539             }
540             else {
541 0           Lab::Exception::CorruptParameter->throw( error =>
542             "\nAgilent 34410A:\nunexpected value for TRIGGER_SOURCE in sub _set_triggersource. Expected values are:\n IMM --> immediate trigger signal\n EXT --> external trigger\n BUS --> software trigger signal via bus\n INT --> internal trigger signal\n"
543             );
544             }
545              
546             }
547              
548             sub _set_triggercount { # internal
549 0     0     my $self = shift;
550              
551             # parameter == hash??
552 0           my ($count) = $self->_check_args( \@_, ['trigger_count'] );
553              
554 0 0         if ( not defined $count ) {
555 0           $count = $self->query( sprintf("TRIGGER:COUNT?") );
556              
557 0           $self->{config}->{triggercount} = $count;
558 0           return $count;
559             }
560              
561 0 0 0       if ( $count >= 0 or $count <= 50000 ) {
562 0           $count
563             = $self->query( sprintf( "TRIGGER:COUNT %d; COUNT?", $count ) );
564 0           $self->{config}->{triggercount} = $count;
565 0           return $count;
566             }
567             else {
568 0           Lab::Exception::CorruptParameter->throw( error =>
569             "\nAgilent 34410A:\nunexpected value for COUNT in sub _set_triggercount. Expected values are between 1 ... 50.000\n"
570             );
571             }
572              
573             }
574              
575             sub _set_triggerdelay { # internal
576 0     0     my $self = shift;
577              
578             # parameter == hash??
579 0           my ($delay) = $self->_check_args( \@_, ['trigger_delay'] );
580              
581 0 0         if ( not defined $delay ) {
582 0           $delay = $self->query( sprintf("TRIGGER:DELAY?") );
583              
584 0           $self->{config}->{triggerdely} = $delay;
585 0           return $delay;
586             }
587              
588 0 0 0       if ( $delay =~ /^(min|max|def)$/i or $delay >= 0 or $delay <= 3600 ) {
    0 0        
589 0           $delay = $self->query("TRIGGER:DELAY $delay; DELAY?");
590 0           $self->{config}->{triggerdely} = $delay;
591 0           return $delay;
592             }
593             elsif ( $delay =~ /^(AUTO|auto)$/ ) {
594 0           $delay = $self->query("TRIGGER:DELAY:AUTO ON; AUTO?");
595 0           $self->{config}->{triggerdely} = "AUTO ON";
596 0           return "AUTO ON";
597             }
598             else {
599 0           Lab::Exception::CorruptParameter->throw( error =>
600             "\nAgilent 34410A:\nunexpected value for DELAY in sub _set_triggerdelay. Expected values are between 1 ... 3600, or 'MIN = 0', 'MAX = 3600' or 'AUTO'\n"
601             );
602             }
603             }
604              
605             sub _set_samplecount { # internal
606 0     0     my $self = shift;
607              
608             # parameter == hash??
609 0           my ($count) = $self->_check_args( \@_, ['sample_count'] );
610              
611 0 0 0       if ( not defined $count ) {
    0          
612 0           $count = $self->query( sprintf("SAMPLE:COUNT?") );
613              
614 0           $self->{config}->{samplecount} = $count;
615 0           return $count;
616             }
617              
618             elsif ( $count < 0 or $count >= 50000 ) {
619 0           Lab::Exception::CorruptParameter->throw( error =>
620             "\nAgilent 34410A:\nunexpected value for COUNT in sub _set_samplecount. Expected values are between 1 ... 50.000\n"
621             );
622             }
623             else {
624 0           $count = $self->query( sprintf( "SAMPLE:COUNT %d; COUNT?", $count ) );
625 0           $self->{config}->{samplecount} = $count;
626 0           return $count;
627             }
628             }
629              
630             sub _set_sampledelay { # internal
631 0     0     my $self = shift;
632              
633             # parameter == hash??
634 0           my ($delay) = $self->_check_args( \@_, ['sample_delay'] );
635              
636 0 0         if ( not defined $delay ) {
637 0           $delay = $self->query( sprintf("SAMPLE:TIMER?") );
638              
639 0           $self->{config}->{sampledelay} = $delay;
640 0           return $delay;
641             }
642              
643 0 0 0       if ( $delay =~ /^(MIN|min|MAX|max|DEF|def)$/ ) {
    0          
644 0           $delay = $self->query( sprintf( "SAMPLE:TIMER %s; TIMER?", $delay ) );
645 0           $self->write("SAMPLE:SOURCE TIM");
646 0           $self->{config}->{samplecount} = $delay;
647 0           return $delay;
648             }
649             elsif ( $delay >= 0 or $delay <= 3600 ) {
650 0           $delay
651             = $self->query( sprintf( "SAMPLE:TIMER %.5f; TIMER?", $delay ) );
652 0           $self->write("SAMPLE:SOURCE TIM");
653 0           $self->{config}->{samplecount} = $delay;
654 0           return $delay;
655             }
656              
657             else {
658 0           Lab::Exception::CorruptParameter->throw( error =>
659             "\nAgilent 34410A:\nunexpected value for DELAY in sub _set_sampledelay. Expected values are between 1 ... 3600, or 'MIN = 0', 'MAX = 3600'\n"
660             );
661             }
662              
663             }
664              
665             # ------------------------------- DISPLAY and BEEPER --------------------------------------------
666              
667              
668             sub display_text { # basic
669 0     0 1   my $self = shift;
670              
671             # parameter == hash??
672 0           my ($text) = $self->_check_args( \@_, ['display_text'] );
673              
674 0 0         if ($text) {
675 0           $self->write(qq(DISPlay:TEXT "$text"));
676             }
677             else {
678 0           $text = $self->query(qq(DISPlay:TEXT?));
679 0           $text =~ s/\"//g;
680             }
681 0           return $text;
682             }
683              
684              
685             sub display_on { # basic
686 0     0 1   my $self = shift;
687 0           $self->write("DISPLAY ON");
688             }
689              
690              
691              
692             sub display_off { # basic
693 0     0 1   my $self = shift;
694 0           $self->write("DISPLAY OFF");
695             }
696              
697              
698             sub display_clear { # basic
699 0     0 1   my $self = shift;
700 0           $self->write("DISPLAY:TEXT:CLEAR");
701             }
702              
703              
704             sub beep { # basic
705 0     0 1   my $self = shift;
706 0           $self->write("SYSTEM:BEEPER");
707             }
708              
709             1;
710              
711             __END__
712              
713             =pod
714              
715             =encoding UTF-8
716              
717             =head1 NAME
718              
719             Lab::Instrument::Agilent34410A - HP/Agilent/Keysight 34410A or 34411A digital multimeter
720              
721             =head1 VERSION
722              
723             version 3.880
724              
725             =head1 SYNOPSIS
726              
727             use Lab::Instrument::Agilent34410A;
728             my $multimeter = Lab::Instrument::Agilent34410A->new(%options);
729              
730             print $multimeter->get_value();
731              
732             =head1 DESCRIPTION
733              
734             The Lab::Instrument::Agilent34410A class implements an interface to the 34410A
735             and 34411A digital multimeters by Agilent (now Keysight, formerly HP).
736              
737             =head1 METHODS
738              
739             =head2 new(%options)
740              
741             This method is described in L<Lab::Measurement::Tutorial> and
742             L<Lab::Instrument>.
743              
744             =head2 get_value()
745              
746             Perform data aquisition.
747              
748             my $value = $multimeter->get_value();
749              
750             =head2 get_error()
751              
752             my ($err_num, $err_msg) = $agilent->get_error();
753              
754             Query the multimeter's error queue. Up to 20 errors can be stored in the
755             queue. Errors are retrieved in first-in-first out (FIFO) order.
756              
757             =head2 reset()
758              
759             $agilent->reset();
760              
761             Reset the multimeter to its power-on configuration.
762              
763             =head2 assert_function($keyword)
764              
765             Throw if the instrument is not in one of the operating modes given in
766             C<$keyword>. See L<Lab::SCPI> for the keyword syntax.
767              
768             =head2 set_function($function)
769              
770             Set a new value for the measurement function of the Agilent34410A.
771              
772             C<$function> can be one of the measurement methods of the Agilent34410A.
773              
774             "current:dc" --> DC current measurement
775             "current:ac" --> AC current measurement
776             "voltage:dc" --> DC voltage measurement
777             "voltage:ac" --> AC voltage measurement
778             "resistance" --> resistance measurement (2-wire)
779             "fresistance" --> resistance measurement (4-wire)
780              
781             =head2 get_function()
782              
783             Return the used measurement function.
784              
785             =head2 set_range($range)
786              
787             Set the range of the used measurement function to C<$range>.
788              
789             C<RANGE> is given in terms of amps, volts or ohms and can be C<-3...+3A | MIN | MAX | DEF | AUTO>, C<100mV...1000V | MIN | MAX | DEF | AUTO> or C<0...1e9 | MIN | MAX | DEF | AUTO>.
790             C<DEF> is default C<AUTO> activates the C<AUTORANGE-mode>.
791             C<DEF> will be set, if no value is given.
792              
793             =head2 get_range()
794              
795             Return the range of the used measurement function.
796              
797             =head2 get_autorange()
798              
799             Return non-zero, if autoranging is enabled.
800              
801             =head2 set_nplc($nplc)
802              
803             Set a new value for the predefined C<NUMBER of POWER LINE CYCLES> for the
804             used measurement function.
805              
806             The C<NUMBER of POWER LINE CYCLES> is actually something similar to an integration time for recording a single measurement value.
807             The values for C<$nplc> can be any value between 0.006 ... 100 but internally the Agilent34410A selects the value closest to one of the following fixed values C< 0.006 | 0.02 | 0.06 | 0.2 | 1 | 2 | 10 | 100 | MIN | MAX | DEF >.
808              
809             Example:
810             Assuming C<$nplc> to be 10 and assuming a netfrequency of 50Hz this results in an integration time of 10*50Hz = 0.2 seconds for each measured value.
811              
812             NOTE:
813             1.) Only those integration times set to an integral number of power line cycles (1, 2, 10, or 100 PLCs) provide normal mode (line frequency noise) rejection.
814             2.) Setting the integration time also sets the resolution for the measurement. The following table shows the relationship between integration time and resolution.
815              
816             Integration Time (power line cycles) Resolution
817             0.001 PLC (34411A only) 30 ppm x Range
818             0.002 PLC (34411A only) 15 ppm x Range
819             0.006 PLC 6.0 ppm x Range
820             0.02 PLC 3.0 ppm x Range
821             0.06 PLC 1.5 ppm x Range
822             0.2 PLC 0.7 ppm x Range
823             1 PLC (default) 0.3 ppm x Range
824             2 PLC 0.2 ppm x Range
825             10 PLC 0.1 ppm x Range
826             100 PLC 0.03 ppm x Range
827              
828             =head2 get_nplc()
829              
830             Return the value of C<nplc> for the used measurement function.
831              
832             =head2 set_resolution($resolution)
833              
834             Set a new resolution for the used measurement function.
835              
836             Give the current value C<RANGE> of the current range,
837             C<$resolution> is given in terms of C<$resolution * RANGE> or C<[MIN|MAX|DEF]>.
838             C<$resolution=0.0001> means 4 1/2 digits for example.
839             $resolution must be larger than 0.3e-6xRANGE.
840             The best resolution is range = 100mV ==> resoltuion = 3e-8V
841             C<DEF> will be set, if no value is given.
842              
843             =head2 get_resolution()
844              
845             Return the resolution of the used measurement function.
846              
847             =head2 set_tc($tc)
848              
849             Set a new value for the predefined C<INTEGRATION TIME> for the used measurement
850             function.
851              
852             C<INTEGRATION TIME> $tc can be C< 1e-4 ... 1s | MIN | MAX | DEF>.
853              
854             NOTE:
855             1.) Only those integration times set to an integral number of power line cycles
856             (1, 2, 10, or 100 PLCs) provide normal mode (line frequency noise) rejection.
857             2.) Setting the integration time also sets the resolution for the
858             measurement. The following table shows the relationship between integration
859             time and resolution.
860              
861             Integration Time (power line cycles) Resolution
862             0.001 PLC (34411A only) 30 ppm x Range
863             0.002 PLC (34411A only) 15 ppm x Range
864             0.006 PLC 6.0 ppm x Range
865             0.02 PLC 3.0 ppm x Range
866             0.06 PLC 1.5 ppm x Range
867             0.2 PLC 0.7 ppm x Range
868             1 PLC (default) 0.3 ppm x Range
869             2 PLC 0.2 ppm x Range
870             10 PLC 0.1 ppm x Range
871             100 PLC 0.03 ppm x Range
872              
873             =head2 get_tc()
874              
875             Return the C<INTEGRATION TIME> of the used measurement function.
876              
877             =head2 set_bw($bw)
878              
879             Set a new C<BANDWIDTH> for the used measurement function, which must be
880             C<VOLTAGE:AC> or C<CURRENT:AC>.
881              
882             C<$bw> can be C< 3 ... 200Hz | MIN | MAX | DEF>.
883              
884             =head2 get_bw()
885              
886             Return the bandwidth of the used measurement function, which must be
887             C<VOLTAGE:AC> or C<CURRENT:AC>.
888              
889             =head2 config_measurement
890              
891             old style:
892             $agilent->config_measurement($function, $number_of_points, <$time>, <$range>);
893            
894             new style:
895             $agilent->config_measurement({
896             'function' => $function,
897             'nop' => $number_of_points,
898             'time' => <$time>,
899             'range' => <$range>
900             });
901              
902             Preset the Agilent34410A for a TRIGGERED measurement.
903              
904             =over 4
905              
906             =item $function
907              
908             C<FUNCTION> can be one of the measurement methods of the Agilent34410A.
909              
910             "current:dc" --> DC current measurement
911             "current:ac" --> AC current measurement
912             "voltage:dc" --> DC voltage measurement
913             "voltage:ac" --> AC voltage measurement
914             "resistance" --> resistance measurement (2-wire)
915             "fresistance" --> resistance measurement (4-wire)
916              
917             =item $number_of_points
918              
919             Preset the C<NUMBER OF POINTS> to be taken for one measurement trace.
920             The single measured points will be stored in the internal memory of the Agilent34410A.
921             For the Agilent34410A the internal memory is limited to 50.000 values.
922              
923             =item <$time>
924              
925             Preset the C<TIME> duration for one full trace. From C<TIME> the integration time value for each measurement point will be derived [TC = (TIME *50Hz)/NOP].
926             Expected values are between 0.0001*NOP ... 1*NOP seconds.
927              
928             =item <$range>
929              
930             C<RANGE> is given in terms of amps, volts or ohms and can be C< -3...+3A | MIN | MAX | DEF | AUTO >, C< 100mV...1000V | MIN | MAX | DEF | AUTO > or C< 0...1e9 | MIN | MAX | DEF | AUTO >.
931             C<DEF> is default C<AUTO> activates the AUTORANGE-mode.
932             C<DEF> will be set, if no value is given.
933              
934             =back
935              
936             =head2 trg()
937              
938             $agilent->trg();
939              
940             Sends a trigger signal via the C<GPIB-BUS> to start the predefined measurement.
941             The LabVisa-script can immediatally be continued, e.g. to start another
942             triggered measurement using a second Agilent34410A.
943              
944             =head2 get_data($readings)
945              
946             reads all recorded values from the internal buffer and returnes them as an array of floatingpoint values.
947             reading the buffer will start immediately. The LabVisa-script cannot be continued until all requested readings have been recieved.
948              
949             =over 4
950              
951             =item <$readings>
952              
953             C<readINGS> can be a number between 1 and 50.000 or 'ALL' to specifiy the number of values to be read from the buffer.
954             If $readings is not defined, the default value "ALL" will be used.
955              
956             =back
957              
958             =head2 abort()
959              
960             Aborts current (triggered) measurement.
961              
962             =head2 wait()
963              
964             Wait until triggered measurement has been finished.
965              
966             =head2 active()
967              
968             Returns '1' if the current triggered measurement is still active and '0' if the current triggered measurement has allready been finished.
969              
970             =head2 display_text($text)
971              
972             Display C<$text> on the front panel. The multimeter will display up to 12
973             characters in a message; any additional characters are truncated.
974              
975             Without parameter, the displayed message is returned.
976              
977             =head2 display_on()
978              
979             Turn the front-panel display on.
980              
981             =head2 display_off()
982              
983             Turn the front-panel display off.
984              
985             =head2 display_off
986              
987             $agilent->display_off();
988              
989             Turn the front-panel display off.
990              
991             =head2 display_clear()
992              
993             Clear the message displayed on the front panel.
994              
995             =head2 beep()
996              
997             Issue a single beep immediately.
998              
999             =head1 SEE ALSO
1000              
1001             =over 4
1002              
1003             =item L<Lab::Instrument>
1004              
1005             =back
1006              
1007             =head1 COPYRIGHT AND LICENSE
1008              
1009             This software is copyright (c) 2023 by the Lab::Measurement team; in detail:
1010              
1011             Copyright 2012 Andreas K. Huettel, Stefan Geissler
1012             2013 Alois Dirnaichner, Andreas K. Huettel, Christian Butschkow, Stefan Geissler
1013             2014 Christian Butschkow
1014             2016 Simon Reinhardt
1015             2017 Andreas K. Huettel
1016             2020 Andreas K. Huettel
1017              
1018              
1019             This is free software; you can redistribute it and/or modify it under
1020             the same terms as the Perl 5 programming language system itself.
1021              
1022             =cut