Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: Multiple blow outs do not work as expected #7356

Open
MarcelRobitaille opened this issue Feb 18, 2021 · 7 comments
Open

bug: Multiple blow outs do not work as expected #7356

MarcelRobitaille opened this issue Feb 18, 2021 · 7 comments
Labels
api Affects the `api` project bug robot-svcs Falls under the purview of the Robot Services squad (formerly CPX, Core Platform Experience). software-investigate Our Software team needs to look into this so we can understand more about it. workaround available This issue has a workaround available, though it isn't necessarily totally fixed.

Comments

@MarcelRobitaille
Copy link

Overview

For use, sometimes one blow_out isn't enough to get rid of all the liquid. When I try calling it twice, nothing happens for the second one. I also tried to put a touch_tip before the second blow_out, thinking that might make it reset. It just does the touch tip and moves on to trash.

Steps to reproduce

In a protocol, write:

pipette.blow_out()
pipette.blow_out()

Current behavior

Tip is only blown out once.

Expected behavior

Tip is blown out, plunger goes up again, and blows out again.

@mcous mcous added api Affects the `api` project software-investigate Our Software team needs to look into this so we can understand more about it. workaround available This issue has a workaround available, though it isn't necessarily totally fixed. and removed software-investigate Our Software team needs to look into this so we can understand more about it. labels Feb 18, 2021
@mcous
Copy link
Contributor

mcous commented Feb 18, 2021

Examined the code in question, and I can see why this behavior is happening. The first blow out leaves the plunger at the bottom of the pipette, in the blowout position. When the second blowout comes along, the plunger is told to move to the location that it's already at, so it does nothing.

I don't know why the plunger isn't reset as part of the blowout procedure (there might be a good reason not to do so), but that strikes me as a potential avenue to fix this.

In terms of a workaround, the only thing in the public API that is able to reset the plunger position is an aspirate. I wonder if something like this would work?

pipette.blow_out()
pipette.aspirate(volume=0.001)  # some tiny volume rather than `0`, since `0` means "as much as possible"
pipette.blow_out()

@MarcelRobitaille
Copy link
Author

Thanks for the answer. I tried that just now. The aspirate makes the tip move up a little bit before aspirating and then back down for the second blow out. I thought aspirate with location=None was supposed to use the current position? Anyway, thanks for the workaround. I am happy to have this closed now, but maybe you want to keep it open to see about fixing bringing the plunger up immediately?

@MarcelRobitaille
Copy link
Author

Since you say there might be a reason to not reset the plunger immediately after the blow out, how about checking if the plunger has to be brought up at the start of blow_out like aspirate does?

@mcous
Copy link
Contributor

mcous commented Feb 18, 2021

Thanks for the answer. I tried that just now. The aspirate makes the tip move up a little bit before aspirating and then back down for the second blow out. I thought aspirate with location=None was supposed to use the current position?

What you're hitting here is a particularly confusing (to me) piece of logic where, if the aspirate procedure decides the plunger needs to be reset due to a blowout, it tries to move to a "safe" location at the top of its current well before resetting the plunger. In this case, because you've used location=None, the procedure is pulling the "current well" from its last move.

Anyway, thanks for the workaround. I am happy to have this closed now, but maybe you want to keep it open to see about fixing bringing the plunger up immediately?

For sure keeping this ticket open! This is a bug and needs to be fixed; we're in the process of figuring out where the current behavior (don't reset plunger after blowout until aspirate time) comes from so we can implement the safest fix.

Since you say there might be a reason to not reset the plunger immediately after the blow out, how about checking if the plunger has to be brought up at the start of blow_out like aspirate does?

This is definitely on the list of available fixes. Might even be the most likely one!

@mcous mcous added the robot-svcs Falls under the purview of the Robot Services squad (formerly CPX, Core Platform Experience). label Feb 23, 2021
@silvtal
Copy link

silvtal commented Sep 16, 2021

Hi, just wanted to comment on this a little bit. I have a protocol that tries to do this:

# after dispensing some glycerol:

# 1 Residual liquid is removed with slower blow_out() at slower flowrate
p20multi.blow_out(well.bottom(mm))                  

# 2 move_to() from liquid to top of labware at 1-5 mm/s      
p20multi.move_to(well.top(mmt), speed=vel_exit_liquid)

