File Coverage

blib/lib/Lab/Moose/Instrument/ABB_TRMC2.pm
Criterion Covered Total %
statement 14 175 8.0
branch 0 36 0.0
condition 0 18 0.0
subroutine 5 28 17.8
pod 23 23 100.0
total 42 280 15.0


line stmt bran cond sub pod time code
1             package Lab::Moose::Instrument::ABB_TRMC2;
2             $Lab::Moose::Instrument::ABB_TRMC2::VERSION = '3.881';
3             #ABSTRACT: ABB TRMC2 temperature controller
4              
5 1     1   5182 use v5.20;
  1         5  
6              
7 1     1   7 use Moose;
  1         2  
  1         10  
8 1         69 use Lab::Moose::Instrument qw/
9 1     1   7336 validated_getter validated_setter setter_params /;
  1         3  
10 1     1   7 use Lab::Moose::Instrument::Cache;
  1         3  
  1         11  
11 1     1   692 use Carp;
  1         3  
  1         2285  
12              
13             carp "The ABB_TRMC2 driver is untested so far. Feedback welcome...";
14              
15             extends 'Lab::Moose::Instrument';
16              
17             has max_setpoint => (
18             is => 'ro',
19             isa => 'Lab::Moose::PosNum',
20             default => 1
21             );
22              
23             has min_setpoint => (
24             is => 'ro',
25             isa => 'Lab::Moose::PosNum',
26             default => 0.02
27             );
28              
29             has read_delay => (
30             is => 'ro',
31             isa => 'Num',
32             default => 0.3
33             );
34              
35             has buffin => (
36             is => 'ro',
37             isa => 'Str',
38             default => 'C:\Program Files\Trmc2\buffin.txt'
39             );
40              
41             has buffout => (
42             is => 'ro',
43             isa => 'Str',
44             default => 'C:\Program Files\Trmc2\buffout.txt'
45             );
46              
47             has initialized => (
48             is => 'rw',
49             isa => 'Bool',
50             default => 0
51             );
52              
53              
54             sub set_T {
55 0     0 1   my ( $self, $value, %args ) = validated_setter( \@_ );
56              
57 0           $self->TRMC2_set_SetPoint($value);
58              
59             # what do we need to return here?
60             #return TRMC2_set_SetPoint(@_);
61             }
62              
63              
64             sub get_T {
65 0     0 1   my ( $self, %args ) = validated_getter( \@_ );
66 0           return $self->TRMC2_get_T(5);
67             }
68              
69              
70             sub TRMC2init {
71 0     0 1   my $self = shift;
72 0 0         if ( $self->initialized ) { die "TRMC already Initialized\n" }
  0            
73              
74 0 0         if ( !open FHIN, "<", $self->buffin ) { ## no critic
75 0           die "could not open command file " . $self->buffin . ": $!\n";
76             }
77 0           close(FHIN);
78 0 0         if ( !open FHOUT, "<", $self->buffout ) { ## no critic
79 0           die "could not open reply file " . $self->buffout . ": $!\n";
80             }
81 0           close(FHOUT);
82              
83 0           $self->initialized(1);
84             }
85              
86              
87             sub TRMC2off {
88 0     0 1   my $self = shift;
89 0           $self->initialized(0);
90             }
91              
92              
93             sub TRMC2_Heater_Control_On {
94 0     0 1   my $self = shift;
95 0           my $state = shift;
96              
97 0 0 0       if ( $state != 0 && $state != 1 ) {
98 0           die
99             "TRMC heater control can be turned off or on by 0 and 1 not by $state\n";
100             }
101 0           my $cmd = sprintf( "MAIN:ON=%d\0", $state );
102 0           $self->TRMC2_Write( $cmd, 0.3 );
103             }
104              
105              
106             sub TRMC2_Prog_On {
107 0     0 1   my $self = shift;
108 0           my $state = shift;
109              
110 0 0 0       if ( $state != 0 && $state != 1 ) {
111 0           die "TRMC Program can be turned off or on by 0 and 1 not by $state\n";
112             }
113              
114 0           my $cmd = sprintf( "MAIN:PROG=%d\0", $state );
115 0           $self->TRMC2_Write( $cmd, 1.0 );
116             }
117              
118              
119             sub TRMC2_get_SetPoint {
120 0     0 1   my $self = shift;
121              
122 0           my $cmd = "MAIN:SP?";
123 0           my @value = $self->TRMC2_Query( $cmd, 0.1 );
124              
125 0           foreach my $val (@value) {
126 0           chomp $val;
127 0           $val = RemoveFrenchComma($val);
128             }
129              
130 0           return $value[0];
131             }
132              
133              
134             sub TRMC2_set_SetPoint {
135 0     0 1   my $self = shift;
136 0           my $setpoint = shift;
137              
138 0 0         if ( $setpoint > $self->max_setpoint ) {
139 0           croak
140             "setting temperatures above $self->max_setpoint K is forbidden\n";
141             }
142 0 0         if ( $setpoint < $self->min_setpoint ) {
143 0           croak
144             "setting temperatures below $self->max_setpoint K is forbidden\n";
145             }
146              
147 0           my $FrSetpoint = MakeFrenchComma( sprintf( "%.6E", $setpoint ) );
148              
149 0           my $cmd = "MAIN:SP=$FrSetpoint";
150 0           $self->TRMC2_Write( $cmd, 0.2 );
151             }
152              
153              
154             sub TRMC2_get_PV {
155 0     0 1   my $self = shift;
156              
157 0           my $cmd = "MAIN:PV?";
158 0           my @value = $self->TRMC2_Query( $cmd, 0.2 );
159              
160 0           foreach my $val (@value) {
161 0           chomp $val;
162 0           $val = RemoveFrenchComma($val);
163             }
164 0           return $value[0];
165             }
166              
167              
168             sub TRMC2_AllMeas {
169 0     0 1   my $self = shift;
170              
171 0           my $cmd = "ALLMEAS?";
172 0           my @value = $self->TRMC2_Query( $cmd, 0.2 );
173              
174 0           foreach my $val (@value) {
175 0           chomp $val;
176 0           $val = RemoveFrenchComma($val);
177             }
178              
179 0           return @value;
180             }
181              
182              
183             sub TRMC2_get_T {
184 0     0 1   my $self = shift;
185 0           my $sensor = shift;
186              
187 0 0 0       if ( $sensor < 0 || $sensor > 6 ) {
188 0           die "Sensor# $sensor not available\n";
189             }
190              
191 0           my @value = $self->TRMC2_AllMeas();
192              
193 0           my @sensorval = split( /;/, $value[$sensor] );
194 0           my $T = $sensorval[1];
195 0           return $T;
196             }
197              
198              
199             sub TRMC2_get_R {
200 0     0 1   my $self = shift;
201 0           my $sensor = shift;
202              
203 0 0 0       if ( $sensor < 0 || $sensor > 6 ) {
204 0           die "Sensor# $sensor not available\n";
205             }
206              
207 0           my @value = $self->TRMC2_AllMeas();
208              
209 0           my @sensorval = split( /;/, $value[$sensor] );
210 0           my $R = $sensorval[0];
211 0           return $R;
212             }
213              
214              
215             sub TRMC2_get_RT {
216 0     0 1   my $self = shift;
217 0           my $sensor = shift;
218              
219 0 0 0       if ( $sensor < 0 || $sensor > 6 ) {
220 0           die "Sensor# $sensor not available\n";
221             }
222              
223 0           my @value = $self->TRMC2_AllMeas();
224              
225 0           my @sensorval = split( /;/, $value[$sensor] );
226 0           my $R = $sensorval[0];
227 0           my $T = $sensorval[1];
228 0           return ( $R, $T );
229             }
230              
231              
232             sub TRMC2_Read_Prog {
233 0     0 1   my $self = shift;
234              
235 0           my $cmd = "MAIN:PROG_Table?\0";
236 0           my @value = $self->TRMC2_Query( $cmd, 0.2 );
237              
238 0           foreach my $val (@value) {
239 0           chomp $val;
240 0           $val = RemoveFrenchComma($val);
241             }
242 0           return @value;
243             }
244              
245              
246             sub TRMC2_Set_T_Sweep {
247 0     0 1   my $arg_cnt = @_;
248              
249 0           my $self = shift;
250 0           my $Setpoint = shift; #K
251 0           my $Sweeprate = shift; #K/min
252 0           my $Holdtime = 0.; #sec.
253 0 0         if ( $arg_cnt == 4 ) { $Holdtime = shift }
  0            
254 0           my $FrSetpoint = MakeFrenchComma( sprintf( "%.6E", $Setpoint ) );
255 0           my $FrSweeprate = MakeFrenchComma( sprintf( "%.6E", $Sweeprate ) );
256 0           my $FrHoldtime = MakeFrenchComma( sprintf( "%.6E", $Holdtime ) );
257              
258 0           my $cmd = "MAIN:PROG_Table=1\0";
259 0           $self->TRMC2_Write( $cmd, 0.5 );
260              
261 0           $cmd = sprintf(
262             "PROG_TABLE(%d)=%s;%s;%s\n",
263             0, $FrSetpoint, $FrSweeprate, $FrHoldtime
264             );
265 0           $self->TRMC2_Write( $cmd, 0.5 );
266             }
267              
268              
269             sub TRMC2_Start_Sweep {
270 0     0 1   my $self = shift;
271 0           my $state = shift;
272              
273 0 0 0       if ( $state != 0 && $state != 1 ) {
274 0           die "Sweep can be turned off or on by 0 and 1 not by $state\n";
275             }
276 0 0         if ( $state == 1 ) { $self->TRMC2_Heater_Control_On($state); }
  0            
277 0           $self->TRMC2_Prog_On($state);
278             }
279              
280              
281             sub TRMC2_All_Channels {
282 0     0 1   my $self = shift;
283              
284 0           my $cmd = "*CHANNEL";
285 0           my @value = $self->TRMC2_Query( $cmd, 0.1 );
286 0           foreach my $val (@value) {
287 0           chomp $val;
288 0           $val = RemoveFrenchComma($val);
289             }
290 0           return @value;
291             }
292              
293              
294             sub TRMC2_Active_Channel {
295 0     0 1   my $self = shift;
296              
297 0           my $cmd = "CHANNEL?";
298 0           my @value = $self->TRMC2_Query( $cmd, $self->read_delay );
299 0           foreach my $val (@value) {
300 0           chomp $val;
301 0           $val = RemoveFrenchComma($val);
302             }
303 0           return @value;
304             }
305              
306              
307             sub TRMC2_Shut_Down {
308 0     0 1   my $self = shift;
309              
310 0           $self->TRMC2_Start_Sweep(0);
311 0           $self->TRMC2_Heater_Control_On(0);
312             }
313              
314              
315             sub TRMC2_Write {
316 0     0 1   my $self = shift;
317              
318 0           my $arg_cnt = @_;
319 0           my $cmd = shift;
320 0           my $wait_write = $self->read_delay;
321 0 0         if ( $arg_cnt == 2 ) { $wait_write = shift }
  0            
322 0 0         if ( !open FHIN, ">", $self->buffin ) { ## no critic
323 0           die "could not open command file " . $self->buffin . ": $!\n";
324             }
325              
326 0           printf FHIN $cmd;
327 0           close(FHIN);
328              
329 0           sleep($wait_write);
330             }
331              
332              
333             sub TRMC2_Query {
334 0     0 1   my $self = shift;
335              
336 0           my $arg_cnt = @_;
337              
338 0           my $cmd = shift;
339 0           my $wait_query = $self->read_delay;
340 0 0         if ( $arg_cnt == 2 ) { $wait_query = shift }
  0            
341              
342             #----Open Command File---------
343 0 0         if ( !open FHIN, ">", $self->buffin ) { ## no critic
344 0           die "could not open command file " . $self->buffin . ": $!\n";
345             }
346              
347 0           printf FHIN $cmd;
348 0           close(FHIN);
349              
350             #-----------End Of Setting Command-----------
351 0           sleep($wait_query);
352              
353             #--------Reading Value----------------------
354 0 0         if ( !open FHOUT, "<", $self->buffout ) { ## no critic
355 0           die "could not open reply file " . $self->buffout . ": $!\n";
356             }
357 0           my @line = <FHOUT>;
358 0           close(FHOUT);
359              
360 0           return @line;
361             }
362              
363              
364             sub RemoveFrenchComma {
365 0     0 1   my $value = shift;
366 0           $value =~ s/,/./g;
367 0           return $value;
368             }
369              
370              
371             sub MakeFrenchComma {
372 0     0 1   my $value = shift;
373 0           $value =~ s/\./,/g;
374 0           return $value;
375             }
376              
377              
378             __PACKAGE__->meta()->make_immutable();
379              
380             1;
381              
382             __END__
383              
384             =pod
385              
386             =encoding UTF-8
387              
388             =head1 NAME
389              
390             Lab::Moose::Instrument::ABB_TRMC2 - ABB TRMC2 temperature controller
391              
392             =head1 VERSION
393              
394             version 3.881
395              
396             =head1 SYNOPSIS
397              
398             use Lab::Moose;
399            
400             my $trmc = instrument(
401             type => 'ABB_TRMC2'
402             );
403            
404             my $temp = $trmc->get_T();
405              
406             Warning: Due to the rather unique (and silly) way of device communication, the
407             TRMC2 driver does not use the connection layer.
408              
409             =head1 External interface
410              
411             =head2 set_T
412              
413             $trmc->set_T(value => 0.1);
414              
415             Program the TRMC to regulate the temperature towards a specific value (in K).
416             The function returns immediately; this means that the target temperature most
417             likely has not been reached yet.
418              
419             Possible values are in the range [min_setpoint, max_setpoint], by default
420             [0.02, 1.0].
421              
422             =head2 get_T
423              
424             $trmc->get_T();
425              
426             This is a shortcut for reading out temperature channel 5, typically the mixing chamber temperature.
427              
428             TODO: Which channel is typically used for the control loop here?
429              
430             =head1 Internal / hardware-specific functions
431              
432             =head2 TRMC2init
433              
434             Checks input and output buffer for TRMC2 commands and tests the file communication.
435              
436             =head2 TRMC2off
437              
438             Unmounts, i.e., releases control of the TRMC
439              
440             =head2 TRMC2_Heater_Control_On
441              
442             Switch the Heater Control (The coupling heater and set point NOT the heater switch in the main menu); 1 on, 0 off
443              
444             =head2 TRMC2_Prog_On
445              
446             What does this precisely do?
447              
448             =head2 TRMC2_get_SetPoint
449              
450             my $target = $trmc->TRMC2_get_SetPoint();
451              
452             Return the current setpoint of the TRMC2 in Kelvin.
453              
454             =head2 TRMC2_set_SetPoint
455              
456             $trmc->TRMC2_set_SetPoint(0.1);
457              
458             Program the TRMC to regulate the temperature towards a specific value (in K).
459             The function returns immediately; this means that the target temperature most
460             likely has not been reached yet.
461              
462             Possible values are in the range [min_setpoint, max_setpoint], by default
463             [0.02, 1.0].
464              
465             =head2 TRMC2_get_PV
466              
467             What does this do?
468              
469             =head2 TRMC2_AllMeas
470              
471             Read out all sensor channels.
472              
473             =head2 TRMC2_get_T
474              
475             my $t = $trmc->TRMC2_get_T($channel);
476              
477             Reads out temperature of a sensor channel.
478              
479             Sensor number:
480             1 Heater
481             2 Output
482             3 Sample
483             4 Still
484             5 Mixing Chamber
485             6 Cernox
486              
487             =head2 TRMC2_get_R
488              
489             my $r = $trmc->TRMC2_get_R($channel);
490              
491             Reads out resistance of a sensor channel.
492              
493             Sensor number:
494             1 Heater
495             2 Output
496             3 Sample
497             4 Still
498             5 Mixing Chamber
499             6 Cernox
500              
501             =head2 TRMC2_get_RT
502              
503             my ($r, $t) = $trmc->TRMC2_get_RT();
504              
505             Reads out resistance and temperature simultaneously.
506              
507             Sensor number:
508             1 Heater
509             2 Output
510             3 Sample
511             4 Still
512             5 Mixing Chamber
513             6 Cernox
514              
515             =head2 TRMC2_Read_Prog
516              
517             Reads Heater Batch Job
518              
519             =head2 TRMC2_Set_T_Sweep
520              
521             $trmc->TRMC2_Set_T_Sweep(SetPoint, Sweeprate, Holdtime)
522              
523             Programs the built in temperature sweep. After Activation it will sweep from the
524             current temperature to the set temperature with the given sweeprate. The Sweep
525             can be started with TRMC2_Start_Sweep(1).
526              
527             Variables: SetPoint in K, Sweeprate in K/Min, Holdtime in s (defaults to 0)
528              
529             =head2 TRMC2_Start_Sweep
530              
531             $trmc->TRMC2_Start_Sweep(1);
532              
533             Starts (1) / stops (0) the sweep --- provided the heater in TRMC2 window is
534             turned ON. At a sweep stop the power is left on.
535              
536             =head2 TRMC2_All_Channels
537              
538             Reads out all channels and values and returns an array
539              
540             =head2 TRMC2_Active_Channel
541              
542             Reads out the active channel (?)
543              
544             =head2 TRMC2_Shut_Down
545              
546             Stops the sweep and the heater control
547              
548             =head2 TRMC2_Write
549              
550             TRMC2_Write($cmd, $wait_write=$WAIT)
551              
552             Sends a command to the TRMC and will wait $wait_write.
553              
554             =head2 TRMC2_Query
555              
556             TRMC2_Query($cmd, $wait_query=$WAIT)
557              
558             Sends a command to the TRMC and will wait $wait_query sec long and returns the
559             result.
560              
561             =head2 RemoveFrenchComma
562              
563             Replace "," in a number with "." (yay for French hardware!)
564              
565             =head2 MakeFrenchComma
566              
567             Replace "." in a number with "," (yay for French hardware!)
568              
569             =head2 Consumed Roles
570              
571             This driver consumes no roles.
572              
573             =head1 COPYRIGHT AND LICENSE
574              
575             This software is copyright (c) 2023 by the Lab::Measurement team; in detail:
576              
577             Copyright 2011 Andreas K. Huettel, Florian Olbrich
578             2012 Alois Dirnaichner, Andreas K. Huettel
579             2013 Alois Dirnaichner
580             2016 Simon Reinhardt
581             2017 Andreas K. Huettel, Simon Reinhardt
582             2020 Andreas K. Huettel
583             2021 Andreas K. Huettel, Simon Reinhardt
584              
585              
586             This is free software; you can redistribute it and/or modify it under
587             the same terms as the Perl 5 programming language system itself.
588              
589             =cut