File Coverage

blib/lib/Lab/Instrument/Lakeshore340.pm
Criterion Covered Total %
statement 11 357 3.0
branch 0 236 0.0
condition 0 156 0.0
subroutine 4 35 11.4
pod 13 31 41.9
total 28 815 3.4


line stmt bran cond sub pod time code
1             package Lab::Instrument::Lakeshore340;
2             $Lab::Instrument::Lakeshore340::VERSION = '3.880';
3             #ABSTRACT: Lakeshore 340 temperature controller
4              
5 1     1   1837 use v5.20;
  1         4  
6              
7 1     1   5 use warnings;
  1         16  
  1         26  
8 1     1   7 use strict;
  1         2  
  1         19  
9              
10 1     1   5 use Lab::Instrument;
  1         2  
  1         5321  
11              
12             our @ISA = ('Lab::Instrument');
13              
14             our %fields = (
15             supported_connections => [ 'GPIB', 'VISA' ],
16              
17             # default settings for the supported connections
18             connection_settings => {
19             gpib_board => 0,
20             gpib_address => undef,
21             timeout => 1
22             },
23              
24             device_settings => {
25              
26             },
27              
28             device_cache => {
29             T => undef,
30             setpoint => undef,
31             range => undef,
32             },
33              
34             device_cache_order => [ 'function', 'range' ],
35             request => 0
36             );
37              
38             sub new {
39 0     0 1   my $proto = shift;
40 0   0       my $class = ref($proto) || $proto;
41 0           my $self = $class->SUPER::new(@_);
42 0           $self->${ \( __PACKAGE__ . '::_construct' ) }(__PACKAGE__);
  0            
43              
44 0           return $self;
45             }
46              
47             sub get_value {
48 0     0 0   my $self = shift;
49              
50 0           return $self->get_T(@_);
51             }
52              
53             sub get_T {
54              
55 0     0 1   my $self = shift;
56 0           my ( $channel, $tail ) = $self->_check_args( \@_, ['channel'] );
57              
58 0 0         if ( not defined $channel ) {
    0          
59 0           $channel = "A";
60             }
61             elsif ( not $channel =~ /\b(a|b|c|d)\b/i ) {
62 0           die
63             "unexpected value ($channel) for CHANNEL in sub get_T. Expected values are A or B.";
64             }
65              
66 0           return $self->query( "KRDG? $channel", $tail );
67             }
68              
69             sub set_T {
70 0     0 1   my $self = shift;
71 0           return $self->set_setpoint(@_);
72             }
73              
74             sub get_setpoint {
75              
76 0     0 0   my $self = shift;
77              
78 0           my ( $loop, $tail ) = $self->_check_args( \@_, ['loop'] );
79              
80 0 0 0       if ( not defined $loop ) {
    0          
81 0           $loop = 1;
82             }
83             elsif ( $loop != 1 and $loop != 2 ) {
84 0           die
85             "unexpected value ($loop) for LOOP in sub get_setpoint. Expected values are 1 or 2.";
86             }
87              
88 0           return $self->query("SETP? $loop");
89             }
90              
91             sub set_setpoint {
92 0     0 0   my $self = shift;
93              
94 0           my ( $setpoint, $loop, $tail )
95             = $self->_check_args( \@_, [ 'value', 'loop' ] );
96              
97 0 0 0       if ( not defined $loop ) {
    0          
98 0           $loop = 1;
99             }
100             elsif ( $loop != 1 and $loop != 2 ) {
101 0           die
102             "unexpected value ($loop) for LOOP in sub set_T. Expected values are 1 or 2.";
103             }
104              
105 0 0 0       if ( $setpoint < 0 or $setpoint > 300 ) {
106 0           die
107             "unexpected value ($setpoint) for SETPOINT in sub set_T. Expected values are between 0...300 K.";
108             }
109              
110             # Device bug. The 340 cannot parse values with too many digits.
111 0           $setpoint = sprintf( '%.6G', $setpoint );
112              
113 0           return $self->query( "SETP $loop,$setpoint; SETP? $loop", $tail );
114              
115             }
116              
117             sub set_range {
118 0     0 1   my $self = shift;
119 0           my $range = shift;
120              
121 0 0         if ( $range =~ /\b(OFF)\b/i ) {
    0          
    0          
    0          
    0          
    0          
122 0           $range = 0;
123             }
124             elsif ( $range =~ /\b(LOW)\b/i ) {
125 0           $range = 1;
126             }
127             elsif ( $range =~ /\b(MEDIUM|MED)\b/i ) {
128 0           $range = 2;
129             }
130             elsif ( $range =~ /\b(HIGH)\b/i ) {
131 0           $range = 3;
132             }
133             elsif ( $range =~ /\b(GIANT)\b/i ) {
134 0           $range = 4;
135             }
136             elsif ( $range =~ /\b(MAX)\b/i ) {
137 0           $range = 5;
138             }
139             else {
140 0           die
141             "unexpected value ($range) for RANGE in sub set_range. Expected values are OFF, LOW, MEDIUM, HIGH, GIANT, MAX.";
142             }
143              
144             # set range
145 0           return $self->query("RANGE $range; RANGE?");
146              
147             }
148              
149             sub get_range {
150 0     0 0   my $self = shift;
151 0           my ($tail) = $self->_check_args( \@_, [] );
152 0           my $range = $self->query( "RANGE?", $tail );
153              
154 0 0         if ( $range == 0 ) {
    0          
    0          
    0          
    0          
    0          
155 0           $range = 'OFF';
156             }
157             elsif ( $range == 1 ) {
158 0           $range = 'LOW';
159             }
160             elsif ( $range == 2 ) {
161 0           $range = 'MEDIUM';
162             }
163             elsif ( $range == 3 ) {
164 0           $range = 'HIGH';
165             }
166             elsif ( $range == 4 ) {
167 0           $range = 'GIANT';
168             }
169             elsif ( $range == 5 ) {
170 0           $range = 'MAX';
171             }
172             else {
173 0           die
174             "unexpected value ($range) for RANGE in sub get_range. Expected values are OFF, LOW, MEDIUM, HIGH, GIANT, MAX.";
175             }
176             }
177              
178       0 0   sub set_heatercontrol {
179              
180             }
181              
182             sub set_control_mode {
183              
184 0     0 0   my $self = shift;
185              
186 0           my ( $mode, $loop, $tail )
187             = $self->_check_args( \@_, [ 'value', 'loop' ] );
188              
189 0 0 0       if ( not defined $loop ) {
    0          
190 0           $loop = 1;
191             }
192             elsif ( $loop != 1 and $loop != 2 ) {
193 0           die
194             "unexpected value ($loop) for LOOP in sub set_control_mode. Expected values are 1 or 2.";
195             }
196              
197 0 0         if ( $mode =~ /\b(MANUAL|manual|MAN|man)\b/ ) {
    0          
    0          
    0          
    0          
    0          
198 0           $mode = 1;
199             }
200             elsif ( $mode =~ /\b(ZONE|zone)\b/ ) {
201 0           $mode = 2;
202             }
203             elsif ( $mode =~ /\b(OFF|off)\b/ ) {
204 0           $mode = 3;
205             }
206             elsif ( $mode =~ /\b(AUTO_PID|auto_pid)\b/ ) {
207 0           $mode = 4;
208             }
209             elsif ( $mode =~ /\b(AUTO_PI|auto_pi)\b/ ) {
210 0           $mode = 5;
211             }
212             elsif ( $mode =~ /\b(AUTO_P|auto_p)\b/ ) {
213 0           $mode = 6;
214             }
215             else {
216 0           die
217             "unexpected value ($mode) for CONTROL MODE in sub set_controlmode. Expected values are MANUAL, ZONE, AUTO_PID, AUTO_PI, AUTO_P and OFF.";
218             }
219              
220 0           return $self->query("CMODE $loop,$mode; CMODE? $loop");
221              
222             }
223              
224             sub get_control_mode {
225 0     0 0   my $self = shift;
226 0           my ( $loop, $tail ) = $self->_check_args( \@_, ['loop'] );
227              
228 0 0         if ( not defined $loop ) {
229 0           $loop = 1;
230             }
231              
232 0           return $self->query( "CMODE? $loop", $tail );
233             }
234              
235             sub get_R {
236              
237 0     0 1   my $self = shift;
238 0           my ( $channel, $tail ) = $self->_check_args( \@_, ['channel'] );
239              
240 0 0         if ( not defined $channel ) {
    0          
241 0           $channel = "A";
242             }
243             elsif ( not $channel =~ /\b(A|a|B|b)\b/ ) {
244 0           die
245             "unexpected value ($channel) for CHANNEL in sub get_R. Expected values are A or B.";
246             }
247              
248 0           return $self->query( "SRDG? $channel", $tail );
249             }
250              
251             sub set_control_loop {
252              
253 0     0 0   my $self = shift;
254              
255 0           my ( $channel, $loop, $units, $powerup, $display, $tail )
256             = $self->_check_args(
257             \@_,
258             [ 'channel', 'loop', 'units', 'powerup', 'display' ]
259             );
260              
261             # loop optinal parameter; Usually you alwas want to use control loop 1
262             # units optinal parameter; 1 == Kelvin, 2 == Celsius, 3 == sensor units
263             # powerup optinal parameter; 0 == power up enable off, 1 == power up enable on
264             # display optinal parameter; 1 == current, 2 == power
265              
266 0 0 0       if ( not defined $loop ) {
    0          
267 0           $loop = 1;
268             }
269             elsif ( $loop != 1 and $loop != 2 ) {
270 0           die
271             "unexpected value ($loop) for LOOP in sub set_control_loop. Expected values are 1 or 2.";
272             }
273              
274 0 0 0       if ( not defined $units ) {
    0 0        
    0          
    0          
    0          
275 0           $units = 1;
276             }
277             elsif ( $units =~ /\b(KELVIN|kelvin|K|k)\b/ ) {
278 0           $units = 1;
279             }
280             elsif ( $units =~ /\b(CELSIUS|celsius|C|c)\b/ ) {
281 0           $units = 2;
282             }
283             elsif ( $units =~ /\b(SENSOR|sensor|S|s)\b/ ) {
284 0           $units = 3;
285             }
286             elsif ( $units != 1 and $units != 2 and $units != 3 ) {
287 0           die
288             "unexpected value ($units) for UNITS in sub set_control_loop. Expected values are KELVIN, CELSIUS or SENSOR.";
289             }
290              
291 0 0 0       if ( not defined $powerup ) {
    0          
    0          
    0          
292 0           $powerup = 1;
293             }
294             elsif ( $powerup =~ /\b(ON|on)\b/ ) {
295 0           $powerup = 1;
296             }
297             elsif ( $powerup =~ /\b(OFF|off)\b/ ) {
298 0           $powerup = 0;
299             }
300             elsif ( $powerup != 0 and $powerup != 1 ) {
301 0           die
302             "unexpected value ($powerup) for POWERUP in sub set_control_loop. Expected values are ON or OFF.";
303             }
304              
305 0 0 0       if ( not defined $display ) {
    0          
    0          
    0          
306 0           $display = 2;
307             }
308             elsif ( $display =~ /\b(CURRENT|current)\b/ ) {
309 0           $display = 1;
310             }
311             elsif ( $display =~ /\b(POWER|power)\b/ ) {
312 0           $display = 2;
313             }
314             elsif ( $display != 1 and $display != 2 ) {
315 0           die
316             "unexpected value ($display) for DISPLAY in sub set_control_loop. Expected values are CURRENT or POWER.";
317             }
318              
319 0 0         if ( not $channel =~ /\b(A|a|B|b)\b/ ) {
320 0           die
321             "unexpected value ($channel) for CHANNEL in sub set_control_loop. Expected values are 'A' or 'B'.";
322             }
323              
324             # set control loop:
325 0           $loop = $self->query(
326             "CSET $loop, $channel, $units, $powerup, $display; CSET? $loop",
327             $tail
328             );
329              
330 0           my @loop = split( /, /, $loop );
331 0           return @loop;
332              
333             }
334              
335             sub get_control_loop {
336 0     0 0   my $self = shift;
337              
338 0           my ( $loop, $tail ) = $self->_check_args( \@_, ['loop'] );
339              
340 0 0 0       if ( not defined $loop ) {
    0          
341 0           $loop = 1;
342             }
343             elsif ( $loop != 1 and $loop != 2 ) {
344 0           die
345             "unexpected value ($loop) for LOOP in sub set_control_loop. Expected values are 1 or 2.";
346             }
347              
348 0           my $result = $self->query( "CSET? $loop", $tail );
349              
350 0           return split( /, /, $result );
351              
352             }
353              
354             sub set_input_curve {
355              
356 0     0 1   my $self = shift;
357              
358 0           my ( $channel, $curve, $tail )
359             = $self->_check_args( \@_, [ 'channel', 'curve' ] );
360              
361 0 0 0       if ( not defined $curve and not defined $channel ) {
    0 0        
    0          
362 0           die
363             "too fiew parameters given in sub set_input_curve. Expected parameters are CHANNEL and CURVE.";
364             }
365             elsif ( not $channel =~ /\b(A|a|B|b)\b/ ) {
366 0           die
367             "unexpected value ($channel) for CHANNEL in sub set_input_curve. Expected values are 'A' or 'B'.";
368             }
369             elsif ( $curve < 0 and $curve > 41 ) {
370 0           die
371             "unexpected value ($curve) for CURVE in sub set_input_curve. Expected values are between 0 ... 41.";
372             }
373 0           return $self->query("INCRV $channel,$curve; INCRV? $channel");
374             }
375              
376             sub get_input_curve {
377 0     0 0   my $self = shift;
378 0           my ( $channel, $tail ) = $self->_check_args( \@_, ['channel'] );
379              
380 0 0         if ( not $channel =~ /\b(A|a|B|b)\b/ ) {
381 0           die
382             "unexpected value ($channel) for CHANNEL in sub set_input_curve. Expected values are 'A' or 'B'.";
383             }
384              
385 0           return $self->query( "INCRV? $channel", $tail );
386             }
387              
388             sub set_remote {
389 0     0 0   my $self = shift;
390              
391 0           my ( $mode, $tail ) = $self->_check_args( \@_, ['mode'] );
392              
393 0 0         if ( not defined $mode ) {
    0          
    0          
    0          
394              
395             }
396             elsif ( $mode =~ /\b(LOCAL|local)\b/ ) {
397 0           $mode = 0;
398             }
399             elsif ( $mode =~ /\b(REMOTE|remote)\b/ ) {
400 0           $mode = 1;
401             }
402             elsif ( $mode =~ /\b(LOCK|lock)\b/ ) {
403 0           $mode = 2;
404             }
405             else {
406 0           die
407             "unexpected value ($mode) for MODE in sub set_remote. Expected values are between LOCAL, REMOTE and LOCK.";
408             }
409              
410 0           $mode = $self->query("MODE $mode; MODE?");
411              
412 0 0         if ( $mode == 0 ) {
    0          
    0          
413 0           $mode = "LOCAL";
414             }
415             elsif ( $mode == 1 ) {
416 0           $mode = "REMOTE";
417             }
418             elsif ( $mode == 2 ) {
419 0           $mode = "LOCK";
420             }
421              
422 0           return $mode;
423             }
424              
425             sub get_remote {
426 0     0 0   my $self = shift;
427              
428 0           my ($tail) = $self->_check_args( \@_, [] );
429              
430 0           my $mode = $self->query( "MODE?", $tail );
431              
432 0 0         if ( $mode == 0 ) {
    0          
    0          
433 0           $mode = "LOCAL";
434             }
435             elsif ( $mode == 1 ) {
436 0           $mode = "REMOTE";
437             }
438             elsif ( $mode == 2 ) {
439 0           $mode = "LOCK";
440             }
441              
442 0           return $mode;
443             }
444              
445             # Bin bis hier her gekommen
446              
447             sub set_PID {
448 0     0 1   my $self = shift;
449 0           my $P = shift;
450 0           my $I = shift;
451 0           my $D = shift;
452 0           my $loop = shift
453             ; # optinal parameter; Usually you alwas want to use control loop 1
454              
455 0 0 0       if ( not defined $loop
    0 0        
    0 0        
    0 0        
    0 0        
      0        
456             and not defined $D
457             and not defined $I
458             and not defined $P ) {
459 0           $loop = 1;
460 0           my $PID = $self->query("PID $loop, $P, $I, $D; PID?");
461 0           chomp $PID;
462 0           chomp $PID;
463 0           my @PID = split( /, /, $PID );
464              
465 0           return @PID;
466             }
467             elsif ( not defined $loop
468             and not defined $D
469             and not defined $I
470             and ( $P == 1 or $P == 2 ) ) {
471 0           $loop = $P;
472 0           my $PID = $self->query("PID $loop, $P, $I, $D; PID?");
473 0           chomp $PID;
474 0           chomp $PID;
475 0           my @PID = split( /, /, $PID );
476              
477 0           return @PID;
478             }
479             elsif ( not defined $loop and not defined $D ) {
480 0           die
481             "too fiew parameters given in sub set_PID. Expected parameters are P, I, D.";
482             }
483             elsif ( not defined $loop ) {
484 0           $loop = 1;
485             }
486             elsif ( $loop != 1 and $loop != 2 ) {
487 0           die
488             "unexpected value ($loop) for LOOP in sub set_PID. Expected values are between 1 and 2.";
489             }
490              
491             # else {
492             # die "unexpected values in sub set_PID.";
493             # }
494              
495 0 0 0       if ( $D < 0 or $D > 200 ) {
    0 0        
    0 0        
496 0           die
497             "unexpected value ($D) for D in sub set_PID. Expected values are between 0 and 200.";
498             }
499             elsif ( $I < 0.1 or $I > 1000 ) {
500 0           die
501             "unexpected value ($I) for I in sub set_PID. Expected values are between 0.1 and 1000.";
502             }
503             elsif ( $P < 0.1 or $P > 1000 ) {
504 0           die
505             "unexpected value ($P) for P in sub set_PID. Expected values are between 0.1 and 1000.";
506             }
507             else {
508 0           my $PID = $self->query("PID $loop, $P, $I, $D; PID? $loop");
509 0           chomp $PID;
510 0           chomp $PID;
511 0           my @PID = split( /, /, $PID );
512              
513 0           return @PID;
514             }
515              
516             }
517              
518             sub set_zone {
519              
520 0     0 0   my $self = shift;
521 0           my $zone = shift;
522 0           my $t_limit = shift;
523 0           my $P = shift;
524 0           my $I = shift;
525 0           my $D = shift;
526 0           my $range = shift;
527 0           my $man_output = shift; # optional parameter, usually zero
528 0           my $loop = shift
529             ; # optinal parameter; Usually you alwas want to use control loop 1
530              
531 0 0 0       if ( defined $zone and ( $zone < 1 or $zone > 10 ) ) {
      0        
532 0           die
533             "unexpected value ($zone) for ZONE in sub set_zone. Expected values are all integer values from 1 to 10.";
534             }
535              
536 0 0 0       if ( not defined $loop ) {
    0          
537 0           $loop = 1;
538             }
539             elsif ( $loop != 1 and $loop != 2 ) {
540 0           die
541             "unexpected value ($loop) for LOOP in sub set_zone. Expected values are 1 or 2.";
542             }
543              
544 0 0 0       if ( not defined $man_output ) {
    0          
545 0           $man_output = 0;
546             }
547             elsif ( $man_output < 0 or $man_output > 100 ) {
548 0           die
549             "unexpected value ($man_output) for MANUAL OUTPUT in sub set_zone. Expected values are between 0 ... 100 %.";
550             }
551              
552 0 0 0       if ( not defined $range
      0        
      0        
      0        
553             and not defined $D
554             and not defined $I
555             and not defined $P
556             and not defined $t_limit ) {
557 0           return;
558             }
559              
560 0 0         if ( not defined $range ) {
561 0           die
562             "too fiew parameters given for sub set_zone. Expected parameters are ZONE, T_LIMIT, P, I, D, RANGE and optional <MAN_OUTPUT> and <LOOP>.";
563             }
564              
565 0 0 0       if ( $t_limit < 0 or $t_limit > 300 ) {
    0 0        
    0 0        
    0 0        
566 0           die
567             "unexpected value ($t_limit) for T_LIMIT in sub set_zone. Expected values are between 0 and 300 K.";
568             }
569             elsif ( $D < 0 or $D > 200 ) {
570 0           die
571             "unexpected value ($D) for D in sub set_zone. Expected values are between 0 and 200.";
572             }
573             elsif ( $I < 0.1 or $I > 1000 ) {
574 0           die
575             "unexpected value ($I) for I in sub set_zone. Expected values are between 0.1 and 1000.";
576             }
577             elsif ( $P < 0.1 or $P > 1000 ) {
578 0           die
579             "unexpected value ($P) for P in sub set_zone. Expected values are between 0.1 and 1000.";
580             }
581              
582 0 0         if ( $range =~ /\b(OFF|off)\b/ ) {
    0          
    0          
    0          
583 0           $range = 0;
584             }
585             elsif ( $range =~ /\b(LOW|low)\b/ ) {
586 0           $range = 1;
587             }
588             elsif ( $range =~ /\b(MEDIUM|medium|MED|med)\b/ ) {
589 0           $range = 2;
590             }
591             elsif ( $range =~ /\b(HIGH|high)\b/ ) {
592 0           $range = 3;
593             }
594             else {
595 0           die
596             "unexpected value ($range) for RANGE in sub set_zone. Expected values are OFF, LOW, MEDIUM, HIGH.";
597             }
598              
599             # set zone:
600 0           $zone
601             = $self->query(
602             "ZONE $loop, $zone, $t_limit, $P, $I, $D, $man_output, $range; ZONE?"
603             );
604 0           chomp $zone;
605 0           chomp $zone;
606 0           my @zone = split( /, /, $zone );
607 0           return @zone;
608              
609             }
610              
611             sub set_heateroutput {
612              
613 0     0 0   my $self = shift;
614 0           my $output = shift;
615 0           my $loop = shift
616             ; # optinal parameter; Usually you alwas want to use control loop 1
617              
618 0 0 0       if ( not defined $loop ) {
    0          
619 0           $loop = 1;
620             }
621             elsif ( $loop != 1 and $loop != 2 ) {
622 0           die
623             "unexpected value ($loop) for LOOP in sub set_heater_output. Expected values are 1 or 2.";
624             }
625              
626 0 0 0       if ( not defined $output ) {
    0          
627 0           $output = $self->query("Mout? $loop");
628 0           chomp $output;
629 0           chomp $output;
630 0           return $output;
631             }
632             elsif ( $output >= 0 and $output <= 100 ) {
633 0           $output = $self->query("MOUT $loop, $output; Mout? $loop");
634 0           chomp $output;
635 0           chomp $output;
636 0           return $output;
637             }
638             else {
639 0           die
640             "unexpected value ($output) for OUTPUT in sub set_heater_output. Expected values are between 0 ... 100 % of full heater range.";
641             }
642              
643             }
644              
645             sub set_input_sensor {
646              
647 0     0 0   my $self = shift;
648 0           my $channel = shift;
649 0           my $sensor_type = shift;
650 0           my $compensation = shift;
651              
652             # check input parameter:
653              
654 0 0         if ( not defined $channel ) {
    0          
655 0           $channel = $self->query(
656             "INTYPE $channel, $sensor_type, $compensation; INTYPE? $channel");
657 0           chomp $channel;
658 0           chomp $channel;
659 0           my @channel = split( /, /, $channel );
660 0           return @channel;
661             }
662             elsif ( not $channel =~ /\b(A|a|B|b)\b/ ) {
663 0           die
664             "unexpected value ($channel) for CHANNEL in sub set_input_sensor. Expected values are 'A' or 'B'.";
665             }
666              
667 0 0 0       if ( not defined $sensor_type ) {
    0          
668              
669             # 0 = Silicon Diode
670             # 1 = GaAlAs Diode
671             # 2 = Platinum 100/250 O
672             # 3 = Platinum 100/500 O
673             # 4 = Platinum 1000 O
674             # 5 = NTC RTD 75mV 7.5 kO
675             # 6 = Thermocouple 25 mV
676             # 7 = Thermocouple 50 mV
677             # 8 = NTC RTD 75mV 75 O
678             # 9 = NTC RTD 75mV 750 O
679             # 10 = NTC RTD 75mV 7.5 kO
680             # 11 = NTC RTD 75mV 75 kO
681             # 12 = NTC RTD 75mV Auto
682              
683 0           $sensor_type = 12;
684              
685             }
686             elsif ( not( $sensor_type >= 1 and $sensor_type <= 12 ) ) {
687 0           die
688             "unexpected value ($sensor_type) for SENSOR_TYPE in sub set_input_sensor. Expected values are all integervalues between 0 ... 12.";
689             }
690              
691 0 0 0       if ( not defined $compensation ) {
    0          
    0          
    0          
692 0           $compensation = 0; # 0 == OFF, 1 == ON
693             }
694             elsif ( $compensation =~ /\b(ON|on)\b/ ) {
695 0           $compensation = 1;
696             }
697             elsif ( $compensation =~ /\b(OFF|off)\b/ ) {
698 0           $compensation = 0;
699             }
700             elsif ( $compensation != 0 and $compensation != 1 ) {
701 0           die
702             "unexpected value ($compensation) for COMPENSATION in sub set_input_sensor. Expected values are ON or OFF.";
703             }
704              
705             # set input sensor:
706              
707 0           $channel = $self->query(
708             "INTYPE $channel, $sensor_type, $compensation; INTYPE? $channel");
709 0           chomp $channel;
710 0           chomp $channel;
711 0           my @channel = split( /, /, $channel );
712 0           return @channel;
713              
714             }
715              
716             sub set_filter {
717              
718 0     0 0   my $self = shift;
719 0           my $channel = shift;
720 0           my $points = shift;
721 0           my $window = shift;
722              
723 0           my $active = 1; # set the filter active after changing parameters
724              
725             # check input paramters:
726 0 0 0       if ( defined $channel and not $channel =~ /\b(A|a|B|b)\b/ ) {
727 0           die
728             "unexpected value ($channel) for CHANNEL in sub set_filter. Expected values are between 'A' and 'B'.";
729             }
730              
731 0 0 0       if ( not defined $window
    0 0        
    0 0        
    0          
732             and not defined $points
733             and not defined $channel ) {
734 0           die
735             "too fiew parameters given. Expected parameters are CHANNEL, POINTS, <WINDOW>";
736             }
737             elsif ( not defined $window and not defined $points ) {
738 0           my $filter = $self->query("FILTER? $channel");
739 0           chomp $filter;
740 0           chomp $filter;
741              
742 0           my @filter = split( /, /, $filter );
743              
744 0 0         if ( $filter[0] == 0 ) {
745 0           $filter[0] = 'OFF';
746             }
747             else {
748 0           $filter[0] = 'ON';
749             }
750              
751 0           return @filter;
752              
753             }
754             elsif ( not defined $window ) {
755 0           $window = 1;
756             }
757             elsif ( $window < 1 or $window > 10 ) {
758 0           die
759             "unexpected value ($window) for WINDOW in sub set_filter. Expected values are between 1 .. 10 % of full scale reading limits.";
760             }
761              
762 0 0         if ( $points =~ /\b(OFF|off)\b/ ) {
763 0           my $filter = $self->query("FILTER? $channel");
764 0           chomp $filter;
765 0           chomp $filter;
766 0           my @filter = split( /, /, $filter );
767              
768 0           $active = 0;
769 0           $points = $filter[1];
770 0           $window = $filter[2];
771              
772             }
773 0 0 0       if ( $points < 2 or $points > 64 ) {
774 0           die
775             "unexpected value ($points) for POINTS in sub set_filter. Expected values are between 2 .. 64.";
776             }
777              
778             # set filter paramters:
779              
780 0           my $filter = $self->query(
781             "FILTER $channel,$active,$points,$window; FILTER? $channel");
782 0           chomp $filter;
783 0           chomp $filter;
784 0           my @filter = split( /, /, $filter );
785              
786 0 0         if ( $filter[0] == 0 ) {
787 0           $filter[0] = 'OFF';
788             }
789             else {
790 0           $filter[0] = 'ON';
791             }
792              
793 0           return @filter;
794              
795             }
796              
797             sub config_sweep {
798 0     0 1   my $self = shift;
799 0           my $setpoint = shift;
800 0           my $rate = shift;
801 0           my $loop = shift
802             ; # optinal parameter; Usually you alwas want to use control loop 1
803              
804 0 0 0       if ( not defined $loop ) {
    0          
805 0           $loop = 1;
806             }
807             elsif ( $loop != 1 and $loop != 2 ) {
808 0           die
809             "unexpected value ($loop) for LOOP in sub config_sweep. Expected values are 1 or 2.";
810             }
811              
812 0 0 0       if ( not defined $rate or $rate < 0.1 or $rate > 100 ) {
    0 0        
      0        
      0        
813 0           die
814             "unexpected value ($rate) for RATE in sub config_sweep. Expected values are between 0...100 K/min.";
815             }
816             elsif ( not defined $setpoint or $setpoint < 0 or $setpoint > 300 ) {
817 0           die
818             "unexpected value ($setpoint) for SETPOINT in sub config_sweep. Expected values are between 0...300 K.";
819             }
820              
821 0           $rate = $self->query("RAMP $loop,0,$rate; RAMP? $loop");
822 0           $setpoint = $self->query("SETP $loop,$setpoint; SETP? $loop");
823              
824 0           return $setpoint, $rate;
825              
826             }
827              
828             sub trg {
829 0     0 1   my $self = shift;
830 0           my $loop = shift
831             ; # optinal parameter; Usually you alwas want to use control loop 1
832              
833 0 0 0       if ( not defined $loop ) {
    0          
834 0           $loop = 1;
835             }
836             elsif ( $loop != 1 and $loop != 2 ) {
837 0           die
838             "unexpected value ($loop) for LOOP in sub trg. Expected values are 1 or 2.";
839             }
840              
841 0           my $rate = $self->query("RAMP? $loop");
842 0           $rate = $self->write("RAMP $loop,1,$rate");
843              
844 0           return 1;
845              
846             }
847              
848             sub halt {
849              
850 0     0 1   my $self = shift;
851 0           my $loop = shift
852             ; # optinal parameter; Usually you alwas want to use control loop 1
853              
854 0 0 0       if ( not defined $loop ) {
    0          
855 0           $loop = 1;
856             }
857             elsif ( $loop != 1 and $loop != 2 ) {
858 0           die
859             "unexpected value ($loop) for LOOP in sub halt. Expected values are 1 or 2.";
860             }
861              
862 0           my $rate = $self->query("RAMP? $loop");
863 0           $rate = $self->write("RAMP $loop,0,$rate");
864              
865             # get control loop channel
866 0           my @channel = $self->set_control_loop();
867 0           my $channel = $channel[0];
868              
869             # get current temperature
870 0           my $temperature_now = $self->get_T($channel);
871 0           $self->set_T($temperature_now);
872              
873             # stop sweeping
874 0           $rate = $self->write("RAMP $loop,0,0.1");
875              
876 0           return 1;
877             }
878              
879             sub active {
880              
881 0     0 1   my $self = shift;
882 0           my $loop = shift
883             ; # optinal parameter; Usually you alwas want to use control loop 1
884              
885 0 0 0       if ( not defined $loop ) {
    0          
886 0           $loop = 1;
887             }
888             elsif ( $loop != 1 and $loop != 2 ) {
889 0           die
890             "unexpected value ($loop) for LOOP in sub active. Expected values are 1 or 2.";
891             }
892              
893 0           my $status = $self->query('RAMPST? $loop');
894 0           chomp $status;
895 0           chomp $status;
896 0           return $status;
897             }
898              
899             sub wait {
900              
901 0     0 1   my $self = shift;
902 0           my $loop = shift
903             ; # optinal parameter; Usually you alwas want to use control loop 1
904              
905 0 0 0       if ( not defined $loop ) {
    0          
906 0           $loop = 1;
907             }
908             elsif ( $loop != 1 and $loop != 2 ) {
909 0           die
910             "unexpected value ($loop) for LOOP in sub active. Expected values are 1 or 2.";
911             }
912              
913 0           print "waiting for the temperature sweep to end.";
914 0           while ( $self->active() ) {
915 0           print $self->get_T('A') . ", " . $self->get_T('B') . "\n";
916             }
917              
918 0           return;
919              
920             }
921              
922             sub id {
923 0     0 1   my $self = shift;
924 0           $self->query('*IDN?');
925             }
926              
927             sub reset {
928              
929 0     0 0   my $self = shift;
930 0           $self->write("*RST");
931              
932             }
933              
934             sub factory_reset {
935              
936 0     0 0   my $self = shift;
937 0           $self->write("DFLT 99");
938              
939             }
940              
941             1;
942              
943             __END__
944              
945             =pod
946              
947             =encoding UTF-8
948              
949             =head1 NAME
950              
951             Lab::Instrument::Lakeshore340 - Lakeshore 340 temperature controller
952              
953             =head1 VERSION
954              
955             version 3.880
956              
957             =head1 SYNOPSIS
958              
959             use Lab::Measurement;
960             my $lake = Instrument('Lakeshore340', {
961             connection_type => ...,
962             gpib_address => ...
963             });
964            
965             my $temp = $lake->get_T({channel => 'C'});
966            
967             $lake->set_T({value => 5.5, loop => 1});
968              
969             =head1 DESCRIPTION
970              
971             The Lab::Instrument::Lakeshore340 class implements an interface to the
972             Lakeshore 340 AC Resistance Bridge.
973              
974             For use in XPRESS temperature sweeps, see the example script
975             F<examples/XPRESS/lakeshore340_sweep.pl>.
976              
977             =head1 METHODS
978              
979             =head2 get_T
980              
981             $t = $lake->get_T(<$channel>);
982              
983             Reads temperature in Kelvin (only possible if temperature curve is available, otherwise returns zero).
984              
985             =over 4
986              
987             =item $channel
988              
989             CHANNEL is an optinal parameter to select the sensor channel (A/B/C/D) for the measurement.
990             If not defined the default channel 'A' will be selected.
991              
992             =back
993              
994             =head2 get_R
995              
996             $t = $lake->get_R(<$channel>);
997              
998             Reads resistance in Ohm.
999              
1000             =over 4
1001              
1002             =item $channel
1003              
1004             CHANNEL is an optinal parameter to select the sensor channel (A/B/C/D) for the measurement.
1005             If not defined the default channel 'A' will be selected.
1006              
1007             =back
1008              
1009             =head2 set_T
1010              
1011             $sp = $lake->set_T($setpoint, <$loop>);
1012              
1013             Set new temperature SETPOINT for temperature control loop $loop. Returns the new setpoint.
1014             If no parameters are given, the currently valid SETPOINT will be returned.
1015              
1016             =over 4
1017              
1018             =item $setpoint
1019              
1020             New temperature Setpoint.
1021              
1022             =item $loop
1023              
1024             Optional prameter to select the temperature control loop for which the new setting will be valid.
1025             If not defined the default value $loop = 1 will be selected.
1026             Possible values are '1' and '2'.
1027              
1028             =back
1029              
1030             .
1031              
1032             =head2 set_range
1033              
1034             $heater_range = $lake->set_range($range);
1035              
1036             Set the HEATER RANGE.
1037              
1038             =over 4
1039              
1040             =item $range
1041              
1042             RANGE can be 'OFF', 'LOW', 'MEDIUM', 'HIGH', 'GIANT' or 'MAX'.
1043              
1044             =back
1045              
1046             .
1047              
1048             =head2 set_input_curve
1049              
1050             $lake->set_input_curve($channel, $curve);
1051              
1052             Set for SENSOR CHANNEL $channel the resistance-to-temperatur CURVE with the internal storage number $curve.
1053              
1054             =over 4
1055              
1056             =item $channel
1057              
1058             CHANNEL selects the SENSOR CHANNEL and can be 'A' or 'B'.
1059              
1060             =item $curve
1061              
1062             CURVE reverse to one ov the internally stored resistance-to-temperatur CURVES and can be 0 .. 41.
1063              
1064             =back
1065              
1066             .
1067              
1068             =head2 set_PID
1069              
1070             @PID = $lake->set_PID($P,$I,$D);
1071              
1072             Set new values for the PID temperature control circuit.
1073              
1074             =over 4
1075              
1076             =item $P
1077              
1078             The PROPORTIONAL term, also called gain must have a value greater then zero for the control loop to operate. It's maximum value is 1000.
1079              
1080             =item $I
1081              
1082             The INTEGRAL term looks at error over time to build the integral contribution to the output. Values are 0.1 ... 1000.
1083              
1084             =item $D
1085              
1086             The DERIVATIVE term acts aon the change in error with time to make its contribution to the output. Values: 0 ... 200.
1087              
1088             =back
1089              
1090             .
1091              
1092             =head2 config_sweep
1093              
1094             $lake->config_sweep($setpoint, $rate);
1095              
1096             Predefine a temperature sweep.
1097              
1098             =over 4
1099              
1100             =item $setpoint
1101              
1102             Predefine the temperature target setpoint for a temperatue sweep. Values 0 .. 300 K.
1103              
1104             =item $rate
1105              
1106             Predefine sweep rate for a temperature sweep. Values 0.1 ... 100 K/minute.
1107              
1108             =back
1109              
1110             .
1111              
1112             =head2 trg
1113              
1114             $lake->trg();
1115              
1116             Start a predefined temperature sweep.
1117              
1118             =head2 halt
1119              
1120             $lake->halt();
1121              
1122             Stop running temperature sweep.
1123              
1124             =head2 active
1125              
1126             $lake->active();
1127              
1128             Returns 1 if a temperature sweep is running and 0 if not.
1129              
1130             =head2 wait
1131              
1132             $lake->wait();
1133              
1134             Wait until the currently active temperature sweep has been finished.
1135              
1136             =head2 id
1137              
1138             $id=$sr780->id();
1139              
1140             Returns the instruments ID string.
1141              
1142             .
1143              
1144             =head1 CAVEATS/BUGS
1145              
1146             probably many
1147              
1148             .
1149              
1150             =head1 SEE ALSO
1151              
1152             =over 4
1153              
1154             =item Lab::Instrument
1155              
1156             =back
1157              
1158             =head1 COPYRIGHT AND LICENSE
1159              
1160             This software is copyright (c) 2023 by the Lab::Measurement team; in detail:
1161              
1162             Copyright 2013-2014 Christian Butschkow
1163             2016 Simon Reinhardt
1164             2017 Andreas K. Huettel, Simon Reinhardt
1165             2019 Simon Reinhardt
1166             2020 Andreas K. Huettel
1167              
1168              
1169             This is free software; you can redistribute it and/or modify it under
1170             the same terms as the Perl 5 programming language system itself.
1171              
1172             =cut