######################################################################## ### FILE: fluidicsarm.mod ### PURPOSE: Composite commands for FLUidics:ARMx branches ### SCOPE: "FLUidics:ARM:" branch. ### ### Copyrights (C) 2010-2011 Life Technologies. All rights reserved. ######################################################################## ALIAS MESSage :PUBLish Fluidics DEFine RinseInside $closeDelay$=0.5 $dropletTouchOff$=False $location$=Rinse $duration$ IF $[ "$location$" != "" ] LOCation $location$ ### Update Rinse tank volume with dispensed volume SYRinge:FACTor? SET volumeFactor $1 SET dispenseVolume $[ $(SYRinge:POSition?) * ${volumeFactor} ] ### Update Rinse Tank volume with rinse volume SET rate $(CONFiguration? -default=0 fluidics_specs.ini RinseRates InteriorWash) SET rinseVolume $[ ${rate} * max(0, $duration$) ] ### Wait for any previous rinse operation to complete before closing valves SYNC RinseClose TRY :FLUidics:SOLenoid:DrainPump1:CONTrol 3 :FLUidics:SOLenoid:InteriorWashValve:CONTrol 3 FLAG -asynchronous EmptySyringe MESSage "RinseInside: Emptying ${dispenseVolume}uL from syringe, rinsing for $duration$s" TRY SYRinge:POSition 0 -pattern=4 SYRinge:HOME WAIT $duration$ VARiable LastRinse $(:SYSTem:TIME?) # Close wash valve, then drain after syringe has been homed :FLUidics:SOLenoid:InteriorWashValve:CONTrol 0 WAIT $closeDelay$ SYNC EmptySyringe :FLUidics:SOLenoid:DrainPump1:CONTrol 0 TRY ":FLUidics:SOLenoid:ExteriorWashValve:CONTrol 0" PASS SYNC -ignoreErrors RinseClose TRY ":FLUidics:SOLenoid:DrainPump1:CONTrol 0" PASS TRY ":FLUidics:SOLenoid:DrainPump2:CONTrol 0" PASS ERRor -id=$error$ $arguments$ "$message$" ### Update volume counts in System Liquid and Rinse tanks; set states SET totalVolume $[ ${dispenseVolume} + ${rinseVolume} ] :FLUidics:RemoveSystemLiquid ${rinseVolume} IF $[ "rinse" in "$location$".lower() ] :FLUidics:AddRinseVolume ${totalVolume} ELIF $[ "waste" in "$location$".lower() ] :FLUidics:AddWasteVolume ${totalVolume} #In some cases, after the rinse, a droplet forms on the tip. To remove #this droplet, this code touches the tip to the plastic poll extending #from the nozzle. The touch is done with the liquid level sensor. IF $dropletTouchOff$ #Activate liquid level sense. :flu:motion:z:liquidlevelsensoractive 0 :flu:motion:z:liquidlevelsensoractive 1 MESSage "RinseInside: DropletTouchOff: Moving 40 counts down" :flu:arm:z:position -relative 40 :flu:motion:z:liquidlevelsensoractive 0 DEFine RinseOutside $closeDelay$=0.5 $pullTime$=1.0 $pullRate$=50 $dropletTouchOff$=False $location$=Rinse $duration$ IF $[ "$location$" != "" ] LOCation $location$ ### Determine how long to stay put, and how many steps to then move SET pulltime $[ min($pullTime$, $duration$) ] ELSE SET pulltime 0 SET staytime $[ $duration$ - ${pulltime} ] SET pullsteps $[ -(abs($pullRate$) * ${pulltime}) ] SYNC RinseClose # Wait for any previous rinse operation to close valves TRY :FLUidics:SOLenoid:DrainPump2:CONTrol 3 # For now open both Drains :FLUidics:SOLenoid:DrainPump1:CONTrol 3 :FLUidics:SOLenoid:ExteriorWashValve:CONTrol 3 :FLUidics:Motion:Z:MPN 5 Wait 0.1 SET Vel $(:FLUidics:Motion:Z:VEL?) SET iVel $(:FLUidics:Motion:Z:IVEL?) FLAG -asynchronous RinsePull MESSage "RinseOutside: Staying for ${staytime}s of total $duration$s rinse time, then pulling up ${pullsteps} steps at $pullRate$ steps/s" WAIT ${staytime} :FLUidics:Motion:Z:VEL $pullRate$ :FLUidics:Motion:Z:IVEL $pullRate$ :FLUidics:ARM:Z:POSition ${pullsteps} -relative -pattern=5 WAIT $duration$ # Wait for the specified duration with valves open # Close wash valve, then asynchronously wait and close drains :FLUidics:SOLenoid:ExteriorWashValve:CONTrol 0 FLAG -asynchronous RinseClose WAIT $closeDelay$ :FLUidics:SOLenoid:DrainPump1:CONTrol 0 :FLUidics:SOLenoid:DrainPump2:CONTrol 0 # And Close both Drains SYNC RinsePull :FLUidics:Motion:Z:MPN 5 Wait 0.1 :FLUidics:Motion:Z:VEL ${Vel} :FLUidics:Motion:Z:IVEL ${iVel} TRY ":FLUidics:SOLenoid:ExteriorWashValve:CONTrol 0" PASS SYNC -ignoreErrors RinseClose TRY ":FLUidics:SOLenoid:DrainPump1:CONTrol 0" PASS TRY ":FLUidics:SOLenoid:DrainPump2:CONTrol 0" PASS ERRor -id=$error$ $arguments$ "$message$" ### Update Rinse Tank volume with rinse volume SET rate $(CONFiguration? -default=0 fluidics_specs.ini RinseRates ExteriorWash) SET rinseVolume $[ ${rate} * max(0, $duration$) ] ### Update volume counts in System Liquid and Rinse tanks; set states :FLUidics:RemoveSystemLiquid ${rinseVolume} IF $[ "rinse" in "$location$".lower() ] :FLUidics:AddRinseVolume ${rinseVolume} ELIF $[ "waste" in "$location$".lower() ] :FLUidics:AddWasteVolume ${rinseVolume} #In some cases, after the rinse, a droplet forms on the tip. To remove #this droplet, this code touches the tip to the plastic poll extending #from the nozzle. The touch is done with the liquid level sensor active. IF $dropletTouchOff$ #Activate liquid level sense. :flu:motion:z:liquidlevelsensoractive 0 :flu:motion:z:liquidlevelsensoractive 1 SET offset $[($pullDistance$ * -1) + 40] MESSage "RinseOutside: DropletTouchOff: Moving ${offset} counts" :flu:arm:z:position -relative ${offset} :flu:motion:z:liquidlevelsensoractive 0 DEFine EmptySyringe $location$=Waste $closeDelay$=0.5 $force$=False SET position $(SYRinge:POSition?) IF $[ ${position} or $force$ ] LOCation $location$ TRY :FLUidics:DrainPump2Open TRY SYRinge:POSition 0 -pattern=4 SYRinge:HOME WAIT $closeDelay$ :FLUidics:DrainPump2Close :FLUidics:DrainPump2Close ERRor -id=$error$ $arguments$ "$message$" ### Update Waste tank volume with dispensed volume SYRinge:FACTor? SET volumeFactor $1 SET dispenseVolume $[ ${position} * ${volumeFactor} ] :FLUidics:AddWasteVolume ${dispenseVolume} DEFine HomeSyringe $force$=False SET Found False IF $[ ($force$ or not $(SYRinge:HOME?) or not $(SYRinge:HOMED?)) ] TRY LOCation Waste SET Found True WARNing "Could not move to 'Waste' location -- not homing syringe" SET Found False IF ${found} IF $(SYRinge:HOMED?) SYRinge:FACTor? SET volumeFactor $1 SET dispenseVolume $[ $(SYRinge:POSition?) * ${volumeFactor} ] :FLUidics:AddWasteVolume ${dispenseVolume} TRY :FLUidics:DrainPump2Open MESSage "HomeSyringe: Homing" TRY SYRinge:HOME SYRinge:HOME SYRinge:HOME WAIT 1 :FLUidics:DrainPump2Close IF ${Open} :FLUidics:DrainPump2Close ERRor -id=$error$ $arguments$ "$message$" ALIas TipCalibrationCheck :FLUidics:CalCheck1 ######################################################################## ### LINE PRIMING DEFine PrimeLine SET IdleTime $[ round($(:SYSTem:TIME?) - ${LastRinse:-0}, 1) ] SET PrimeTime $[ round(min(${PrimeMax}, ${IdleTime} / ${PrimeFactor}), 1) ] IF $[ ${PrimeTime} >= ${PrimeMin} ] SET howlong ${LastRinse:+for ${IdleTime} seconds} SET howlong ${howlong:-since the beginning of time} MESSage "PrimeLine: Delivery line has been idle ${howlong}; priming for ${PrimeTime} seconds" RinseInside ${PrimeTime} DESCribe PrimeLine Prime the delivery line by performing an inside tip rinse. The duration of the priming depends on the elapsed time since the last inside rinse operation, divided by a priming factor and constrained by a minimum threshold and maximum priming time, all of which can be specified with the "PrimeLine=" command. DEFine PrimeLine= $min$ $max$ $factor$ VAR PrimeMin $min$ VAR PrimeMax $max$ VAR PrimeFactor $factor$ DESCribe PrimeLine= Specify how long lines should be primed when the PrimeLines command is invoked (i.e. prior to SURVEY as well as prior to running fluidics script). The inputs are: - Only prime if the priming time exceeds this threshold. Default: 0.5s - Maximum priming time. Default: 30s. - Ratio between elapsed time since the last inside rinse and the desired priming time. Default: 900 (1 second per 1/2 hour idle time). PrimeLine= -min=0.5 -max=30 -factor=1800 DEFine PrimeLine? RETurn -min=${PrimeMin} -max=${PrimeMax} -factor=${PrimeFactor} DESCribe PrimeLine Return the minmum/maximum priming time as well as the ratio between idle time and priming time. ######################################################################## ### Axis test script DEFine AxisTest $min$='' $max$='' $axis$ $count$ SET min $[ "$min$" or "$($axis$:REGISTERS:TRAVELLIMITNEGATIVE?)" ] SET max $[ "$max$" or "$($axis$:REGISTERS:TRAVELLIMITPOSITIVE?)" ] FLAG -asynchronous AxisTest REPeat -counter=count -start=1 $count$ :PUBLish AxisTest "Iteration ${count} of $count$; moving $axis$ to ${min}, then ${max}..." $axis$:POSition ${min} $axis$:POSition ${max} NEXT TRY FLAG- -ignoreMissing AxisTest :PUBLish AxisText "Completed; parking $axis$" PARK $axis$ IF $[ "$error$" == "Aborted" ] PUBLish AxisTest "Aborted; parking $axis$" PARK $axis$ :PUBLish AxisText "Failed; parking $axis$" PARK $axis$ ERRor -id=$error$ $arguments$ $message$ DEFine AxisTest~ FLAG- -abort -ignoreMissing AxisTest ### Force line priming after removing system liquid tank :STATE:TRIGGER -states=SystemLiquid:Installed -edge=Clear ForcePrime FLUidics:ARM:VARiable- -ignoreMissing LastRinse