# 3 move_to() to bottom of labware at 10 mm/s speed to aspirate
p20multi.move_to(reservoir.wells_by_name()[reservoir_well_name].bottom(mm))

# 4 aspirate() (at slower flowrate)
p20multi.aspirate(20,                                             
                 reservoir.wells_by_name()[reservoir_well_name].bottom(mm))

What happens here in practice is that the pipette goes to the bottom of the reservoir well as per step 3, but after that, since the plunger is still down after the blowout, it moves back to the top to (I guess) return the plunger to its default position, then waits there 10 seconds and then does step 4.

There's a bit of time waste there, but the big problem is that when it comes out the well between steps 3 and 4, the pipette is full of glycerol and that glycerol ends up absorbed , so the pipette ends up dispensing 21 or so uL instead of 20.

If I didn't explain myself clearly I'm happy to clarify. The thing is, this can become a big problem and, if you don't figure it out early, a big headache. I'm surprised that this hasn't been fixed yet as of September 2021.

@mcous
Copy link
Contributor

mcous commented Sep 16, 2021

Hey @silvtal, in this case, why is the (3) move_to call needed? Setting aside the behavior of "blow out reset doesn't happen until next aspirate" behavior, I would expect p20multi.aspirate(20, reservoir.wells_by_name()[reservoir_well_name].bottom(mm)) to work without the preceding move_to. By itself, the aspirate call should:

  1. Move to top of well to reset plunger after blowout (might be a no-op because of the preceding move in (2))
  2. Reset plunger motor while at the top of the well
  3. Move to the bottom(mm) position
  4. Perform the aspiration

Is it not doing that, or is there something about how it's doing that that's not working for your needs?

I'm surprised that this hasn't been fixed yet as of September 2021.

After my last comment in the thread, I shopped this around internally, and we're sort of in a difficult spot with blow-out. In general, protocol API v2 has some fairly fundamental architectural limitations that make changes like this a little fraught. Where that comes up with blow-outs specifically is: it's pretty difficult for the robot to know the answer to the question "is the pipette tip currently in liquid?"

This is a really important question when it comes to resetting after a blow-out, because if you answer the question incorrectly, you risk damaging the pipette hardware itself by sucking up liquid into the internals. The current behavior, while annoying a lot of the time, is a way of ensuring we pick a reliably not-risky spot to perform the plunger reset in the architecture we currently have.

We're in the middle of an overhaul of the protocol execution engine with the goal of making these sort of changes much less risky. But as it turns out, re-writing our the execution engine to address core architectural limitations while keeping everything else working takes... a lot more time than I thought 🙃. We are working on it, though! I recommend following along with the protocol-engine issue label if you're curious about watching this work progress

@silvtal
Copy link

silvtal commented Sep 17, 2021

Thank you for your hard work. As for your question,

why is the (3) move_to call needed?

you're absolutely right and I skipped that step in my updated code. The only reason I included that step is because I took that idea verbatim from your latest glycerol handling webinar, see page 13. https://f.hubspotusercontent30.net/hubfs/5383285/Automating-Viscous-Liquid-Handling_09-09-2021_Opentrons-Webinar-slides.pdf?utm_campaign=2021_Webinars_Viscous-Liquids_09-09-2021&utm_medium=email&_hsmi=157751988&_hsenc=p2ANqtz-94wprFwoIxGOjyCNCuaoELTtZsI5g7KMg3hjTmRhDyFONRlxSudmZPEhknhKV7knvLpoiWQz5den2lrEm1NrgORlLOmg&utm_content=157751988&utm_source=hs_email . Note that they also included a blow_out step in the dispense part, so this issue was bound to happen if you do sequential aspirate-dispense steps.

I don't have the OT2 here right now so I can't check, but I guess aspirate would move to the .top(0) (or whatever the default is) of the reservoir instead of .top(mmt). So in order to keep the .top(mmt) height I might need to do a aspirate(0.001,well.top(mmt)) to reset the plunger "manually" first. Thank you again for that workaround idea

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api Affects the `api` project bug robot-svcs Falls under the purview of the Robot Services squad (formerly CPX, Core Platform Experience). software-investigate Our Software team needs to look into this so we can understand more about it. workaround available This issue has a workaround available, though it isn't necessarily totally fixed.
Projects
None yet
Development

No branches or pull requests

3 participants