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

Set up Opentrons Flex #150

Open
sgbaird opened this issue Jan 15, 2025 · 16 comments
Open

Set up Opentrons Flex #150

sgbaird opened this issue Jan 15, 2025 · 16 comments
Assignees

Comments

@sgbaird
Copy link
Member

sgbaird commented Jan 15, 2025

The Opentrons Flex should still be in its box on the first floor. It will need two people to unpack and lift it onto one of the benches, but the rest should be OK to set up with a single person. I'm having a router sent over there (2-5 day shipping), so you should be able to connect the Flex to that network. There are two Flex pipettes and a Flex gripper that can go over with you.

@MatPopp
Copy link

MatPopp commented Jan 16, 2025

20250116_133022.jpg

It is starting up and homing of the gantry works.

@MatPopp
Copy link

MatPopp commented Jan 21, 2025

Documentation: Setting up the pressure sensor of OpenTronsFlex (aiming at #141)

  • Installation of OpenTronsFlex according to quick start guide

  • Start JupyterLab

    • start Opentrons App on PC
    • Robot Settings -> Advanced Tab -> launch Jupyter Notebook (google for mor details, it is simple to find)
  • copied python files to jupyter lab root folder from https://github.com/Opentrons/opentrons/tree/edge/hardware/opentrons_hardware/scripts

    • sensor_utils.py
    • sensors.py
  • tried with console

    • go to directory of scripts:
      cd /var/lib/jupyter/notebooks
    • execute sensor script: python3 sensors.py -> a prompt will occur that asks for which quantity to measure
    • this will produce a .csv file with sensor data. Touching the pipette during the measurement time will result in changing values. (The sensor seems to be sensitive)

Reading pressure sensor from python without cli

  • minimal working example:
from opentrons_hardware.sensors.types import SensorDataType, EnvironmentSensorDataType
from opentrons_hardware.drivers.can_bus import DriverSettings, settings, build

from opentrons_hardware.drivers.can_bus.can_messenger import CanMessenger
from opentrons_hardware.drivers.can_bus.abstract_driver import AbstractCanDriver
from opentrons_hardware.firmware_bindings.constants import NodeId, SensorType, SensorId
from opentrons_hardware.sensors import sensor_driver, sensor_types


driver_settings = DriverSettings(
        interface=settings.DEFAULT_INTERFACE,
        port=settings.DEFAULT_PORT,
        host=settings.DEFAULT_HOST,
        bit_rate=settings.DEFAULT_BITRATE,
        channel=settings.DEFAULT_CHANNEL,
    )
node_id = NodeId.pipette_left # from https://github.com/Opentrons/opentrons/blob/edge/hardware/opentrons_hardware/scripts/sensors.py
pressure_sensor = sensor_types.PressureSensor.build(SensorId.S0, node_id)
s_driver = sensor_driver.SensorDriver()


async def track_pressure():
    async with build.driver(driver_settings) as driver:
        
        messenger = CanMessenger(driver=driver)
        messenger.start()
        for i in range(10):
            data = await s_driver.read(messenger, pressure_sensor, offset=False, timeout=10)
            print("current pressure (in ?):", data.to_float())
        await messenger.stop()
    
await track_pressure()

reading pressure sensor while aspirating and dispensing

from opentrons_hardware.sensors.types import SensorDataType, EnvironmentSensorDataType
from opentrons_hardware.drivers.can_bus import DriverSettings, settings, build

from opentrons_hardware.drivers.can_bus.can_messenger import CanMessenger
from opentrons_hardware.drivers.can_bus.abstract_driver import AbstractCanDriver
from opentrons_hardware.firmware_bindings.constants import NodeId, SensorType, SensorId
from opentrons_hardware.sensors import sensor_driver, sensor_types

import time

driver_settings = DriverSettings(
        interface=settings.DEFAULT_INTERFACE,
        port=settings.DEFAULT_PORT,
        host=settings.DEFAULT_HOST,
        bit_rate=settings.DEFAULT_BITRATE,
        channel=settings.DEFAULT_CHANNEL,
    )
node_id = NodeId.pipette_left # from https://github.com/Opentrons/opentrons/blob/edge/hardware/opentrons_hardware/scripts/sensors.py
pressure_sensor = sensor_types.PressureSensor.build(SensorId.S0, node_id)
s_driver = sensor_driver.SensorDriver()


async def track_pressure(duration_s = 1, debug = False):
    async with build.driver(driver_settings) as driver:
        
        t_start = time.time()
        
        times = []
        pressures = []
        
        messenger = CanMessenger(driver=driver)
        messenger.start()
        while time.time()-t_start < duration_s:
            data = await s_driver.read(messenger, pressure_sensor, offset=False, timeout=10)
            if debug:
                print("current pressure (in ?):", data.to_float())
            times.append(time.time()-t_start)
            pressures.append(data.to_float())
        await messenger.stop()
    
    return(times,pressures)

import asyncio
from threading import Thread
import time

def aspirate_dispense_sensed():
    
    results = []
    def track_pressure_sync(exchange_list):
        loop = asyncio.new_event_loop()
        times, pressures = asyncio.run(track_pressure(duration_s = 20))
        results.append((times, pressures))

    def aspirate_dispense():

        for i in range(3):
            position_1 = plate["A2"].bottom(z=2) # tip is 20 mm above well bottom
            print("aspirate")
            left_pipette.aspirate(100, position_1)
            
            time.sleep(1)

            position_2 = plate["A1"].bottom(z=2) # tip is 20 mm above well bottom
            print("dispense")
            left_pipette.dispense(100, position_2)
            
            time.sleep(1)

    t = Thread(target=track_pressure_sync, args = [results])
    t.start()
    aspirate_dispense()
    print("waiting for sensing to finish")
    t.join()
    times_ret, pressures_ret = results[0]
    return(times_ret, pressures_ret)

times, pressures = aspirate_dispense_sensed()

working with pip install

TODO: install git on the OT Flex

@sgbaird and @Neil-YL can you by chance point towards an easy solution?

@MatPopp
Copy link

MatPopp commented Jan 21, 2025

Measuring the pressure while tapping with the finger on the open pipette tip:

Image

Measuring pressure while pipetting water from one well to another (waiting for 1s after aspirating/dispensing):

Image

Pressure curve during actual aspiration:

Image

Exponential decay after aspiration:

Image

Comment: the calculated decay time here is 0.58 s which is much higher than in previous syringe experiments. Possible reasons:

  • larger "dead" volume compared to syringe experiment
  • different tip geometry? (smaller diameter?)
  • side effects that I do not fully understand, so far.

@sgbaird
Copy link
Member Author

sgbaird commented Jan 21, 2025

Wow! Very impressive you got this to work. Sounds like it took a lot of troubleshooting and I'm sure a lot of digging through the codebase. Thank you for the thorough documentation of steps, too 🙌

I'll look into installing git. Could you comment on what you intend to use it for? E.g., pushing changes to a repo while you're developing vs. cloning packages, etc. This might help during my search.

@Neil-YL
Copy link
Contributor

Neil-YL commented Jan 21, 2025

working with pip install

In this article

Certain packages can't be installed
Some of the more sophisticated Python packages, like NumPy, aren't written purely in Python. Parts of them are written in other languages, like C.

You won't be able to install those packages on the OT-2. They require a compiler, which the OT-2 doesn't have.

Also the protocol to run on the machine should be a single self-contained Python file so I think it would not encourage you to use git on the machine.
I am also working on changing our liquid color matching demo from SSH to MQTT and I am planning to run a single python file on the OT2's jupyter notebook, but in my case I believe all the packages I need are all pre-installed.

@MatPopp
Copy link

MatPopp commented Jan 21, 2025

Wow! Very impressive you got this to work. Sounds like it took a lot of troubleshooting and I'm sure a lot of digging through the codebase. Thank you for the thorough documentation of steps, too 🙌

Thanks!

I'll look into installing git. Could you comment on what you intend to use it for? E.g., pushing changes to a repo while you're developing vs. cloning packages, etc. This might help during my search.

Intended use:

  • push scripts from the OT Flex jupyter to a safe place
  • maybe work with jupyter notebooks for combined code + documentation of experiments, use git for sharing.
  • cloning packages would of course also be useful

@MatPopp
Copy link

MatPopp commented Jan 21, 2025

Also the protocol to run on the machine should be a single self-contained Python file so I think it would not encourage you to use git on the machine. I am also working on changing our liquid color matching demo from SSH to MQTT and I am planning to run a single python file on the OT2's jupyter notebook, but in my case I believe all the packages I need are all pre-installed.

It has to be a single python file only if it is started via the display on the machine, right? (which I agree is very useful)

When connecting to OT Flex via jupyter lab, however, I can execute single movement commands within cells (video will follow)

@Neil-YL
Copy link
Contributor

Neil-YL commented Jan 21, 2025

Also the protocol to run on the machine should be a single self-contained Python file so I think it would not encourage you to use git on the machine. I am also working on changing our liquid color matching demo from SSH to MQTT and I am planning to run a single python file on the OT2's jupyter notebook, but in my case I believe all the packages I need are all pre-installed.

It has to be a single python file only if it is started via the display on the machine, right? (which I agree is very useful)

When connecting to OT Flex via jupyter lab, however, I can execute single movement commands within cells (video will follow)

In the same article above:


Can I upload protocols comprising multiple Python files through the Opentrons App?
Not currently.

Instead, write your protocol so that it's a single self-contained Python file.

Or, as described above, collect your additional files into a package, and use pip to install it.

My understanding is it does not support to use class or function by imported from other py file? You have to either write everything in one file or pack everything into a package.

I realized it is talking about through app.
You are right

@MatPopp
Copy link

MatPopp commented Jan 22, 2025

For handling raw materials a Rack with holders for larger vials would be useful.
@Neil-YL could you 3D-Print one of the racks that is curerntly in use with the OT-2 or send me the corresponding CAD files?

@Neil-YL
Copy link
Contributor

Neil-YL commented Jan 22, 2025

For handling raw materials a Rack with holders for larger vials would be useful. @Neil-YL could you 3D-Print one of the racks that is curerntly in use with the OT-2 or send me the corresponding CAD files?

I think the vial rack I am using now is printed by other scientist. I don't have the CAD file either, but I can make one quickly for you now.

@sgbaird
Copy link
Member Author

sgbaird commented Jan 22, 2025

@cyrilcaoyang I believe you might have the CAD file for the vial holder with six slots that fits the pioreactor vials?

@Neil-YL
Copy link
Contributor

Neil-YL commented Jan 22, 2025

I measured the current one and sent it to print. Would you like to pick it up tomorrow? @MatPopp

Vial_rack v1.step.zip

@Neil-YL
Copy link
Contributor

Neil-YL commented Jan 22, 2025

For handling raw materials a Rack with holders for larger vials would be useful. @Neil-YL could you 3D-Print one of the racks that is curerntly in use with the OT-2 or send me the corresponding CAD files?

@sgbaird Just a reminder we may need to order more vials of this size.

@MatPopp
Copy link

MatPopp commented Jan 23, 2025

I measured the current one and sent it to print. Would you like to pick it up tomorrow? @MatPopp

Vial_rack v1.step.zip

great, thanks! :)
I'll probably pick it up at the weekend. Could you place it on my desk?

