Hendricks-Laboratory / OT2Control

software to provide detailed control of Opentrons OT2 robot
7 stars 7 forks source link

Tip still touches liquid during deposit when filling tube from empty #51

Closed Hendricks-Laboratory closed 2 years ago

Hendricks-Laboratory commented 2 years ago

The tip shouldn't touch the liquid level because this will lead to contamination of the source. I'm pretty sure it only happens when filling from empty due to the dead-volume calculation, and it only touches a little bit right around the beginning of the cylinder portion of the tube (when the dead volume is near full).

Hendricks-Laboratory commented 2 years ago

Here's the code at issue here:

image image

The problem is that we're setting the liquid height to the minimum height (4 mm) if it's below the bottom of the cylinder height (30.5 mm). And then to determine the dispense height we just add 20 mm to the liquid level height. But if we're almost at the bottom of the cylinder height, let's say at 30 mm, then it still says the height is the minimum height and the dispense height is this plus 20, so 24 mm. That means we should be going 6 mm into the solution for the dispense (in actuality I don't think it's this bad, it's closer to 2-3 mm). One way to solve this is to increase the disp_height calculation to height + 27 mm, but that's getting pretty ridiculous, particularly for the 2 mL tubes. I think instead we should define the disp_height separately for each type of tube, like we do for the asp_height.

Hendricks-Laboratory commented 2 years ago

Here are some example changes we could make:

for class Tube20000uL(Tube):

@property
def disp_height(self):
    min_disp_height = 40 #mm above the bottom of the tube
    disp_height_above_liquid = 10 #mm above the liquid level
    return self.height + disp_height_above_liquid if self.height > height_bottom_cylinder else min_disp_height

for class Tube50000uL(Tube):

@property
def disp_height(self):
    min_disp_height = 30 #mm above the bottom of the tube
    disp_height_above_liquid = 10 #mm above the liquid level
    return self.height + disp_height_above_liquid if self.height > height_bottom_cylinder else min_disp_height

for class Tube2000uL(Tube):

instead of using the bottom of the cylinder as the cutoff for this one, I've hardcoded in a separate cutoff value so this one will dispense from around the top always, which I think is better for these small tubes.

@property
def disp_height(self):
    height_disp_cutoff = 32 #mm above the bottom of the tube
    min_disp_height = 40 #mm above the bottom of the tube
    disp_height_above_liquid = 7 #mm above the liquid level
    return self.height + disp_height_above_liquid if self.height > height_disp_cutoff else min_disp_height
kaplannp commented 2 years ago

That looks great to me!
I made one minor change to the 20 and 50mL. I replaced the return statement with,

        return max(self.height + disp_height_above_liquid, min_disp_height)

which I think accomplishes what you wanted and is a little easier to understand since min_disp_height is actually the minimum height you can dispense at now. Can easily change back if you prefer the if statement.

The 2000 uL tube, I left exactly as is.