File Coverage

blib/lib/Lab/Instrument/PD11042.pm
Criterion Covered Total %
statement 17 330 5.1
branch 0 86 0.0
condition 0 48 0.0
subroutine 6 23 26.0
pod 1 15 6.6
total 24 502 4.7


line stmt bran cond sub pod time code
1             package Lab::Instrument::PD11042;
2             $Lab::Instrument::PD11042::VERSION = '3.880';
3             #ABSTRACT: Trinamic PD-110-42 low-cost 42mm stepper motor
4              
5 1     1   1846 use v5.20;
  1         4  
6              
7 1     1   5 use strict;
  1         2  
  1         25  
8 1     1   5 use Time::HiRes qw/usleep/, qw/time/;
  1         2  
  1         6  
9 1     1   100 use Lab::Instrument;
  1         2  
  1         52  
10 1     1   6 use Config;
  1         2  
  1         147  
11              
12             # todo:
13             # * test with VISA_RS232
14             # * integrate the limits etc into the config hash
15             # * hash call parameters
16             # * path for ini / log file???
17             # ...
18              
19             # Opcodes of all TMCL commands that can be used in direct mode
20             use constant {
21 1         4622 TMCL_ROR => 1,
22             TMCL_ROL => 2,
23             TMCL_MST => 3,
24             TMCL_MVP => 4,
25             TMCL_SAP => 5,
26             TMCL_GAP => 6,
27             TMCL_STAP => 7,
28             TMCL_RSAP => 8,
29             TMCL_SGP => 9,
30             TMCL_GGP => 10,
31             TMCL_STGP => 11,
32             TMCL_RSGP => 12,
33             TMCL_RFS => 13,
34             TMCL_SIO => 14,
35             TMCL_GIO => 15,
36             TMCL_SCO => 30,
37             TMCL_GCO => 31,
38             TMCL_CCO => 32
39              
40             # Options for MVP commandds
41             ,
42             MVP_ABS => 0,
43             MVP_REL => 1,
44             MVP_COORD => 2
45              
46             # Options for RFS command
47             ,
48             RFS_START => 0,
49             RFS_STOP => 1,
50             RFS_STATUS => 2
51              
52             # Result codes for GetResult
53             ,
54             TMCL_RESULT_OK => 0,
55             TMCL_RESULT_NOT_READY => 1,
56             TMCL_RESULT_CHECKSUM_ERROR => 2
57              
58             # axis paramter for SAP and GAP
59             ,
60             target_position => 0,
61             actual_position => 1,
62             target_speed => 2,
63             actual_speed => 3,
64             maximum_positioning_speed => 4,
65             maximum_acceleration => 5,
66             absolut_max_current => 6,
67             standby_current => 7,
68             minimum_speed => 130,
69             ramp_mode => 138,
70             microstep_resolution => 140,
71             ramp_divisor => 153,
72             puls_divisor => 154,
73             freewheeling => 204,
74             stall_detection_threshold => 211,
75             power_down_dely => 214
76              
77             # global parameters
78             , user_defined => 2
79              
80 1     1   8 };
  1         2  
