Flex 8-channel 50ul holds tips at different heights?

I’ve been surprised to see that my Flex 8-channel 50ul appears to hold tips at different heights. For a long time I assumed the difference was in the tips themselves, but I’ve measured them with digital calipers and they’re the same. The difference appears to be that the tip-release metal piece has some molding to release inner tips before outer tips, and since it rests on the tips it slightly pushes inner tips further down. Has anyone else noticed this? I find it relatively shocking and it leads to very bad partial pipetting precision performance.

I’m not sure how obvious it is in this picture (the right tip is lower) but it’s very real:


2 Likes

Hey @april - can you send this to support@opentrons.com and copy meghan.ferzoco@opentrons.com? This isn’t normal behavior, and I want to ensure we get to the root cause of this for you.
Thanks!

Thank you Meghan! Just sent an email, glad to hear it’s not normal

2 Likes

Well, to follow up, here’s what I learned:

  • The API offers PARTIAL_COLUMN mode for the 8-channel multichannel and allows asking for start="A1": API Version 2 Reference — Opentrons Python API V2 Documentation
  • However start="A1" is not configured in the pipette definitions for the 8-channel aside from SINGLE and it fails at run-time: opentrons/shared-data/pipette/definitions/2/general/eight_channel/p50/3_5.json at edge · Opentrons/opentrons · GitHub
  • There was a suggestion to use SINGLE and then just position the pipette head over a partial column of tips, which would cause the head to pick up more than one tip. So I was doing that
  • Doing that causes this problem because SingleA1 in the pipette definition configures different distances and tipOverlaps for SingleA1 vs eg H1toE1
  • I wasted a loooooot of time before I dove deep enough into the Opentrons codebase to figure this out (ps thank you Opentrons for having an open source codebase)
  • Opentrons FAS says that they put in a feature request to add A1toB1 etc but gave no ETA. I doubt it will land any time soon. They also asked why I care, which is a funny question because you cannot use the 8-channel multichannel with only 3 tips on the thermocycler trying to hit well A1 when start="H1". I had thought the why would be fairly obvious but I get the sense that no one else actually uses PARTIAL_COLUMN

Anyway, in the absence of that feature request being implemented, I came up with a hack to get PARTIAL_COLUMN working with start="A1".

def patch_pipette_loading():
    from opentrons_shared_data.pipette.pipette_definition import PipetteConfigurations

    original_model_validate = PipetteConfigurations.model_validate

    def evil_model_validate(obj, *args, **kwargs):
        valid_maps = obj["validNozzleMaps"]["maps"]
        configurations = obj["pickUpTipConfigurations"]["pressFit"]["configurationsByNozzleMap"]
        if obj["channels"] == 8:
            start = "A1"
            ends = ["B1", "C1", "D1", "E1", "F1", "G1"]
            for i, end in enumerate(ends):
                key = f"{start}to{end}"
                if key in valid_maps:
                    continue
                reverse = f"H1to{ends[len(ends) - 1 - i]}"
                if config := configurations.get(reverse):
                    configurations[key] = config
                    valid_maps[key] = [start] + ends[:i + 1]
        return original_model_validate(obj, *args, **kwargs)

    PipetteConfigurations.model_validate = evil_model_validate

patch_pipette_loading()

Which worked great, until I noticed I was getting super wonky z-height accuracy on aspirate/dispense. I used liquid level detection to detect the same liquid heights across every tip configuration on the multi-channel and it seems quite inconsistent (ignore the outliers). I assume it’s something to do with my hack but don’t have the time or energy to debug further right now.

So, long story short, I’ve given up on the mult-channel pipette

2 Likes

Hey April, thanks for much for leaving this feedback- I learned something new today. I’ve asked our documentation team to add your thermocycler partial tip pickup limitations to our public API so we don’t have additional frustrated customers in the future.

2 Likes

Hi April, were you able to figure this out? I’m trying to use PARTIAL_COLUMN, and can get the tips to pick up, but can’t get it to dispense in the correct location. I’m having start be H1 and end be D1… I’d appreciate any help you can give. Thank you!

What does “dispense in the correct location” mean in this context? Are the tips incorrectly offset vertically? Or is it something else? I have never tried start="H1" but I assumed that was the only configuration where this feature worked. I guess it would explain why my solutions for start="A1" didn’t work if start="H1" doesn’t even work…

After writing my post about start="A1" I reverted back to single-channel pipetting and gave up on partial.

I’ve since discovered used Hamiltons are very cheap, found a Hamilton Nimbus 8-channel on eBay for $1,500, and wrote a simple library to control it: GitHub - escalante-bio/piglet: A Rust library designed to control IP-based Hamilton robots . I have much more hope about this approach to partial column pipetting.

I’m trying to pick up 5 tips starting at H1, then aspirate from a reservoir, and dispense in a sample plate (A1-E1). My issue is that it tries to dispense the contents of H1 into well A1 of the sample plate and the rest just spills onto the deck.

UPDATE: I got it to work, forgot that the ‘primary pipette’ automatically goes back to A1, so just named the dispense location well to ‘E1’ and it seems to work? Still testing.

1 Like

Happy to hear it’s working for you! If you use LLD, I’d love to know if you see consistent liquid z-heights depending on the tip count. It’d be great if I’m just doing something wrong :slight_smile:

1 Like

The protocol I’m working on right now doesn’t include it, but it may in the future. I’ll definitely let you know if I add it! Yeah, I thought I was going crazy with all the errors I was getting. :sweat_smile: