Skip to content

DIY - Openware para laboratorio

Listado de subpáginas:

Articulos y notas

Perfiles interesantes

Software

LIMS

LIMS es "Laboratory Information Management System". OpenBIS es uno de ellos.

Hay más: https://open-neuroscience.com/post/lab-management-software/

OpenBIS

Documentacion de OpenBIS: https://unlimited.ethz.ch/display/openBISDoc2010/openBIS+20.10+Documentation

Demo: https://openbis.ch/index.php/demo/#demo

Video tutoriales: https://openbis.ch/index.php/screencasts/#video%20tutorials

Repositorio: https://sissource.ethz.ch/sispub/openbis

Desgargas:

OpenBIS Docker

Ver:

Comandos:

# Para instalar OpenBIS
docker pull openbis/debian-openbis:latest

# Para iniciar OpenBIS
sudo docker run -p443:443 openbis/debian-openbis &
## Visitar: https://localhost:443      ####
## Visitar: https://localhost/openbis/ ####
## u: admin    ####
## p: changeit ####

# Para detener el container
sudo docker container list
sudo docker stop 675acf59bfc8

La contraseña se cambia con variables en el Dockerfile.

Wetware

Ni hardware, ni software, wetware serían los reactivos y organismos que se usan en el labo de biología:

FreeGenes project

https://stanford.freegenes.org/

Hardware

Otros sitios y proyectos interesantes

Gaudi Labs tiene un montón de cosas copadas:

Talleres Opensource:

Cosas de neuroscience (usualmente no tan específicas):

Otros:

To-do:

Proyectos:

Cursos

http://instrumentacion.qi.fcen.uba.ar/

Microscopía

Con un celu: https://www.nature.com/articles/s41598-018-21543-2#Sec1

Con un microscopio y usando el celu como cámara: https://www.thingiverse.com/thing:3020917

OFM

Para comprar y usar un objetivo 40x con el OFM hay que entender algunas cosas de óptica y estándares de microscopios: https://www.edmundoptics.com/knowledge-center/application-notes/microscopy/understanding-microscopes-and-objectives/

Ver ahí "The Objective Standard" la parte de "fixed length objectives".

Ver también:

Entiendo de todo eso que los objetivos "finite" / "fixed tube length".

Vienen en dos estándares. Lo importante para el OFM es de "160 mm", y tambien dice que importa el "parafocal length" es 35 mm o 45 mm, dependiendo de si se usa el sample riser del OFM.

En el primer link dice:

The DIN standard has a 160mm distance from the objective flange to the eyepiece flange.

Joya, necesito uno DIN, pero más adelante en el mismo sitio se dice:

Lastly, there is a dimension typically listed for objectives to allow the user to consistently know what length it is: the parfocal distance (PD).

The parfocal distance is the distance from the flange of the objective to the object under inspection.

For DIN objectives this distance is a standard 45mm and for JIS is it 36mm

Y eso es un poco confuso, porque el manual habla sobre dos distancias parafocales, pero solo sobre un tube length. 🤷

Más confuso respecto a lo estándar es que el OFM usa un "tube lens" antes del sensor de la cámara (ver manual). Y se supone que este tipo de microscopio no tiene "tube lens".

En teoría un objetivo "fixed" genera una imagen magnificada real, que luego es magnificada por el lente ocular. ¿Por qué no se usa la del objetivo directamente? La imagen magnificada por un ocular es virtual, osea que no se podría formar una imagen sobre el sensor del raspberry pi, y en el microscopio convencional esa imagen real se enfoca o proyecta sobre la retina solamente a través del lente del ojo.

Entonces: ¿como funciona el OFM?

Expectativa: compstd.zip

20211224-233128.png

Realidad?: compofmmaybe.zip

20211224-233538.png

En el segundo sistema, el segundo lente se corrió para que forme una imagen magnificada real (o sea con el objeto mas lejos del lente que su distancia focal). Esa es la proyección que necesita el OFM.

Acá explica bien lo que pasa: https://build.openflexure.org/openflexure-microscope/v6.1.5/docs/#/parts/optics/tube_lens

La idea es acortar la distancia a la que se forma la imagen del objetivo, para que se forme antes (sobre el sensor de la cámara) en vez de a los 160 mm o lo que sea. Algo así: compofmmaybe2.zip

20211225-000113.png

Aparentemente en la simulación, eso achica la imagen final. Si los pixeles del sensor resuelven todo igual, entonces no hay pérdida real.

Salvo que las correcciones del objetivo se degraden por usar un lente que no debería estar.

Quizas por eso eligieron un "achromatic doublet" como lente de "tubo" (ver manual).

Ver también:

Termociclador - PCRrera

Un viejo proyecto (en pausa).

Docs: https://drive.google.com/drive/folders/0Bx7ffAgTk0buTmR4ZjI1bDBFMGM

Code: https://github.com/naikymen/Plataforma-Increible-Argenta

20201201-122049.png

screenshot_20201201_172131.png

screenshot_20201201_172236.png

Robot pipeteador

Ver la página del proyecto.

20201201-122415.png

20201201-122447.png

20201201-122607.png

20201201-123915.png

Work in progress...

Espectrofotómetro

Proyectos interesantes:

Centrífuga

Proyectos:

Rpm counter:

Reciclado de motores:

HDD Centrifuge

Ver: proyectos/diy/upcycle

Para tubos de 0.5 mL.

Da entre 1000 g (5400 RPM) y 3000 g (7200 RPM).

Hay que cortar piezas de acrílico para altas velocidades, las de plástico de impresora 3D no son adecuadas.

Quizás podría agregarle algún sistemita de swing para que al detenerse el tubo quede parado (y no acostado como en el diseño original).

Cableado y partes: https://www.youtube.com/watch?v=WDrRPRUpvgg&feature=share

Hay que conseguir un ESC (que sale 1400 pesos) o armar algo de cero, ver la página para eso.

Auto-balanceo

Ver: proyectos/mecanica

Pipeta electrónica

Una bomba de diafragma: https://hackaday.com/2020/12/02/diaphragm-air-engine/

Servos para pipetear

Problemas:

  • La resolución angular de un servo controlado por el PWM de GRBL no es muy alta.
  • El servo tiene algo de "rebote". La inercia del movimiento interno del servo hace que se "pase" un poco y luego vuelva a donde debería haber frenado en un principio.

Soluciones: usar el servo para trasladar la pipeta en Z y el stepper para pipetear.

Alternativas:

  • Usar un stepper (con algun feedback mejor) directamente sobre el shaft de la pipeta. Por ejemplo alguno pequeño de estos: https://www.pololu.com/category/87/stepper-motors
  • Usar un embolo con resortes mucho más blandos, no es necesario que sean tan duros en este caso, pero significa que no puedo usar muchas micropipetas directamente.

Servos:

Closed-loop control

20200711-102206.png

Movimiento lineal

Control remoto

20191118-073122.png

Música

Servo-pipeta

Thing: https://www.thingiverse.com/thing:3985878

Models: https://www.tinkercad.com/things/2ZC4g48iKkl-pipette-dock/

photo_2019-11-18_22-30-23_crop.jpg

Ese servo era bastante malo, se movia solo! y la fuerza que opone el resorte de la pipeta es bastante grande.

Servo-jeringa

Ideas:

Seria mas facil quizas, hacer algo por mi cuenta que adaptar otra cosa. Que osa el Opentrons OT-2?

Antecedentes:

Mecánica de sellos

Diafragma simple de la BiroPette:

Notas y artículos:

Stepper para pipetear

Análogo al eje "E" de las impresoras 3D. Usar un Arduino para esto es "trivial", hay librerías para eso y muchos ejemplos.

Control directo con RPi y Driver

Usando un Raspberry Pi y un "Pololu" no es tan común, pero se puede hacer.

Nota: A4988 y DRV8255 son equivalentes en cuanto a software de control.

La posta: https://www.rototron.info/raspberry-pi-stepper-motor-tutorial/

Más info

Ejemplos:

Código:

Links ML:

pigpio DMA chains y Real-time Kernel

Quizás ayude:

pigpio wave chains will control steppers with zero CPU cost.
"Transmitted waveforms are accurate to a microsecond" (< 1 MHz range)

Control indirecto RPi con Arduino y Driver

Hay mucha data para esto, podria usar un arduino con GRBL directamente.

Arduino Nano

https://www.instructables.com/id/GRBL-Pinout-Arduino-Nano-v30/

Homing con GRBL Probe

Se puede usar una Probe para calibrar el eje S si es que se usa el Raspberry con otro Arduino para el stepper de la pipeta. Si no habría que codearlo (algo bién rústico en un loop) en el raspberry o buscar algo hecho.

RPi Stepper

A lo bruto con GPIO y for loops

20200717-144030.png

20200717-144539.png

#!/usr/bin/python

from time import sleep
from RPi import GPIO

DIR = 20   # Direction GPIO Pin
STEP = 21  # Step GPIO Pin
CW = 1     # Clockwise Rotation
CCW = 0    # Counterclockwise Rotation
SPR = 200   # Steps per Revolution (360 / 7.5)

GPIO.setmode(GPIO.BCM)
GPIO.setup(DIR, GPIO.OUT)
GPIO.setup(STEP, GPIO.OUT)
GPIO.output(DIR, CW)
MODE = (14, 15, 18)   # Microstep Resolution GPIO Pins
GPIO.setup(MODE, GPIO.OUT)
RESOLUTION = {'Full': (0, 0, 0),
              'Half': (1, 0, 0),
              '1/4': (0, 1, 0),
              '1/8': (1, 1, 0),
              '1/16': (0, 0, 1),
              '1/32': (1, 0, 1)}
GPIO.output(MODE, RESOLUTION['1/4'])

step_count = SPR * 32
delay = .0208 / 32

#step_count = SPR
#delay = .0208

for x in range(step_count):
    GPIO.output(STEP, GPIO.HIGH)
    sleep(delay)
    GPIO.output(STEP, GPIO.LOW)
    sleep(delay)

sleep(.5)
GPIO.output(DIR, CCW)
for x in range(step_count):
    GPIO.output(STEP, GPIO.HIGH)
    sleep(delay)
    GPIO.output(STEP, GPIO.LOW)
    sleep(delay)

GPIO.cleanup()

Con PWM más cheto

Tener en cuenta posibles frecuencias para la "ramp" de aceleración:

20200717-220230.png

Antes hay que correr:

$ sudo pigpiod
from time import sleep
import pigpio

DIR = 20     # Direction GPIO Pin
STEP = 21    # Step GPIO Pin

# Connect to pigpiod daemon
pi = pigpio.pi()

# Set up pins as an output
pi.set_mode(DIR, pigpio.OUTPUT)
pi.set_mode(STEP, pigpio.OUTPUT)

MODE = (14, 15, 18)   # Microstep Resolution GPIO Pins
RESOLUTION = {'Full': (0, 0, 0),
              'Half': (1, 0, 0),
              '1/4': (0, 1, 0),
              '1/8': (1, 1, 0),
              '1/16': (0, 0, 1),
              '1/32': (1, 0, 1)}
for i in range(3):
    pi.write(MODE[i], RESOLUTION['1/16'][i])


def run_ramp(ramp):
    """Generate ramp wave forms.
    ramp:  List of [Frequency, Steps]
    """
    pi.wave_clear()     # clear existing waves
    length = len(ramp)  # number of ramp levels
    wid = [-1] * length

    # Generate a wave per ramp level
    for i in range(length):
        frequency = ramp[i][0]
        micros = int(500000 / frequency)
        wf = []
        wf.append(pigpio.pulse(1 << STEP, 0, micros))  # pulse on
        wf.append(pigpio.pulse(0, 1 << STEP, micros))  # pulse off
        pi.wave_add_generic(wf)
        wid[i] = pi.wave_create()

    # Generate a chain of waves
    chain = []
    for i in range(length):
        steps = ramp[i][1]
        x = steps & 255
        y = steps >> 8
        chain += [255, 0, wid[i], 255, 1, x, y]

    pi.wave_chain(chain)  # Transmit chain.


ramp = [[320, 20],
        [500, 40],
        [800, 50],
        [1000, 70],
        [1600, 90],
        [2000, 1000]]

# Ramp up
run_ramp(ramp)
Problemas

A veces tiraba esto y no sé por qué:

pigpio.error: too many chain counters

Activar limit switch

Como el wave chain ya es async quizás pueda interrumpirlo usando las funciones con las que viene.

Y funciona, la wave chain se puede detener despues de que se manda sin hacer nada raro en python mirando el GPIO del switch en un while loop.