Our device design addresses several challenges not present in the original Dropseq system (See Figure Below). First, extended cell viability. We maintain cell suspension viability for experiments lasting 2 hours or longer, compared to typical 30-minute Dropseq runs. Second, cross-contamination prevention. We implemented a washing system to remove unused cells or beads between samples. Third, sample isolation. We designed a system to prevent mixing wash fluid with droplets. To address these challenges, our device operates in two main phases during each injection cycle. 1. Flushing phase that clears fluid lines of residual beads or cells from previous injections. 2. Injection phase that precisely introduces cells and time-tagged beads into the microfluidic chip. This integrated system enables controlled, sequential introduction of cells and time-tagged beads, capturing gene expression dynamics across multiple time points in a single experiment.
ChronoSeq vs Dropseq comparison |
---|
![]() |
The ChronoSeq device is controlled via serial connections to a computer, which coordinates the actions of its various components, while the Dropseq device works by setting flow rates manually on syringe pumps. Some key features distinguish the ChronoSeq device:
Before getting started with this assembly protocol you need to assemble some of the individual components. Follow the instructions in the notebooks linked below before you move onto the next section:
Distance between support pieces | Height/Distance between racks | Depth of rack |
---|---|---|
![]() |
![]() |
![]() |
The first rack is 28 inches above the bench.
We also kept a 5%CO2 cylinder close to the bench.
An additional backup cylinder was also kept in the hallway secured with restraints.
The barbs for the House Air and Vacuum sources were also removed. The input threads for sources in our building were Female NPT 1/4 Inch.
We had 2 each of Vacuum and House Air sources on our bench as shown.
WARNING: Make sure you wear safety glasses. Comressed Air can be dangerous. Please follow the Hazard Control Plans for your lab and institution.
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/npxS9k2oQEg?si=Wmczb_2HpV-5k8vi" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/vaCiO843u6A?si=LrUy3pbDrqNDBWHV" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
![]() |
![]() |
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/irPr6I4Sb8A?si=Iop2RGkeZGaKVGCn" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/5q3FdRU-HvI?si=AjSbE3-zBajwQlS6" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/GlHhLa7J9-k?si=S44eV6COFLli2M4y" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/uAPeY82PT_4?si=bTl86-rfipuNgATv" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/m67uend2roI?si=g6A1ALqVY39b3Y1i" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
Left Side | Right Side |
---|---|
![]() |
![]() |
HDMI Cable | Routed along the back | Plugged into nearest electrical Outlet |
---|---|---|
![]() |
![]() |
![]() |
Keyboard and Mouse | Connected to USB Hub for USB 2 Port |
---|---|
![]() |
![]() |
>ipconfig/all
to get the Hardware(MAC) address for your Ethernet.Place the Hub at back in middle of ChronoSeq device area | Connect to the USB 3 Type C Port as shown | Secure the Extension cable in place using Labelling Tape |
---|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
Put the power strip at the back of your bench | The On/Off switch should be close to the right side of the monitor for easy access |
---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
# coding : utf8
%matplotlib inline
import os
import sys
sys.path.append(os.getcwd());
import ivPID.PID as PID_controller
print(os.getcwd())
os.chdir(".\config")
#Adding required directories to sys.path. Make sure you are in the Directory with the Git Repo when you start Jupyter Notebook
sys.path.append(os.getcwd());
sys.path.append(os.getcwd()+"\\DLL64");
import time
import Elveflow64
os.chdir("..")
from ctypes import *
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import serial
import threading
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.schedulers import SchedulerNotRunningError
from datetime import datetime,timedelta
import seaborn as sns
import pygame
C:\Users\kanis\Documents\ChronoSeq pygame 2.5.2 (SDL 2.28.3, Python 3.7.16) Hello from the pygame community. https://www.pygame.org/contribute.html
%%javascript
IPython.OutputArea.prototype._should_scroll = function(lines) {
return false;
}
%%writefile
magic as follows.from IPython.core.magic import register_cell_magic
@register_cell_magic
def write_and_run(line, cell):
argz = line.split()
file = argz[-1]
mode = 'w'
if len(argz) == 2 and argz[0] == '-a':
mode = 'a'
with open(file, mode) as f:
f.write(cell)
get_ipython().run_cell(cell)
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/vY6V0Eq87n8?si=x5sQQwJoQZgS2SXT" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/DC1oscWOHng?si=fX7POu0JLhZYOXPn" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
config/instrument_initialization.py
file.%%write_and_run config/instrument_initialization.py
OB1_pressureControllerCOM="020B9F6C" #Serial Number from NI MAX Paste Here
#Initializing Pressure Controller
pressureController=c_int32()
error=Elveflow64.OB1_Initialization(OB1_pressureControllerCOM.encode('ascii'),2,2,2,0,byref(pressureController))
if(error==0):
print("Pressure Controller Connection Started")
print('Pressure Controller ID: %d' % pressureController.value)
else:
print("error %d :" % error)
#Defining Channel Bindings according to current configuration
cell_channel=1
oil_channel=2
bead_channel=3
Pressure Controller Connection Started Pressure Controller ID: 0
%%write_and_run config/pressure_controller_load_calibration_file.py
#Make sure you Calibrate with the plugs in place if you are generating the file for the first time.
#See OB1 user manual for details about calibration and the plug type to use.
calibrationVector=(c_double*1000)()
currentWorkingDirectory=os.getcwd()
calibrationFilePath=currentWorkingDirectory + "\\config\OB1_CalibrationFile.txt"
fileExists=os.path.isfile(calibrationFilePath)
if(fileExists):
error=Elveflow64.Elveflow_Calibration_Load(calibrationFilePath.encode('ascii'), byref(calibrationVector), 1000)
if(error==0):
print("Calibration File Load Successful!")
else:
print("error %d :" % error)
else:
Elveflow64.OB1_Calib(pressureController.value, calibrationVector, 1000)
error=Elveflow64.Elveflow_Calibration_Save(calibrationFilePath.encode('ascii'), byref(calibrationVector), 1000)
if(error==0):
print('Calibration saved in %s' % calibrationFilePath)
else:
print("error %d :" % error)
Calibration File Load Successful!
def set_oil_channel_pressure(oil_channel_pressure):
Elveflow64.OB1_Set_Press(pressureController.value,c_int32(oil_channel),c_double(oil_channel_pressure),byref(calibrationVector),len(calibrationVector))
def get_oil_channel_pressure():
getOilChannelPressure=c_double()
Elveflow64.OB1_Get_Press(pressureController.value,c_int32(oil_channel),1,byref(calibrationVector),byref(getOilChannelPressure),len(calibrationVector))
return getOilChannelPressure.value
def set_cell_channel_pressure(cell_channel_pressure):
Elveflow64.OB1_Set_Press(pressureController.value,c_int32(cell_channel),c_double(cell_channel_pressure),byref(calibrationVector),len(calibrationVector))
def get_cell_channel_pressure():
getCellChannelPressure=c_double()
Elveflow64.OB1_Get_Press(pressureController.value,c_int32(cell_channel),1,byref(calibrationVector),byref(getCellChannelPressure),len(calibrationVector))
return getCellChannelPressure.value
def set_bead_channel_pressure(bead_channel_pressure):
Elveflow64.OB1_Set_Press(pressureController.value,c_int32(bead_channel),c_double(bead_channel_pressure),byref(calibrationVector),len(calibrationVector))
def get_bead_channel_pressure():
getBeadChannelPressure=c_double()
Elveflow64.OB1_Get_Press(pressureController.value,c_int32(bead_channel),1,byref(calibrationVector),byref(getBeadChannelPressure),len(calibrationVector))
return getBeadChannelPressure.value
def reset_pressures():
set_cell_channel_pressure(get_cell_channel_pressure())
set_bead_channel_pressure(get_bead_channel_pressure())
set_oil_channel_pressure(get_oil_channel_pressure())
time.sleep(5)
set_cell_channel_pressure(2000)
set_bead_channel_pressure(2000)
set_oil_channel_pressure(2000)
time.sleep(5)
set_cell_channel_pressure(0)
set_bead_channel_pressure(0)
set_oil_channel_pressure(0)
config/deviceShutdown.py
%%write_and_run config/deviceShutdown.py
error=Elveflow64.OB1_Destructor(pressureController.value)
if(error==0):
print("Pressure Controller Connection Closed!")
else:
print("error %d :" % error)
Pressure Controller Connection Closed!
config/instrument_initialization.py
file.%%write_and_run -a config/instrument_initialization.py
firstControllerCOM="COM3" #COM Port from Arduino IDE
secondControllerCOM="COM4" #COM Port from Arduino IDE
thirdControllerCOM="COM5" #COM Port from Arduino IDE
#Initializing Valve Controllers
valve_controller1=c_int32()
valve_controller1.value=1111
firstController=serial.Serial(firstControllerCOM, timeout=1, write_timeout=0)
time.sleep(5.0)
print(firstController.is_open)
print(firstController.get_settings())
valve_controller2=c_int32()
valve_controller2.value=2222#Assigning some number for third valve controller
secondController=serial.Serial(secondControllerCOM, timeout=1, write_timeout=0)
time.sleep(5.0)
print(secondController.is_open)
print(secondController.get_settings())
valve_controller3=c_int32()
valve_controller3.value=3333#Assigning some number for third valve controller
thirdController=serial.Serial(thirdControllerCOM, timeout=1, write_timeout=0)
time.sleep(5.0)
print(thirdController.is_open)
print(thirdController.get_settings())
True {'baudrate': 9600, 'bytesize': 8, 'parity': 'N', 'stopbits': 1, 'xonxoff': False, 'dsrdtr': False, 'rtscts': False, 'timeout': 1, 'write_timeout': 0, 'inter_byte_timeout': None} True {'baudrate': 9600, 'bytesize': 8, 'parity': 'N', 'stopbits': 1, 'xonxoff': False, 'dsrdtr': False, 'rtscts': False, 'timeout': 1, 'write_timeout': 0, 'inter_byte_timeout': None} True {'baudrate': 9600, 'bytesize': 8, 'parity': 'N', 'stopbits': 1, 'xonxoff': False, 'dsrdtr': False, 'rtscts': False, 'timeout': 1, 'write_timeout': 0, 'inter_byte_timeout': None}
config/setValveControllers.py
%%write_and_run config/setValveControllers.py
#Creating a ctypes vector to store the valve states
#Zero based indexing used. So first valve state is at index 0
valveController1_state=(c_int32*8)(0)
valveController2_state=(c_int32*8)(0)
valveController3_state=(c_int32*8)(0)
def set_first_controller(state_vector):
stringVector=""
readString=""
for digit in state_vector:
stringVector+=str(digit)
stringVector+="\n"
firstController.write(stringVector.encode())
try:
readString=firstController.readline().decode("utf-8").strip()
if readString==stringVector.strip():
print("Valve Controller 1 State successfully changed!")
print_array(state_vector)
else:
print("Valve Controller 1 Strings don't match. There is a problem!")
print("Read String is: ",readString)
except Exception as e:
print("Valve Controller 1 Serial Read Error. Will Try again!")
print("Reseting Pressures!")
reset_pressures()
set_first_controller(state_vector)
def set_second_controller(state_vector):
stringVector=""
readString=""
for digit in state_vector:
stringVector+=str(digit)
stringVector+="\n"
secondController.write(stringVector.encode())
try:
readString=secondController.readline().decode("utf-8").strip()
if readString==stringVector.strip():
print("Valve Controller 2 State successfully changed!")
print_array(state_vector)
else:
print("Valve Controller 2 Strings don't match. There is a problem!")
print("Read String is: ",readString)
except Exception as e:
print("Valve Controller 2 Serial Read Error. Will Try again!")
print("Reseting Pressures!")
reset_pressures()
set_second_controller(state_vector)
def set_third_controller(state_vector):
stringVector=""
readString=""
for digit in state_vector:
stringVector+=str(digit)
stringVector+="\n"
thirdController.write(stringVector.encode())
try:
readString=thirdController.readline().decode("utf-8").strip()
if readString==stringVector.strip():
print("Valve Controller 3 State successfully changed!")
print_array(state_vector)
else:
print("Valve Controller 3 Strings don't match. There is a problem!")
print("Read String is: ",readString)
except Exception as e:
print("Valve Controller 3 Serial Read Error. Will Try again!")
print("Reseting Pressures!")
reset_pressures()
set_third_controller(state_vector)
#Defining function to print out all valve states
def print_array(int_array):
for i in range(0,len(int_array)):
print(int_array[i], end= " ")
print("")
#Defining functions to set valves to a specific state
#WARNING! Only use the safe alternatives of these functions defined below
def set_valves(Instr_ID,state_vector):
if Instr_ID is valve_controller1:
set_first_controller(state_vector)
elif Instr_ID is valve_controller2:
set_second_controller(state_vector)
elif Instr_ID is valve_controller3:
set_third_controller(state_vector)
#Use safe alternative defined below
def close_all_valves(Instr_ID,state_vector):
for i in range(0,len(state_vector)):
state_vector[i]=0
set_valves(Instr_ID,state_vector)
def reset_state_vector(state_vector):
for i in range(0,len(state_vector)):
state_vector[i]=0
def reset_all_state_vectors():
reset_state_vector(valveController1_state)
reset_state_vector(valveController2_state)
reset_state_vector(valveController3_state)
## Need Load File
def update_valve_states():
set_valves(valve_controller1,valveController1_state)
set_valves(valve_controller2,valveController2_state)
set_valves(valve_controller3,valveController3_state)
def reset_valve_states():
close_all_valves(valve_controller1,valveController1_state)
close_all_valves(valve_controller2,valveController2_state)
close_all_valves(valve_controller3,valveController3_state)
#Turning on the first Valve for all three Controllers
valveController1_state[0]=1
valveController2_state[0]=1
valveController3_state[0]=1
update_valve_states()
time.sleep(5)
Valve Controller 1 State successfully changed! 1 0 0 0 0 0 0 0 Valve Controller 2 State successfully changed! 1 0 0 0 0 0 0 0 Valve Controller 3 State successfully changed! 1 0 0 0 0 0 0 0
reset_valve_states()
Valve Controller 1 State successfully changed! 0 0 0 0 0 0 0 0 Valve Controller 2 State successfully changed! 0 0 0 0 0 0 0 0 Valve Controller 3 State successfully changed! 0 0 0 0 0 0 0 0
config/deviceShutdown.py
file.%%write_and_run -a config/deviceShutdown.py
firstController.close()
if not firstController.isOpen():
print("Valve Controller 1 Connection Closed!")
else:
print("error! Count not close Valve Controller 1 connection.")
secondController.close()
if not secondController.isOpen():
print("Valve Controller 2 Connection Closed!")
else:
print("error! Count not close Valve Controller 2 connection.")
thirdController.close()
if not thirdController.isOpen():
print("Valve Controller 3 Connection Closed!")
else:
print("error! Count not close Valve Controller 3 connection.")
Valve Controller 1 Connection Closed! Valve Controller 2 Connection Closed! Valve Controller 3 Connection Closed!
config/instrument_initialization.py
file.%%write_and_run -a config/instrument_initialization.py
magneticStirrerCOM="COM12" #Using Arduino IDE
#Initializing magnetic stirrer
ser = serial.Serial(magneticStirrerCOM, timeout=1, write_timeout=0)
time.sleep(5)
print(ser.name)
print(ser.get_settings())
print(ser.is_open)
if not ser.is_open:
ser.open()
time.sleep(5)
COM12 {'baudrate': 9600, 'bytesize': 8, 'parity': 'N', 'stopbits': 1, 'xonxoff': False, 'dsrdtr': False, 'rtscts': False, 'timeout': 1, 'write_timeout': 0, 'inter_byte_timeout': None} True
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/ff7pH2Nusm0?si=6UPNB0Qf3a2jlYut" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
#Sets stirrer speed in rpm units
def set_stirrer_speed(rpm):
buffer=ser.read(ser.inWaiting())
byteString="s "+str(rpm)
ser.write(byteString.encode())
def stop_stirrer():
set_stirrer_speed(0)
set_stirrer_speed(200)
time.sleep(10)
stop_stirrer()
config/deviceShutdown.py
file.%%write_and_run -a config/deviceShutdown.py
def shutdown_stirrer():
buffer=ser.read(ser.inWaiting())
byteString="s "+str(0)
ser.write(byteString.encode())
ser.close()
if not ser.is_open:
print("Magnetic Stirrer Connection Closed!")
shutdown_stirrer()
Magnetic Stirrer Connection Closed!
![]() |
![]() |
config/instrument_initialization.py
file.%%write_and_run -a config/instrument_initialization.py
#Initializing Flow Meters
Cell_Channel_BFS_COM="ASRL13::INSTR" # VISA Resource Name from NI Max
Oil_Channel_BFS_COM="ASRL14::INSTR" # VISA Resource Name from NI Max
cellChannelFlowMeter=c_int32()
oilChannelFlowMeter=c_int32()
error=Elveflow64.BFS_Initialization(Cell_Channel_BFS_COM.encode('ascii'),byref(cellChannelFlowMeter))
error=Elveflow64.BFS_Set_Filter(cellChannelFlowMeter,float(0.1))
print('Cell Channel Flow Meter ID: %d' % cellChannelFlowMeter.value)
print("error %d :" % error) #Error 1073481728 is harmless and is just a warning
error=Elveflow64.BFS_Initialization(Oil_Channel_BFS_COM.encode('ascii'),byref(oilChannelFlowMeter))
error=Elveflow64.BFS_Set_Filter(oilChannelFlowMeter,float(0.1))
print('Oil Channel Flow Meter ID: %d' % oilChannelFlowMeter.value)
print("error %d :" % error)
#Density measurement is required so that correct flow measurement is returned.
#Defining Return Variables
cellChannelFlowDensity=c_double(-1)
oilChannelFlowDensity=c_double(-1)
cellChannelFlowRate=c_double(-1)
oilChannelFlowRate=c_double(-1)
#Getting Density and Flow values for Cell Channel
error=Elveflow64.BFS_Get_Density(cellChannelFlowMeter,byref(cellChannelFlowDensity))
print("Cell Channel Density:")
print(cellChannelFlowDensity.value)
error=Elveflow64.BFS_Get_Flow(cellChannelFlowMeter.value,byref(cellChannelFlowRate))
print("Cell Channel Flow rate:")
print(cellChannelFlowRate.value)
#Getting Density and Flow values for Oil Channel
error=Elveflow64.BFS_Get_Density(oilChannelFlowMeter,byref(oilChannelFlowDensity))
print("Oil Channel Density:")
print(oilChannelFlowDensity.value)
error=Elveflow64.BFS_Get_Flow(oilChannelFlowMeter.value,byref(oilChannelFlowRate))
print("Oil Channel Flow rate:")
print(oilChannelFlowRate.value)
Cell Channel Flow Meter ID: 3000 error 0 : Oil Channel Flow Meter ID: 3001 error 0 : Cell Channel Density: 0.4997599124908447 Cell Channel Flow rate: -1750.4286887357505 Oil Channel Density: 1.184064269065857 Oil Channel Flow rate: -1968.7159802554222
config/deviceShutdown.py
file.%%write_and_run -a config/deviceShutdown.py
#Shutting Down Flow Oil and Cell Channel Flow Sensors
error=Elveflow64.BFS_Destructor(cellChannelFlowMeter.value)
if(error==0):
print("Cell Channel Flow meter Connection Closed!")
else:
print("error %d :" % error)
error=Elveflow64.BFS_Destructor(oilChannelFlowMeter.value)
if(error==0):
print("Oil Channel Flow meter Connection Closed!")
else:
print("error %d :" % error)
Cell Channel Flow meter Connection Closed! Oil Channel Flow meter Connection Closed!
Left Side | Right Side |
---|---|
![]() |
![]() |
![]() |
![]() |
Right Leg | Left Leg |
---|---|
![]() |
![]() |
![]() |
![]() |
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/t5Qxu1TRRuk?si=nWq5D13l-IY05dNR" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/sraLl1G57F8?si=2Nidj-OFolLfSx3a" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/H8A0E8uKts8?si=YhJPUffp-IDcbCci" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/f2Y3IT-hyE8?si=MuAKWz4MflwhA_A4" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
config/instrument_initialization.py
file.%%write_and_run -a config/instrument_initialization.py
mainPlotterRobotCOM="COM15" # COM Port for XYZ Robot
smallDropletCollectionRobotCOM="COM9" # COM Port for XY Robot
#Initializing XYZ Robot
plotter=serial.Serial(mainPlotterRobotCOM,timeout=1,write_timeout=1)
time.sleep(5)
print(plotter.name)
print(plotter.get_settings())
print(plotter.is_open)
if not plotter.is_open:
plotter.open()
time.sleep(5)
#Initializing XY Robot
droplet_collector=serial.Serial(smallDropletCollectionRobotCOM,timeout=1,write_timeout=1)
time.sleep(5)
print(droplet_collector.name)
print(droplet_collector.get_settings())
print(droplet_collector.is_open)
if not droplet_collector.is_open:
droplet_collector.open()
time.sleep(5)
COM15 {'baudrate': 9600, 'bytesize': 8, 'parity': 'N', 'stopbits': 1, 'xonxoff': False, 'dsrdtr': False, 'rtscts': False, 'timeout': 1, 'write_timeout': 1, 'inter_byte_timeout': None} True COM9 {'baudrate': 9600, 'bytesize': 8, 'parity': 'N', 'stopbits': 1, 'xonxoff': False, 'dsrdtr': False, 'rtscts': False, 'timeout': 1, 'write_timeout': 1, 'inter_byte_timeout': None} True
config/deviceShutdown.py
file.%%write_and_run -a config/deviceShutdown.py
#Shutting Down XYZ Robot
plotter.write("H\n".encode())
time.sleep(1.0)
plotter.write("D\n".encode())
plotter.close()
if not plotter.isOpen():
print("Connection to the XYZ Robot closed successfully!")
else:
print("error! Could not close connection to the XYZ Robot.")
#Shutting Down XY Robot
droplet_collector.write("H\n".encode())
time.sleep(1.0)
droplet_collector.close()
if not droplet_collector.isOpen():
print("Connection to the XY Robot closed successfully!")
else:
print("error! Could not close connection to the XY Robot.")
Connection to the XYZ Robot closed successfully! Connection to the XY Robot closed successfully!
Front View | Side View: Side Row of Valve Slots should be jutting out |
---|---|
![]() |
![]() |
config/instrument_initialization.py
file.%%write_and_run -a config/instrument_initialization.py
arduinoSensirionFlowMeterCOM="COM7" #From Arduino IDE
arduino_Bead_Flow_meter = serial.Serial(arduinoSensirionFlowMeterCOM, timeout=1, write_timeout=1)
time.sleep(5)
print(arduino_Bead_Flow_meter.name)
print(arduino_Bead_Flow_meter.get_settings())
print(arduino_Bead_Flow_meter.is_open)
COM7 {'baudrate': 9600, 'bytesize': 8, 'parity': 'N', 'stopbits': 1, 'xonxoff': False, 'dsrdtr': False, 'rtscts': False, 'timeout': 1, 'write_timeout': 1, 'inter_byte_timeout': None} True
config/deviceShutdown.py
file.%%write_and_run -a config/deviceShutdown.py
arduino_Bead_Flow_meter.close()
if not arduino_Bead_Flow_meter.isOpen():
print("Bead Channel Flow meter Connection Closed!")
else:
print("error! Could not close Bead Channel Flow meter connection.")
Bead Channel Flow meter Connection Closed!
config/instrument_initialization.py
file.%%write_and_run -a config/instrument_initialization.py
vortexRelayCOM="COM10"
vortexRelay=serial.Serial(vortexRelayCOM,timeout=1,write_timeout=0)
time.sleep(5)
print(vortexRelay.name)
print(vortexRelay.get_settings())
print(vortexRelay.is_open)
if not vortexRelay.is_open:
vortexRelay.open()
time.sleep(5)
COM10 {'baudrate': 9600, 'bytesize': 8, 'parity': 'N', 'stopbits': 1, 'xonxoff': False, 'dsrdtr': False, 'rtscts': False, 'timeout': 1, 'write_timeout': 0, 'inter_byte_timeout': None} True
def stop_bead_vortex():
stop_both_vortices()
def start_bead_vortex():
vortexRelay.write("A1|B0\n".encode())
#Use this method to stop the Bead Channel Vortex
def stop_bead_vortex2():
stop_both_vortices()
def start_bead_vortex2():
vortexRelay.write("A0|B1\n".encode())
def start_both_vortices():
vortexRelay.write("A1|B1\n".encode())
def stop_both_vortices():
vortexRelay.write("A0|B0\n".encode())
time.sleep(10)
start_bead_vortex()
time.sleep(10)
start_bead_vortex2()
time.sleep(10)
start_both_vortices()
time.sleep(10)
stop_both_vortices()
time.sleep(10)
%%HTML
<iframe width="800" height="600" src="https://www.youtube.com/embed/jpxHyFy2_0k?si=IjLdjYzJ5_5yrHfZ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
config/deviceShutdown.py
file.%%write_and_run -a config/deviceShutdown.py
vortexRelay.write("A0|B0\n".encode())
vortexRelay.close()
if not vortexRelay.isOpen():
print("Connection to the Vortex Relay closed successfully!")
else:
print("error! Could not close connection to the Vortex Relay.")
Connection to the Vortex Relay closed successfully!