@Neil-YL
Copy link
Contributor

Neil-YL commented Jan 23, 2025

I measured the current one and sent it to print. Would you like to pick it up tomorrow? @MatPopp
Vial_rack v1.step.zip

great, thanks! :) I'll probably pick it up at the weekend. Could you place it on my desk?

Image

@MatPopp
Copy link

MatPopp commented Jan 24, 2025

Fixing pressure leakage issues

problem description

  • on first tests on pressure decay times, I found out that the measured decay time for soap was the same as for water -> either they have the same viscosity, or there was some other reason for pressure decay -> either leak or intentional software decay time.
  • I aspirated some water with the tip being immersed under the surface in order to rule out surface tension effects: the following video shows, how the water level drops, without the plunger moving -> the pipette was (very) untight:
    https://github.com/user-attachments/assets/c7eacc2a-5be0-4f31-ad68-5898b9a662fc

Documentation of opening and fixing the pipette:

  • I unsrewed the top lid of the pipette with a small tx ?? screwdriver (not included in kit, many other tools were thankfully included). The lid could be slided roughly 5 mm to the top and then needed some force to release the clamping brackets.
    Image
  • the metallic part right next to the spindle is the plunger. Some transparent grease was distributed on the plunger, in my case a bit uneven. I decided to spread it as well as possible with a screwdriver.
  • to view all possible points of pressure leakage, I unscrewed the black plastic part from the release mechanism, which revealed the metallic pipette cylinder:
    Image
  • unscrewing the 3 black screws, I could unmount the cylinder. This took some force.

Image

  • The turquoise o-rings seemed dry, so I spread some of the grease from the end of the cylinder across the o-rings to close potential leaks.

  • The revealed black chamber probably serves as connection to the pressure sensor. I guess it is mounted on the PCB on the left.

  • I looked into the the chamber:
    Image

  • and found that the grease at the intersection to the plunger (inner circle in the picture) was asymmetrically distributed. I stirred it with a screwdriver for the case that the connection between the black plastic chamber and the plunger caused the leakage.

  • I reassembled all functional parts and took the chance to operate the pipette with open lid (video):
    https://github.com/user-attachments/assets/8f4a2cef-5b20-4d88-896b-ae19d7305ffe

  • to check for functionality I measured some pressure curves. (plots are currently saved in the jupyter lab on the opentrons, might follow in edits)

  • everything seems to be thight, now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants