use strict; use Win32::SerialPort; # user control ###### # STILL TO DO ##### # PROMPT USER FOR INPUT # Z axis is Velmex Bislide E01 # E01 - 1 step = 0.00025" # X, Y axis is Velmex Bislide E04 # E04 - 1 step = 0.001" my $number_of_plates = 0; my $number_of_filters = 0; my $replicate_spots_per_filter = 0; my $replicate_hits_per_spot = 0; my $pause_every_plate = 0; my $temp_pause = ''; my $z_speed_liquid = 0; my $ready_to_go = 0; # need to be 4 cm higher # 4 cm = 1.57480315" devided by 0.00025 (inches per step) # = 6299.213 steps my $y_adjust = 5300 - 6250;#jg changed from 6000 to 6250 Nov07,2005 while ($ready_to_go == 0){ print "INPUT: Number of Source Plates\n"; $number_of_plates = ; chomp $number_of_plates; print "INPUT: Number of Destination Filters\n"; $number_of_filters = ; chomp $number_of_filters; print "INPUT: Number of Replicate Spots per Filter\n"; $replicate_spots_per_filter = ; chomp $replicate_spots_per_filter; print "INPUT: Number of Replicate Hits per Spot\n"; $replicate_hits_per_spot = ; chomp $replicate_hits_per_spot; # print "INPUT: Speed coming in and out of plates and filters\n"; # $z_speed_liquid = ; # chomp $z_speed_liquid; $z_speed_liquid = 2000; print "INPUT: Pause After Every OTHER Plate (1=yes, 0=no)\n"; $pause_every_plate = ; chomp $pause_every_plate; my $temp_pause = ""; if($pause_every_plate == 0){ $temp_pause = "NOT"; } print "It appears that you plan to print from $number_of_plates source plates\n"; print "to $number_of_filters destination filters. You wish each sample\n"; print "to be replicate spotted $replicate_spots_per_filter times\n"; print "and each spot to be hit $replicate_hits_per_spot times.\n"; print "You do $temp_pause wish to pause after every OTHER plate (to remove a lid, etc.).\n\n"; my $temp_product = $number_of_plates * $replicate_spots_per_filter; print "$number_of_plates times $replicate_spots_per_filter equals $temp_product total spots per filter\n\n"; print "Is the above information all correct (1=yes, 0=no)???\n"; $ready_to_go = ; if($temp_product > 12){ $ready_to_go = 0; print "You want to print too many spots\n"; } } #### # STILL TO DO #### # files of positions and offsets # these are hardwired at the moment my $filter_definition_file = "filters.in"; # ideally I would like to read these in my @x_filter_offset_positions = (0, 53, 106, 27, 80, 133, 0, 53, 106, 27, 80, 133); my @y_filter_offset_positions = (0, 0, 0, 39, 39, 39, 79, 79, 79, 118, 118, 118); my @x_wash_positions = (0,0,0,0); my @y_wash_positions = (1500,5250,9000,12750); my @x_plate_positions = (6000, 6030, 6004, 6004, 12010, 12000); my @y_plate_positions = (20, 3997, 8015, 12015, 5, 3990); my @x_filter_positions = (18000, 18000, 18000, 18000, 23000, 23000, 23000, 23000, 28000, 28000, 28000, 28000, 33000, 33000, 33000, 33000, 38000, 38000, 38000, 38000, 43000, 43000, 43000, 43000, 48000, 48000, 48000, 48000); my @y_filter_positions = (0, 3850, 7700, 11550, 0, 3850, 7700, 11550, 0, 3850, 7700, 11550, 0, 3850, 7700, 11550, 0, 3850, 7700, 11550, 0, 3850, 7700, 11550, 0, 3850, 7700, 11550); # speeds and heights my $x_speed = 3000; my $y_speed = 3000; my $z_speed = 2000; # speed in plates and touching membrane # my $z_speed_liquid = 2000; my $time_of_pause = 30; $time_of_pause = $time_of_pause*10; # heights my $z_safe_up = 9921 - $y_adjust; my $z_filter_down = 15000 - $y_adjust; my $z_plate_down = 14200 - $y_adjust; my $z_wash_down = 13780 - $y_adjust; my $z_plate_and_filter_up = 11000 - $y_adjust; #safe for plates and filters BUT NOT WASH # 11750 safe for 384 thermocycle my $z_plate_change_speed = 12800 - $y_adjust; #change speed pulling out of plates my $z_filter_change_speed = 14200 - $y_adjust; #change speed pulling out of filters # mapping of motors # changing these would be VERY VERY BAD # do not ever change these unless you REALLY REALLY know what you are doing my $x_motor = 1; my $y_motor = 3; my $z_motor = 2; ######################## # MAIN PROGRAM STARTS HERE ######################## my $wait_for_it = ''; # start talking to COM my $ob = Win32::SerialPort->new ('COM1') || die; $ob->user_msg(1); # misc. warnings $ob->error_msg(1); # hardware and data errors #initialize COM1 $ob->baudrate(9600); $ob->parity("none"); # $ob->parity_enable(1); # for any parity except "none" $ob->databits(8); $ob->stopbits(1); $ob->handshake('none'); #write settings $ob->write_settings; $ob->save("tpj4.cfg"); print "wrote configuration file tpj4.cfg\n"; #open port for talking $ob -> write("F"); home_machine(); my $current_offset = 0; for(my $nop = 0; $nop < $number_of_plates; $nop++){ print "WASHING TOOL\n"; wash_pin_tool(); my $platewait = ''; if ($nop%6 == 0){ # GO HIGH, pause and wait for user to load six more plates send_to_velmex( "C, IA".$z_motor."M500, R"); send_to_velmex( "C,(IA".$y_motor."M200,IA".$x_motor."M23000,)R"); print "PLEASE LOAD SIX NEW PLATES\n"; print "After loading plates press return to continue\n"; $platewait = ; } # n_pause is normally equal to 2 (pause after every other plate # by it may be useful to set it to other numbers for testing # for example setting it equal to 1 would pause after EVERY plate my $n_pause = 2; if($pause_every_plate & $nop%$n_pause == 0){ # pause and wait for user to remove lid etc. send_to_velmex( "C, IA".$z_motor."M500, R"); send_to_velmex( "C,(IA".$y_motor."M200,IA".$x_motor."M23000,)R"); print "PLEASE REMOVE LID OF PLATE NUMBERS ".($nop+1)." AND ".($nop+2)."\n"; print "After removing lid press return to continue\n"; $platewait = ; } for(my $rhps = 0; $rhps < $replicate_hits_per_spot; $rhps++){ for(my $rspf = 0; $rspf < $replicate_spots_per_filter; $rspf++){ for(my $nof = 0; $nof < $number_of_filters; $nof++){ print "Source Plate = ".($nop+1).", Replicate Spot = ".($rspf+1).", Hit Number = ".($rhps+1).", Filter number = ".($nof+1)."\n"; get_sample($nop%6); put_sample($nof,$current_offset); } #nof # if doing replicate spots up offset $current_offset++; } #rspf #Note: this seems funny but it is better to loop through # all spots and filters before re-hitting in order # to maximize print yield $current_offset = $current_offset - $replicate_spots_per_filter; } #rhps $current_offset = $current_offset + $replicate_spots_per_filter; } #nop # final wash and home wash_pin_tool(); send_to_velmex( "C, IA".$z_motor."M200, R"); send_to_velmex( "C,(IA".$y_motor."M200,IA".$x_motor."M200,)R"); $ob -> write("Q"); undef $ob; exit; ############functions######### ################### # get sample from plate ################### sub get_sample{ my ($plate_number) = @_; # position xy, z = speed change, slow, z = bottom, z = speed change, fast, z = filter&plate height send_to_velmex( "C,(IA".$y_motor."M".$y_plate_positions[$plate_number].",IA".$x_motor."M".$x_plate_positions[$plate_number].",)R"); # send_to_velmex( "C, IA".$z_motor."M".$z_plate_change_speed.", R"); # send_to_velmex( "C, S".$z_motor."M".$z_speed_liquid.", R"); send_to_velmex( "C, IA".$z_motor."M".$z_plate_down.", R"); # my $platewait = ''; # print "After checking position press return to continue\n"; # $platewait = ; # send_to_velmex( "C, IA".$z_motor."M".$z_plate_change_speed.", R"); # send_to_velmex( "C, S".$z_motor."M".$z_speed.", R"); send_to_velmex( "C, IA".$z_motor."M".$z_plate_and_filter_up.", R"); return; } ################### # print sample to filter ################### sub put_sample{ my ($filter_number,$offset_number) = @_; # filternumber + offset my $true_x = $x_filter_positions[$filter_number] + $x_filter_offset_positions[$offset_number]; my $true_y = $y_filter_positions[$filter_number] + $y_filter_offset_positions[$offset_number]; # position xy, z = speed change, slow, z = bottom, z = speed change, fast, z = filter&plate height send_to_velmex( "C,(IA".$y_motor."M".$true_y.",IA".$x_motor."M".$true_x.",)R"); # 1/2 second pause as per sjm Oct 13/05 send_to_velmex( "C, P5, R"); # send_to_velmex( "C, IA".$z_motor."M".$z_filter_change_speed.", R"); # send_to_velmex( "C, S".$z_motor."M".$z_speed_liquid.", R"); send_to_velmex( "C, IA".$z_motor."M".$z_filter_down.", R"); # send_to_velmex( "C, IA".$z_motor."M".$z_filter_change_speed.", R"); # send_to_velmex( "C, S".$z_motor."M".$z_speed.", R"); send_to_velmex( "C, IA".$z_motor."M".$z_plate_and_filter_up.", R"); return; } ################## # wash pins and pause ################## sub wash_pin_tool{ for(my $ii = 0; $ii < 4; $ii++){ #safe height, wash 1, down, shake-n-bake send_to_velmex( "C, IA".$z_motor."M".$z_safe_up.", R"); send_to_velmex( "C,(IA".$y_motor."M".$y_wash_positions[$ii].",IA".$x_motor."M".$x_wash_positions[$ii].",)R"); send_to_velmex( "C, IA".$z_motor."M".$z_wash_down.", R"); send_to_velmex( "C, LM0, I1M100, I1M-100, L5, R"); } # safe height, pause send_to_velmex( "C, IA".$z_motor."M".$z_safe_up.", R"); send_to_velmex( "C, P".$time_of_pause.", R"); return; } ########### # home all 3 axis # go to safe height ########### sub home_machine{ # slow speed send_to_velmex( "C, S2M200, R"); send_to_velmex( "C, S1M200, R"); send_to_velmex( "C, S3M200, R"); # home send_to_velmex( "C, I2M-0, I2M200, IA2M-0,R"); send_to_velmex( "C, I1M-0, I1M200, IA1M-0,R"); send_to_velmex( "C, I3M-0, I3M200, IA3M-0,R"); # return to fast speeds send_to_velmex( "C, S".$z_motor."M".$z_speed.", R"); send_to_velmex( "C, S".$x_motor."M".$x_speed.", R"); send_to_velmex( "C, S".$y_motor."M".$y_speed.", R"); # go to safe height return; } ################ # send commands to the arrayer ################ sub send_to_velmex{ my ($print_command) = @_; # print "Here is the command to send to Velmex ".$print_command."\n"; $ob -> write($print_command); my $result = ''; do{ $result = $ob->input; } until ($result eq '^'); # print "Command Has Now Run, Press Return to Continue\n"; # $wait_for_it = ; return; }