81              
82             our %limits;
83             our $RESOLUTION = 32;
84             our $GETRIEBEMULTIPLIKATOR = 43;
85              
86             our @ISA = ("Lab::Instrument");
87              
88             our %fields = (
89             supported_connections => [ 'VISA', 'VISA_RS232', 'RS232', 'DEBUG' ],
90             connection_settings => {
91             baudrate => 9600,
92             databits => 8,
93             stopbits => 1,
94             parity => 'none',
95             handshake => 'none',
96             termchar => '\r',
97             timeout => 2,
98             },
99              
100             device_settings => {
101             read_default => 'device',
102             pos_mode => 'ABS',
103             speed_max => 180,
104             upper_limit => 180,
105             lower_limit => -180,
106             inipath => $Config{sitelib} . "/Lab/Instrument/PD11042.ini",
107             logpath => $Config{sitelib} . "/Lab/Instrument/PD11042.log",
108              
109             },
110              
111             device_cache => {
112             position => undef,
113             target => undef,
114             },
115              
116             device_cache_order => ['id'],
117             );
118              
119             sub new {
120 0     0 1   my $proto = shift;
121 0   0       my $class = ref($proto) || $proto;
122 0           my $self = $class->SUPER::new(@_);
123 0           $self->${ \( __PACKAGE__ . '::_construct' ) }(__PACKAGE__);
  0            
124              
125             # my $status;
126             # termchar is imho disabled by default
127             # $status=Lab::VISA::viSetAttribute($self->{vi}->{config}->{RS232}->{vi}->{instr}, $Lab::VISA::VI_ATTR_TERMCHAR_EN, $Lab::VISA::VI_FALSE);
128             # if ($status != $Lab::VISA::VI_SUCCESS) { Lab::Exception::CorruptParameter->throw( error => "Error while setting termchar enabled: $status");}
129             # not sure what the echo setting by default is, let's test
130             # $self->{vi}->{config}->{RS232_Echo} = 'OFF';
131              
132             # my ($result, $errcode) = $self->exec_cmd(TMCL_GAP, maximum_positioning_speed, 10);
133             # print $result."\n";
134             # my ($result, $errcode) = $self->exec_cmd(TMCL_GAP, ramp_mode, 0);
135             # print $result."\n";
136             # my ($result, $errcode) = $self->exec_cmd(TMCL_GAP, microstep_resolution, 5);
137             # print $result."\n";
138             # my ($result, $errcode) = $self->exec_cmd(TMCL_GAP, absolut_max_current, 745);
139             # print $result."\n";
140             # my ($result, $errcode) = $self->exec_cmd(TMCL_GAP, standby_current, 1400);
141             # print $result."\n";
142             # my ($result, $errcode) = $self->exec_cmd(TMCL_GAP, stall_detection_threshold, 2040);
143             # print $result."\n";
144             # my ($result, $errcode) = $self->exec_cmd(TMCL_GAP, power_down_dely, 0);
145             # print $result."\n";
146             # my ($result, $errcode) = $self->exec_cmd(TMCL_GAP, ramp_divisor, 7);
147             # print $result."\n";
148             # my ($result, $errcode) = $self->exec_cmd(TMCL_GAP, puls_divisor, 3);
149             # print $result."\n";
150             # my ($result, $errcode) = $self->exec_cmd(TMCL_GAP, freewheeling, 100);
151             # print $result."\n";
152             # exit;
153              
154 0           my ( $result, $errcode );
155              
156             # set initial motor parameters (reference point, speed, microstep resolution, etc.
157             # 1.) speed:
158 0           $limits{'maximum_positioning_speed'} = 120;
159 0           ( $result, $errcode ) = $self->exec_cmd( TMCL_SAP, target_speed, 0 );
160             ( $result, $errcode )
161             = $self->exec_cmd( TMCL_SAP, maximum_positioning_speed,
162 0           $self->steps2angle( $limits{'maximum_positioning_speed'} / 2.4 )
163             ); #HIER ANSETZEN!!!
164 0           ( $result, $errcode ) = $self->exec_cmd( TMCL_SAP, ramp_mode, 2 );
165              
166             # 2.) microstep resolution:
167             # 0 = full step (don't use),
168             # 1 = half step (don't use),
169             # 2 = 4 microsteps,
170             # 3 = 8 microsteps,
171             # 4 = 16 microsteps,
172             # 5 = 32 microsteps,
173             # 6 = 64 microsteps
174 0           $RESOLUTION = 32;
175 0           ( $result, $errcode )
176             = $self->exec_cmd( TMCL_SAP, microstep_resolution, 5 );
177              
178             # 3.) motor current settings:
179 0           ( $result, $errcode )
180             = $self->exec_cmd( TMCL_SAP, absolut_max_current, 745 ); # 469 mA
181 0           ( $result, $errcode )
182             = $self->exec_cmd( TMCL_SAP, standby_current, 1400 ); # 117 mA
183 0           ( $result, $errcode )
184             = $self->exec_cmd( TMCL_SAP, stall_detection_threshold, 2040 );
185 0           ( $result, $errcode ) = $self->exec_cmd( TMCL_SAP, power_down_dely, 0 );
186 0           ( $result, $errcode ) = $self->exec_cmd( TMCL_SAP, ramp_divisor, 7 );
187 0           ( $result, $errcode ) = $self->exec_cmd( TMCL_SAP, puls_divisor, 3 );
188 0           ( $result, $errcode ) = $self->exec_cmd( TMCL_SAP, freewheeling, 100 );
189              
190             # ($result, $errcode) = $self->exec_cmd(TMCL_SAP, actual_position, $self->angle2steps(-330));
191             # print $self->get_position()."\n";;
192             # exit;
193              
194             # 4.) restore position
195             #$self->exec_cmd(TMCL_RSGP, 0, 0, 2);
196             #my ($result, $errcode) = $self->exec_cmd(TMCL_GGP, 0, 0, 2);
197             #my ($result2, $errcode) = $self->exec_cmd(TMCL_SAP, target_position, $self->angle2steps(83.59));
198             #my ($result2, $errcode) = $self->exec_cmd(TMCL_SAP, actual_position, $self->angle2steps(83.59));
199             #exit;
200              
201             # 5.) set some reference point and limits for motor movements:
202 0           $self->init_limits();
203              
204 0           return $self;
205             }
206              
207             # Execute command: exec_cmd(cmd, type, value, [motor])
208             sub exec_cmd {
209 0     0 0   my $self = shift;
210              
211 0           my $addr = 1;
212 0           my $cmd = shift;
213 0           my $type = shift;
214 0           my $value = shift;
215 0           my $motor = shift;
216 0 0         if ( not defined $motor ) {
217 0           $motor = 0;
218             }
219              
220 0 0         if ( $value < 0 ) {
221 0           $value = 4244897281 + $value;
222             }
223              
224 0           my $v4 = int( $value / 255**3 );
225 0 0         $v4 = ( $v4 > 255 ) ? 255 : $v4;
226 0           $value -= ( 255**3 ) * $v4;
227 0           my $v3 = int( $value / 255**2 );
228 0 0         $v3 = ( $v3 > 255 ) ? 255 : $v3;
229 0           $value -= ( 255**2 ) * $v3;
230 0           my $v2 = int( $value / 255 );
231 0 0         $v2 = ( $v2 > 255 ) ? 255 : $v2;
232 0           $value -= 255 * $v2;
233              
234 0           my $checksum
235             = ( $addr + $cmd + $type + $motor + $v4 + $v3 + $v2 + $value ) % 256;
236              
237 0           my $query = pack(
238             "C9", $addr, $cmd, $type, $motor, $v4, $v3, $v2, $value,
239             $checksum
240             );
241 0           my $result = 0;
242 0           my $errcode = 0;
243 0           my $i = 0;
244              
245 0   0       while ( $errcode != 100 && $i < 10 ) {
246              
247             #print $addr."-".$cmd."-".$type."-".$motor."-".$v4."-".$v3."-".$v2."-".$value."-".$checksum." (".$i.")\n";
248 0           $self->write($query);
249 0           ( $result, $errcode ) = $self->get_reply();
250 0           $i++;
251             }
252              
253 0           return $result, $errcode;
254             }
255              
256             sub get_reply {
257 0     0 0   my $self = shift;
258 0           my @result;
259              
260 0           foreach ( 1 .. 9 ) {
261 0           my $a = $self->connection()->BrutalRead( read_length => 1 );
262 0           push( @result, unpack( "C", $a ) );
263             }
264              
265 0           my $value
266             = ( 255**3 ) * $result[4]
267             + ( 255**2 ) * $result[5]
268             + 255 * $result[6]
269             + $result[7];
270 0 0         if ( $value > 2122448640 ) {
271 0           $value = -( 4244897281 - $value );
272             }
273              
274 0           return $value, $result[2];
275             }
276              
277             sub move {
278 0     0 0   my $self = shift;
279              
280             # Parameter, old style: ABS/REL, angle, speed
281              
282 0           my ( $position, $speed, $mode )
283             = $self->_check_args( \@_, [ 'position', 'speed', 'mode' ] );
284              
285             # TODO:
286             # if (ref($mode) eq 'HASH') ...
287             # 'mode', 'angle', 'speed'
288              
289 0 0         if ( not defined $mode ) {
290 0           $mode = $self->device_settings()->{pos_mode};
291             }
292 0 0         if ( not $mode =~ /ABS|abs|REL|rel/ ) {
293 0           Lab::Exception::CorruptParameter->throw( error =>
294             "unexpected value for <MODE> in sub move. expected values are ABS and REL."
295             );
296             }
297 0 0         if ( not defined $speed ) {
298 0           $speed = $self->device_settings()->{speed_max};
299             }
300 0 0         if ( not defined $position ) {
    0          
301 0           Lab::Exception::CorruptParameter->throw(
302             error => $self->get_id() . ": No target given in sub move! " );
303             }
304             elsif (
305             not $position =~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/ )
306             {
307 0           Lab::Exception::CorruptParameter->throw( error => $self->get_id()
308             . ": Illegal Value given for POSITION in sub move!" );
309             }
310              
311             # this sets the upper limit for the positioning speed:
312 0           $speed = abs($speed);
313 0 0         if ( $speed > $self->device_settings()->{speed_max} ) {
314             print new Lab::Exception::CorruptParameter( error =>
315             "Warning in sub move: <SPEED> = $speed is too high. Reduce <SPEED> to its maximum value defined by internal limit settings of "
316 0           . $self->device_settings()->{speed_max} );
317 0           $speed = $self->device_settings()->{speed_max};
318             }
319              
320 0           $speed = $speed / 2.4;
321 0           my ( $result, $errcode )
322             = $self->exec_cmd( TMCL_SAP, maximum_positioning_speed, $speed );
323              
324             # Moving in ABS or REL mode:
325 0           my $CP = $self->get_position();
326 0 0 0       if ( $mode eq "ABS"
    0 0        
      0        
      0        
      0        
      0        
327             or $mode eq "abs"
328             or $mode eq "ABSOLUTE"
329             or $mode eq "absolute" ) {
330 0 0 0       if ( $position < $self->device_settings()->{lower_limit}
331             or $position > $self->device_settings()->{upper_limit} ) {
332 0           Lab::Exception::CorruptParameter->throw( error =>
333             "unexpected value for NEW POSITION in sub move. Expected values are between $limits{'LOWER'} ... $limits{'UPPER'}"
334             );
335             }
336 0           $self->device_cache()->{target} = $position;
337 0           $self->_save_motorlog( $CP, $position );
338 0           $self->save_motorinitdata();
339 0           $self->exec_cmd( TMCL_MVP, MVP_ABS, $self->angle2steps($position) );
340             }
341             elsif ($mode eq "REL"
342             or $mode eq "rel"
343             or $mode eq "RELATIVE"
344             or $mode eq "relative" ) {
345 0 0 0       if ( $CP + $position < $self->device_settings()->{lower_limit}
346             or $CP + $position > $self->device_settings()->{upper_limit} ) {
347             Lab::Exception::CorruptParameter->throw( error =>
348             "ERROR in sub move.Can't execute move; TARGET POSITION ("
349             . ( $CP + $position )
350             . ") is out of valid limits ("
351             . $limits{'LOWER'} . " ... "
352 0           . $limits{'UPPER'}
353             . ")" );
354             }
355              
356 0           $self->device_cache()->{target} = $CP + $position;
357 0           $self->_save_motorlog( $CP, $CP + $position );
358 0           $self->save_motorinitdata();
359              
360 0           $self->exec_cmd( TMCL_MVP, MVP_REL, $self->angle2steps($position) );
361             }
362 0           return 1;
363             }
364              
365             sub active {
366 0     0 0   my $self = shift;
367              
368 0           my ( $result, $errcode ) = $self->exec_cmd( TMCL_GAP, actual_speed, 0 );
369 0           $self->get_position();
370 0           return abs($result);
371              
372             }
373              
374             sub wait {
375 0     0 0   my $self = shift;
376 0           my $flag = 1;
377 0           local $| = 1;
378              
379 0           while ( $self->active() ) {
380 0 0 0       if ( $flag <= 1.1 and $flag >= 0.9 ) {
    0          
381             printf(
382             "%s is sweeping (%06.2f)\r",
383             $self->get_id(), $self->device_cache()->{position}
384 0           );
385             }
386             elsif ( $flag <= 0 ) {
387             printf(
388             "%s is (%06.2f)\r",
389             $self->get_id(), $self->device_cache()->{position}
390 0           );
391 0           $flag = 2;
392             }
393 0           $flag -= 0.5;
394 0           usleep(5e3);
395             }
396              
397 0           print "\t\t\t\t\t\t\t\t\t\r";
398 0           $| = 0;
399              
400 0           return 1;
401              
402             }
403              
404             sub abort {
405 0     0 0   my $self = shift;
406 0           $self->exec_cmd( TMCL_MST, 0, 0 );
407 0           print "Motor stoped at " . $self->get_position() . "\n";
408 0           return;
409             }
410              
411             sub init_limits {
412 0     0 0   my $self = shift;
413 0           my $lowerlimit;
414             my $upperlimit;
415              
416 0 0         if ( $self->read_motorinitdata() ) {
417 0           while (1) {
418 0           print
419             "Motor-Init data found. Do you want to keep the reference point and the limits? (y/n) ";
420 0           my $input = <>;
421 0           chomp $input;
422 0 0         if ( $input =~ /YES|yes|Y|y/ ) {
    0          
423 0           return 1;
424             }
425             elsif ( $input =~ /NO|no|N|n/ ) {
426 0           my ( $result, $errcode )
427             = $self->exec_cmd( TMCL_MST, 0, 0 )
428             ; # Motor stop, to prevent unexpected motor activity
429 0           ( $result, $errcode )
430             = $self->exec_cmd( TMCL_SAP, target_position, 0 );
431 0           ( $result, $errcode )
432             = $self->exec_cmd( TMCL_SAP, actual_position, 0 );
433 0           $self->device_settings->{lower_limit} = -360;
434 0           $self->device_settings->{upper_limit} = 360;
435 0           last;
436             }
437             }
438             }
439              
440 0           print "\n\n";
441 0           print "----------------------------------------------\n";
442 0           print "----------- Init Motor PDx-110-42 ------------\n";
443 0           print "----------------------------------------------\n";
444 0           print "\n";
445 0           print
446             "This procedure will help you to initialize the Motor PDx-110-42 correctly.\n\n";
447 0           print "Steps to go:\n";
448 0           print " 1.) Define the REFERENCE POINT.\n";
449 0           print " 2.) Define the LOWER and UPPER LIMITS for rotation.\n";
450 0           print " 3.) Confirm the LOWER and UPPER LIMITS.\n";
451 0           print "\n\n";
452              
453 0           print "----------------------------\n";
454 0           print "1.) Define the REFERENCE POINT:\n\n";
455 0           print "--> Move the motor position to the REFERENCE POINT.\n";
456 0           print "--> Enter an angle between -180 ... +180 deg.\n";
457 0           print
458             "--> Repeat until you have reached the position you want to define as the REFERENCE POINT.\n";
459 0           print
460             "--> Enter 'REF' to confirm the actual position as the REFERENCE POINT.\n\n";
461              
462 0           while (1) {
463 0           print "MOVE: ";
464 0           my $value = <STDIN>;
465 0           chomp $value;
466 0 0 0       if ( $value eq "REF" or $value eq "ref" ) {
    0 0        
      0        
467              
468             # set actual position as reference point Zero
469 0           $self->device_cache()->{position} = 0; # for testing only
470 0           my ( $result, $errcode )
471             = $self->exec_cmd( TMCL_MST, 0, 0 )
472             ; # Motor stop, to prevent unexpected motor activity
473 0           ( $result, $errcode )
474             = $self->exec_cmd( TMCL_SAP, target_position, 0 );
475 0           ( $result, $errcode )
476             = $self->exec_cmd( TMCL_SAP, actual_position, 0 );
477 0           last;
478             }
479             elsif ( $value =~ /^[+-]?\d+$/ and $value >= -180 and $value <= 180 )
480             {
481 0           $self->move( $value, { mode => 'REL' } );
482 0           $self->wait();
483             }
484             else {
485 0           print
486             "Please move the motor position to the REFERENCE POINT. Enter an angle between -188° ... +180°.\n";
487             }
488             }
489              
490 0           print "----------------------------\n";
491 0           print "2.) Define the LOWER and UPPER LIMITS for rotation:\n\n";
492 0           print "--> Enter LOWER LIMIT\n";
493 0           print "--> Enter UPPER LIMIT\n\n";
494              
495 0           while (1) {
496 0           print "LOWER LIMIT: ";
497 0           my $value = <STDIN>;
498 0           chomp $value;
499 0           $lowerlimit = $value;
500 0           $self->device_settings()->{lower_limit} = $lowerlimit;
501 0           print "UPPER LIMIT: ";
502 0           $value = <STDIN>;
503 0           chomp $value;
504 0           $upperlimit = $value;
505 0           $self->device_settings()->{upper_limit} = $upperlimit;
506              
507 0 0         if ( $lowerlimit < $upperlimit ) {
508 0           last;
509             }
510             else {
511 0           print "LOWER LIMIT >= UPPER LIMIT. Try again!\n";
512             }
513             }
514              
515 0           print "----------------------------\n";
516 0           print "3.) Confirm the LOWER and UPPER LIMITS:\n\n";
517 0           print "--> Motor will move to LOWER LIMIT in steps of 10 deg\n";
518 0           print "--> Motor will move to UPPER LIMIT in steps of 10 deg\n";
519 0           print
520             "--> Confirm each step with ENTER or type <STOP> to take the actual position as the limit value. \n\n";
521              
522 0           print "Moving to LOWER LIMIT ...\n";
523 0           while (1) {
524 0           print "MOVE +/-10: Please press <ENTER> to confirm.";
525 0           my $input = <STDIN>;
526 0           chomp $input;
527 0 0         if ( $input =~ /stop|STOP/ ) {
528 0           $lowerlimit = $self->get_position();
529 0           last;
530             }
531 0 0         if ( abs( $self->get_position() - $lowerlimit ) >= 10 ) {
532 0 0         if ( $lowerlimit <= 0 ) {
533 0           $self->move( -10, { mode => 'REL' } );
534 0           $self->wait();
535              
536             }
537             else {
538 0           $self->move( 10, { mode => 'REL' } );
539 0           $self->wait();
540             }
541             }
542             else {
543 0           $self->move( $lowerlimit, { mode => 'ABS' } );
544 0           $self->wait();
545 0           last;
546             }
547              
548             }
549 0           print "Reached LOWER LIMIT\n";
550 0           print "Please confirm the position of the LOWER LIMIT: ";
551 0           <STDIN>;
552 0           $self->device_settings()->{'lower_limit'} = $lowerlimit;
553 0           print "\n\n";
554 0           print "Moving to REFERENCE POINT ... \n";
555 0           print $self->move( 0, { mode => 'ABS' } ) . "\n";
556 0           $self->wait();
557 0           print "Moving to UPPER LIMIT ...\n";
558              
559 0           while (1) {
560 0           print "MOVE +/-10: Please press <ENTER> to confirm.";
561 0           my $input = <STDIN>;
562 0           chomp $input;
563 0 0         if ( $input =~ /stop|STOP/ ) {
564 0           $upperlimit = $self->get_position();
565 0           last;
566             }
567 0 0         if ( abs( $upperlimit - $self->get_position() ) >= 10 ) {
568 0           $self->move( 10, { mode => 'REL' } );
569 0           $self->wait();
570             }
571             else {
572 0           $self->move( $upperlimit, { mode => 'ABS' } );
573 0           $self->wait();
574              
575 0           last;
576             }
577              
578             }
579 0           print "Reached UPPER LIMIT\n";
580 0           print "Please confirm the position of the UPPER LIMIT: ";
581 0           <STDIN>;
582 0           $self->device_settings()->{'upper_limit'} = $upperlimit;
583 0           print "\n\n";
584 0           $self->save_motorinitdata();
585              
586 0           print "moving to the reference point.\n";
587 0           $self->move( 0, { mode => 'ABS' } );
588              
589 0           $self->wait();
590 0           print "------------------------------------------------------\n";
591 0           print "------------ Motor PDx-110-42 initialized ------------\n";
592 0           print "------------------------------------------------------\n";
593 0           print "\n\n";
594              
595             }
596              
597             sub _set_REF {
598 0     0     my $self = shift;
599 0           my $new_ref = shift;
600              
601 0           my $old_ref = $self->get_position();
602              
603             open( my $handle, ">>", $self->device_settings()->{logpath} )
604 0 0         or print "cant open logfile\n";
605              
606 0           print "Set actual position from $old_ref to $new_ref\n";
607 0           my ( $result, $errcode ) = $self->exec_cmd( TMCL_SAP, target_position,
608             $self->angle2steps($new_ref)
609             );
610 0           ( $result, $errcode ) = $self->exec_cmd( TMCL_SAP, actual_position,
611             $self->angle2steps($new_ref)
612             );
613 0           print {$handle} ( my_timestamp() )
  0            
614             . "\t set new REF: $old_ref -> $new_ref \n";
615 0           close($handle);
616              
617             # this writes the new position to the ini-file.
618 0           $self->get_position();
619              
620 0           return;
621             }
622              
623             sub steps2angle {
624 0     0 0   my $self = shift;
625 0           my $steps = shift;
626 0           my $angle = $steps / ( 200 * $RESOLUTION / 360 ) / $GETRIEBEMULTIPLIKATOR;
627 0           return $angle;
628             }
629              
630             sub angle2steps {
631 0     0 0   my $self = shift;
632 0           my $angle = shift;
633 0           my $steps = $angle * ( 200 * $RESOLUTION / 360 ) * $GETRIEBEMULTIPLIKATOR;
634 0           return sprintf( "%0.f", $steps );
635              
636             }
637              
638             sub get_value {
639 0     0 0   my $self = shift;
640 0           my ( $read_mode, $tail ) = $self->_check_args( \@_, ['read_mode'] );
641              
642 0           return $self->get_position( { read_mode => $read_mode } );
643             }
644              
645             sub get_position {
646 0     0 0   my $self = shift;
647 0           my ($read_mode) = $self->_check_args( \@_, ['read_mode'] );
648              
649 0 0 0       if ( not defined $read_mode
650             or not $read_mode =~ /device|cache|request|fetch/ ) {
651 0           $read_mode = $self->device_settings()->{read_default};
652             }
653              
654 0 0 0       if ( $read_mode eq 'cache'
655             and defined $self->{'device_cache'}->{'position'} ) {
656 0           return $self->{'device_cache'}->{'position'};
657             }
658              
659 0           my ( $result, $errcode )
660             = $self->exec_cmd( TMCL_GAP, actual_position, 0 );
661              
662             # store position in Global-Parameter 0:
663 0           $self->exec_cmd( TMCL_SGP, 0, $result, 2 );
664 0           $self->exec_cmd( TMCL_STGP, 0, 0, 2 );
665              
666 0           $self->device_cache()->{position} = $self->steps2angle($result);
667 0           $self->save_motorinitdata();
668 0           $self->{value} = $self->device_cache()->{position};
669 0           return $self->device_cache()->{position};
670              
671             }
672              
673             sub save_motorinitdata {
674 0     0 0   my $self = shift;
675              
676 0           open( DUMP, ">" . $self->device_settings()->{'inipath'} )
677             ; #open for write, overwrite
678 0           print DUMP "POSITION: " . $self->device_cache()->{position} . "\n";
679 0           print DUMP "TARGET: " . $self->device_cache()->{target} . "\n";
680 0           print DUMP "SPEED_MAX: " . $self->device_settings()->{speed_max} . "\n";
681             print DUMP "UPPER_LIMIT: "
682 0           . $self->device_settings()->{upper_limit} . "\n";
683             print DUMP "LOWER_LIMIT: "
684 0           . $self->device_settings()->{lower_limit} . "\n";
685 0           print DUMP "TIMESTAMP: " . time() . "\n";
686 0           close(DUMP);
687             }
688              
689             sub _save_motorlog {
690 0     0     my $self = shift;
691 0           my ( $init_pos, $end_pos )
692             = $self->_check_args( \@_, [ 'init_pos', 'end_pos' ] );
693              
694 0           open( DUMP, ">>" . $self->device_settings()->{'logpath'} )
695             ; #open for write, overwrite
696              
697 0           print DUMP ( my_timestamp() ) . "\t move: $init_pos -> $end_pos \n";
698              
699 0           close(DUMP);
700             }
701              
702             sub read_motorinitdata {
703 0     0 0   my $self = shift;
704              
705 0 0         if ( not open( DUMP, "<" . $self->device_settings()->{'inipath'} ) ) {
706 0           return 0;
707             }
708 0           while (<DUMP>) {
709 0           chomp($_);
710 0           my @line = split( /: /, $_ );
711 0 0         if ( $line[0] eq 'POSITION' ) {
    0          
    0          
    0          
    0          
712 0           $self->device_cache()->{position} = $line[1];
713             }
714             elsif ( $line[0] eq 'TARGET' ) {
715 0           $self->device_cache()->{target} = $line[1];
716             }
717             elsif ( $line[0] eq 'SPEED_MAX' ) {
718 0           $self->device_settings()->{speed_max} = $line[1];
719             }
720             elsif ( $line[0] eq 'UPPER_LIMIT' ) {
721 0           $self->device_settings()->{upper_limit} = $line[1];
722             }
723             elsif ( $line[0] eq 'LOWER_LIMIT' ) {
724 0           $self->device_settings()->{lower_limit} = $line[1];
725             }
726              
727             }
728              
729 0           print "\nread MOTOR-INIT-DATA\n";
730 0           print "--------------------\n";
731 0           print "POSITION: " . $self->device_cache()->{position} . "\n";
732 0           print "TARGET: " . $self->device_cache()->{target} . "\n";
733 0           print "SPEED_MAX: " . $self->device_settings()->{speed_max} . "\n";
734 0           print "UPPER_LIMIT: " . $self->device_settings()->{upper_limit} . "\n";
735 0           print "LOWER_LIMIT: " . $self->device_settings()->{lower_limit} . "\n";
736              
737 0           print "--------------------\n";
738 0           return 1;
739             }
740              
741             sub my_timestamp {
742              
743             my (
744 0     0 0   $Sekunden, $Minuten, $Stunden, $Monatstag, $Monat,
745             $Jahr, $Wochentag, $Jahrestag, $Sommerzeit
746             ) = localtime(time);
747              
748 0           $Monat += 1;
749 0           $Jahrestag += 1;
750 0 0         $Monat = $Monat < 10 ? $Monat = "0" . $Monat : $Monat;
751 0 0         $Monatstag = $Monatstag < 10 ? $Monatstag = "0" . $Monatstag : $Monatstag;
752 0 0         $Stunden = $Stunden < 10 ? $Stunden = "0" . $Stunden : $Stunden;
753 0 0         $Minuten = $Minuten < 10 ? $Minuten = "0" . $Minuten : $Minuten;
754 0 0         $Sekunden = $Sekunden < 10 ? $Sekunden = "0" . $Sekunden : $Sekunden;
755 0           $Jahr += 1900;
756              
757 0           return "$Stunden:$Minuten:$Sekunden $Monatstag.$Monat.$Jahr\n";
758              
759             }
760              
761             1;
762              
763             __END__
764              
765             =pod
766              
767             =encoding utf-8
768              
769             =head1 NAME
770              
771             Lab::Instrument::PD11042 - Trinamic PD-110-42 low-cost 42mm stepper motor
772              
773             =head1 VERSION
774              
775             version 3.880
776              
777             =head1 SYNOPSIS
778              
779             use Lab::Instrument::PD11042;
780            
781             ...
782              
783             =head1 DESCRIPTION
784              
785             The Lab::Instrument::PD11042 class implements an interface to the
786             Trinamic PD-110-42 low-cost 42mm stepper motor with integrated
787             controller/driver.
788              
789             =head1 CONSTRUCTOR
790              
791             ...
792              
793             =head1 METHODS
794              
795             =head2 ...
796              
797             ...
798              
799             ...
800              
801             =head1 CAVEATS/BUGS
802              
803             None known so far. :)
804              
805             =head1 SEE ALSO
806              
807             =over 4
808              
809             =item Lab::Instrument
810              
811             =item
812             <Lhttp://www.trinamic.com/index.php?option=com_content&view=article&id=243&
813             Itemid=355>
814              
815             =back
816              
817             =head1 COPYRIGHT AND LICENSE
818              
819             This software is copyright (c) 2023 by the Lab::Measurement team; in detail:
820              
821             Copyright 2012 Andreas K. Huettel
822             2013 Andreas K. Huettel, Christian Butschkow
823             2014 Christian Butschkow
824             2016 Simon Reinhardt
825             2017 Andreas K. Huettel
826             2020 Andreas K. Huettel, Simon Reinhardt
827              
828              
829             This is free software; you can redistribute it and/or modify it under
830             the same terms as the Perl 5 programming language system itself.
831              
832             =cut