Fluid - Microsoft Research

advertisement
Microfluidic Biochips: Design,
Programming, and Optimization
Bill Thies
Joint work with Vaishnavi Ananthanarayanan, J.P. Urbanski,
Nada Amin, David Craig, Jeremy Gunawardena,
Todd Thorsen, and Saman Amarasinghe
Indian Statistical Institute
March 2, 2011
Microfluidic Chips
• Idea: a whole biology lab on a single chip
– Input/output
– Sensors: pH, glucose,
temperature, etc.
– Actuators: mixing, PCR,
electrophoresis, cell lysis, etc.
• Benefits:
–
–
–
–
Small sample volumes
High throughput
Geometrical manipulation
Portability
• Applications:
– Biochemistry
- Cell biology
– Biological computing
1 mm 10x real-time
Application to Rural Diagnostics
Disposable
Enteric Card
PATH,
Washington U.
Micronics, Inc.,
U. Washington
Targets:
- E. coli, Shigella,
Salmonella,
C. jejuni
DxBox
CARD
U. Washington,
Micronics, Inc.,
Nanogen, Inc.
Rheonix, Inc.
Targets:
- malaria (done)
- dengue, influenza,
Rickettsial diseases,
typhoid, measles
(under development)
Targets:
- HPV diagnosis
- Detection of
specific gene
sequences
Moore’s Law of Microfluidics:
Valve Density Doubles Every 4 Months
Source: Fluidigm Corporation (http://www.fluidigm.com/images/mlaw_lg.jpg)
Moore’s Law of Microfluidics:
Valve Density Doubles Every 4 Months
Source: Fluidigm Corporation (http://www.fluidigm.com/didIFC.htm)
Current Practice: Manage Gate-Level
Details from Design to Operation
• For every change in the experiment or the chip design:
fabricate
chip
1. Manually draw in AutoCAD
2. Operate each gate from LabView
Abstraction Layers for Microfluidics
Silicon Analog
Protocol Description Language
- architecture-independent protocol description
Fluidic Instruction Set Architecture (ISA)
- primitives for I/O, storage, transport, mixing
C
x86
Pentium III,
Pentium IV
chip 1
chip 2
chip 3
Fluidic Hardware Primitives
- valves, multiplexers, mixers, latches
transistors,
registers, …
Abstraction Layers for Microfluidics
Contributions
Protocol Description Language
- architecture-independent protocol description
Fluidic Instruction Set Architecture (ISA)
- primitives for I/O, storage, transport, mixing
BioCoder Language
[J.Bio.Eng. 2010]
Optimized Compilation
[Natural Computing 2007]
Demonstrate Portability
[DNA 2006]
Micado AutoCAD Plugin
chip 1
chip 2
chip 3
Fluidic Hardware Primitives
- valves, multiplexers, mixers, latches
[MIT 2008, ICCD 2009]
Digital Sample Control
Using Soft Lithography
[Lab on a Chip ‘06]
Droplets vs. Continuous Flow
• Digital manipulation of droplets
on an electrode array
[Chakrabarty, Fair, Gascoyne, Kim, …]
• Pro:
– Reconfigurable routing
– Electrical control
– More traction in CAD community
Source: Chakrabarty et al, Duke University
• Continuous flow of fluids (or
droplets) through fixed channels
[Whitesides, Quake, Thorsen, …]
• Pro:
– Smaller, more precise sample sizes
– Made-to-order availability [Stanford]
– More traction in biology community
Primitive 1: A Valve (Quake et al.)
Control
Layer
Flow
Layer
0. Start with mask of channels
Primitive 1: A Valve (Quake et al.)
Control
Layer
Flow
Layer
1. Deposit pattern on silicon wafer
Primitive 1: A Valve (Quake et al.)
Control
Layer
2. Pour PDMS over mold
- polydimexylsiloxane: “soft lithography”
Thick layer (poured)
Thin layer (spin-coated)
Flow
Layer
Primitive 1: A Valve (Quake et al.)
Control
Layer
Flow
Layer
3. Bake at 80° C (primary cure),
then release PDMS from mold
Primitive 1: A Valve (Quake et al.)
Control
Layer
Flow
Layer
4a. Punch hole in control channel
4b. Attach flow layer to glass slide
Primitive 1: A Valve (Quake et al.)
Control
Layer
Flow
Layer
5. Align flow layer over control layer
Primitive 1: A Valve (Quake et al.)
Control
Layer
Flow
Layer
6. Bake at 80° C (secondary cure)
Primitive 1: A Valve (Quake et al.)
Control
Layer
Flow
Layer
7. When pressure is high, control
channel pinches flow channel to
form a valve
pressure
actuator
Primitive 2: A Multiplexer (Thorsen et al.)
Bit 2
0 1
Bit 1
0 1
Bit 0
0 1
flow layer
control layer
Output 7
Output 6
Output 5
Input
Output 4
Output 3
Output 2
Output 1
Output 0
• Control lines can cross
flow lines
- Only thick parts make valves
• Logic is not
complimentary
• To control n flow lines,
need 2 log2 n control lines
Primitive 2: A Multiplexer (Thorsen et al.)
Bit 2
0 1
Bit 1
0 1
flow layer
control layer
Bit 0
0 1
Output 7
Output 6
Output 5
Input
Output 4
Output 3
Output 2
Output 1
Output 0
Example: select 3 = 011
• Control lines can cross
flow lines
- Only thick parts make valves
• Logic is not
complimentary
• To control n flow lines,
need 2 log2 n control lines
Primitive 2: A Multiplexer (Thorsen et al.)
Bit 2
0 1
Bit 1
0 1
flow layer
control layer
Bit 0
0 1
Output 7
Output 6
Output 5
Input
Output 4
Output 3
Output 2
Output 1
Output 0
Example: select 3 = 011
• Control lines can cross
flow lines
- Only thick parts make valves
• Logic is not
complimentary
• To control n flow lines,
need 2 log2 n control lines
Primitive 2: A Multiplexer (Thorsen et al.)
Bit 2
0 1
Bit 1
0 1
flow layer
control layer
Bit 0
0 1
Output 7
Output 6
Output 5
Input
Output 4
Output 3
Output 2
Output 1
Output 0
Example: select 3 = 011
• Control lines can cross
flow lines
- Only thick parts make valves
• Logic is not
complimentary
• To control n flow lines,
need 2 log2 n control lines
Primitive 3: A Mixer (Quake et al.)
1. Load sample on bottom
2. Load sample on top
3. Peristaltic pumping
Rotary Mixing
Primitive 4: A Latch (Our contribution)
• Purpose: align sample with specific location on device
– Examples: end of storage cell, end of mixer, middle of sensor
Sample
Latch
• Latches are implemented as a partially closed valve
– Background flow passes freely
– Aqueous samples are caught
Primitive 4: A Latch (Our contribution)
• Purpose: align sample with specific location on device
– Examples: end of storage cell, end of mixer, middle of sensor
Sample
Latch
• Latches are implemented as a partially closed valve
– Background flow passes freely
– Aqueous samples are caught
Primitive 5: Cell Trap
• Several methods for confining cells in microfluidic chips
– U-shaped weirs
– Holographic optical traps
- C-shaped rings / microseives
- Dialectrophoresis
• In our chips: U-Shaped Microseives in PDMS Chambers
Source: Wang, Kim, Marquez, and Thorsen, Lab on a Chip 2007
Primitive 6: Imaging and Detection
• As PDMS chips are translucent,
contents can be imaged directly
– Fluorescence, color, opacity, etc.
• Feedback can be used to
drive the experiment
Abstraction Layers for Microfluidics
Protocol Description Language
- architecture-independent protocol description
Fluidic Instruction Set Architecture (ISA)
- primitives for I/O, storage, transport, mixing
chip 1
chip 2
chip 3
Fluidic Hardware Primitives
- valves, multiplexers, mixers, latches
Driving Applications
1. What are the best indicators for oocyte viability?
-
With Mark Johnson’s and
Todd Thorsen’s groups
During in-vitro fertilization,
monitor cell metabolites and
select healthiest embryo for implantation
2. How do mammalian signal transduction pathways
respond to complex inputs?
-
With Jeremy Gunawardena’s
and Todd Thorsen’s groups
Isolate cells and stimulate with
square wave, sine wave, etc.
Driving Applications
1. What are the best indicators for oocyte viability?
-
With Mark Johnson’s and
Todd Thorsen’s groups
During in-vitro fertilization,
monitor cell metabolites and
select healthiest embryo for implantation
2. How do mammalian signal transduction pathways
respond to complex inputs?
-
With Jeremy Gunawardena’s
and Todd Thorsen’s groups
Isolate cells and stimulate with
square wave, sine wave, etc.
Video courtesy David Craig
CAD Tools for Microfluidic Chips
• Goal: automate placement, routing, control of
microfluidic features
• Why is this different than electronic CAD?
CAD Tools for Microfluidic Chips
• Goal: automate placement, routing, control of
microfluidic features
• Why is this different than electronic CAD?
1. Control ports (I/O pins) are bottleneck to scalability
– Pressurized control signals cannot yet be generated on-chip
– Thus, each logical set of valves requires its own I/O port
2. Control signals correlated due to continuous flows
pipelined flow
continuous flow
 Demand & opportunity for minimizing control logic
Our Technique:
Automatic Generation of Control Layer
Our Technique:
Automatic Generation of Control Layer
1. Describe Fluidic ISA
Our Technique:
Automatic Generation of Control Layer
1. Describe Fluidic ISA
Our Technique:
Automatic Generation of Control Layer
1. Describe Fluidic ISA
Our Technique:
Automatic Generation of Control Layer
1. Describe Fluidic ISA
2. Infer control valves
Our Technique:
Automatic Generation of Control Layer
1. Describe Fluidic ISA
2. Infer control valves
Our Technique:
Automatic Generation of Control Layer
1. Describe Fluidic ISA
2. Infer control valves
3. Infer control sharing
Our Technique:
Automatic Generation of Control Layer
1. Describe Fluidic ISA
2. Infer control valves
3. Infer control sharing
Our Technique:
Automatic Generation of Control Layer
1.
2.
3.
4.
Describe Fluidic ISA
Infer control valves
Infer control sharing
Route valves to control ports
Our Technique:
Automatic Generation of Control Layer
1.
2.
3.
4.
Describe Fluidic ISA
Infer control valves
Infer control sharing
Route valves to control ports
Our Technique:
Automatic Generation of Control Layer
1.
2.
3.
4.
Describe Fluidic ISA
Infer control valves
Infer control sharing
Route valves to control ports
Our Technique:
Automatic Generation of Control Layer
1.
2.
3.
4.
5.
Describe Fluidic ISA
Infer control valves
Infer control sharing
Route valves to control ports
Generate an interactive GUI
Our Technique:
Automatic Generation of Control Layer
1.
2.
3.
4.
5.
Describe Fluidic ISA
Infer control valves
Infer control sharing
Route valves to control ports
Generate an interactive GUI
Our Technique:
Automatic Generation of Control Layer
1.
2.
3.
4.
5.
Describe Fluidic ISA
Infer control valves
Infer control sharing
Route valves to control ports
Generate an interactive GUI
Our Technique:
Automatic Generation of Control Layer
1.
2.
3.
4.
5.
Describe Fluidic ISA
Infer control valves
Infer control sharing
Route valves to control ports
Generate an interactive GUI
1. Describe a Fluidic ISA
• Hierarchical and composable flow declarations
Sequential flow
P 1  P2
P1
P2
F1
AND-flow
F 1 Λ F2
OR-flow
F1 \/ F2
Mixing
mix(F)
Pumped flow
pump(F)
F2
F1
F1
or
F2
F
F
F2
1. Describe a Fluidic ISA
1. Describe a Fluidic ISA
mix-and-store (S1, S2, D) {
1. in1  top  out
2. in2  bot  out
3. mix(top  bot-left 
bot-right  top)
4. wash  bot-right 
top  bot-left  store
}
50x real-time
2. Infer Control Valves
2. Infer Control Valves
2. Infer Control Valves
3. Infer Control Sharing
3. Infer Control Sharing
3. Infer Control Sharing
3. Infer Control Sharing
3. Infer Control Sharing
3. Infer Control Sharing
3. Infer Control Sharing
3. Infer Control Sharing
3. Infer Control Sharing
3. Infer Control Sharing
Column Compatibility Problem
- NP-hard
- Reducible to graph coloring
3. Infer Control Sharing
Column Compatibility Problem
- NP-hard
- Reducible to graph coloring
3. Infer Control Sharing
Column Compatibility Problem
- NP-hard
- Reducible to graph coloring
3. Infer Control Sharing
Column Compatibility Problem
- NP-hard
- Reducible to graph coloring
3. Infer Control Sharing
Column Compatibility Problem
- NP-hard
- Reducible to graph coloring
4. Route Valves to Control Ports
• Build on recent algorithm
for simultaneous pin
assignment & routing
[Xiang et al., 2001]
• Idea: min cost - max flow
from valves to ports
• Our contribution: extend algorithm to allow sharing
– Previous capacity constraint on each edge:
f1 + f2 + f3 + f4 + f5 + f6 ≤ 1
– Modified capacity constraint on each edge:
max(f1, f4) + max(f2 , f3) + f5 + f6 ≤ 1
Solve with linear programming, allowing sharing where beneficial
4. Route Valves to Control Ports
• Build on recent algorithm
for simultaneous pin
assignment & routing
[Xiang et al., 2001]
• Idea: min cost - max flow
from valves to ports
• Our contribution: extend algorithm to allow sharing
– Previous capacity constraint on each edge:
f1 + f2 + f3 + f4 + f5 + f6 ≤ 1
– Modified capacity constraint on each edge:
max(f1, f4) + max(f2 , f3) + f5 + f6 ≤ 1
Solve with linear programming, allowing sharing where beneficial
Micado: An AutoCAD Plugin
• Implements ISA, control inference, routing, GUI export
– Using slightly older algorithms
than presented here [Amin ‘08]
– Parameterized design rules
– Incremental construction of chips
• Realistic use by at least 3
microfluidic researchers
• Freely available at:
http://groups.csail.mit.edu/cag/micado/
Cell Culture with Waveform Generator
Courtesy David Craig
Cell Culture with Waveform Generator
Courtesy David Craig
Embryonic Cell Culture
Courtesy J.P. Urbanski
Embryonic Cell Culture
Courtesy J.P. Urbanski
Metabolite Detector
Courtesy J.P. Urbanski
Metabolite Detector
Courtesy J.P. Urbanski
Open Problems
• Automate the design of the flow layer
– Hardware description language for microfluidics
– Define parameterized and reusable modules
• Replicate and pack a primitive as densely as possible
– How many cell cultures can you fit on a chip?
• Support additional primitives and functionality
–
–
–
–
–
Metering volumes
Sieve valves
Alternate mixers
Separation primitives
…
Conclusions: Microfludics CAD
• Microfluidics represents a rich new
playground for CAD researchers
• Two immediate goals:
– Enable designs to scale
– Enable non-experts to design own chips
• Micado is a first step towards
these goals
–
–
–
–
Hierarchical ISA for microfluidics
Inference and minimization of control logic
Routing shared channels to control ports
Generation of an interactive GUI
http://groups.csail.mit.edu/cag/micado/
Courtesy J.P. Urbanski
Abstraction Layers for Microfluidics
Protocol Description Language
- architecture-independent protocol description
Fluidic Instruction Set Architecture (ISA)
- primitives for I/O, storage, transport, mixing
chip 1
chip 2
chip 3
Fluidic Hardware Primitives
- valves, multiplexers, mixers, latches
Toward “General Purpose”
Microfluidic Chips
In
Fluidic
Storage
(RAM)
Out
Outputs
Inputs
Sensors
Mixing
and
Chambers
Actuators
A Digital Architecture
• Recent techniques can control independent samples
– Droplet-based samples [Fair et al.]
– Continuous-flow samples [Our contribution]
– Microfluidic latches [Our contribution]
• In abstract machine, all
samples have unit volume
In
Fluidic
Storage
(RAM)
Outputs
Inputs
– Input/output a sample
– Store a sample
– Operate on a sample
Sensors
Mixing
and
Chambers
Actuators
Out
• Challenge for a digital architecture: fluid loss
– No chip is perfect – will lose some volume over time
– Causes: imprecise valves, adhesion to channels, evaporation, ...
– How to maintain digital abstraction?
Maintaining a Digital Abstraction
Maintaining a Digital Abstraction
Electronics
Soft error
Handling?
?
?
?
High-Level
Language
Expose loss in language
- User deals with it
?
Randomized
Gates [Palem]
?
Microfluidics
Instruction Set
Architecture (ISA)
Expose loss in ISA
- Compiler deals with it
?
Replenish charge
(GAIN)
Loss of charge
Replenish fluids?
Hardware
- Maybe (e.g., with water)
- But may affect chemistry
Loss of fluids
Towards a Fluidic ISA
• Microfluidic chips have various mixing technologies
– Electrokinetic mixing [Levitan et al.]
– Droplet mixing [Fair et al.]
– Rotary mixing [Quake et al.]
• Common attributes:
– Ability to mix two samples in equal proportions, store result
• Fluidic ISA: mix (int src1, int src2, int dst)
– Ex: mix(1, 2, 3)
Storage Cells
1
2
3
4
Mixer
– To allow for lossy transport, only 1 unit of mixture retained
Implementation: Oil-Driven Chip
Inputs Storage Cells Background Phase Wash Phase
Chip 1
2
8
Oil
—
Mixing
Rotary
Implementation: Oil-Driven Chip
mix (S1, S2, D) {
1. Load S1
2. Load S2
3. Rotary mixing
4. Store into D
}
50x real-time
Inputs Storage Cells Background Phase Wash Phase
Chip 1
2
8
Oil
—
Mixing
Rotary
Implementation 2: Air-Driven Chip
Inputs Storage Cells Background Phase Wash Phase
Mixing
Chip 1
2
8
Oil
—
Rotary
Chip 2
4
32
Air
Water
In channels
Implementation 2: Air-Driven Chip
mix (S1, S2, D) {
1. Load S1
2. Load S2
3. Mix / Store into D
4. Wash S1
5. Wash S2
}
50x real-time
Inputs Storage Cells Background Phase Wash Phase
Mixing
Chip 1
2
8
Oil
—
Rotary
Chip 2
4
32
Air
Water
In channels
“Write Once, Run Anywhere”
• Example: Gradient generation
Fluid yellow = input (0);
Fluid blue = input(1);
for (int i=0; i<=4; i++) {
mix(yellow, 1-i/4, blue, i/4);
}
• Hidden from programmer:
–
–
–
–
Location of fluids
Details of mixing, I/O
Logic of valve control
Timing of chip operations
450 Valve Operations
“Write Once, Run Anywhere”
• Example: Gradient generation
Fluid yellow = input (0);
Fluid blue = input(1);
for (int i=0; i<=4; i++) {
mix(yellow, 1-i/4, blue, i/4);
}
• Hidden from programmer:
–
–
–
–
Location of fluids
Details of mixing, I/O
Logic of valve control
Timing of chip operations
setValve(0,
HIGH);
setValve(1,
HIGH);
wait(2000);
setValve(0,
HIGH);
setValve(1,
HIGH);
wait(2000);
setValve(0,
HIGH);
setValve(1,
HIGH);
wait(2000);
setValve(0,
HIGH);
setValve(1,
HIGH);
wait(2000);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
HIGH);
setValve(1,
HIGH);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
HIGH);
setValve(1,
HIGH);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
HIGH);
setValve(1,
HIGH);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
HIGH);
setValve(1,
HIGH);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(2,
LOW);
setValve(3,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(2,
LOW);
setValve(3,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(2,
LOW);
setValve(3,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(2,
LOW);
setValve(3,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(10,
LOW);
setValve(11,
HIGH);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
wait(2000);
setValve(19,
LOW);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
wait(2000);
setValve(19,
LOW);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
wait(2000);
setValve(19,
LOW);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
wait(2000);
setValve(19,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
wait(2000);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
wait(2000);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
wait(2000);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
wait(2000);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
wait(2000);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
wait(2000);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
wait(2000);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
wait(2000);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(16,
HIGH);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(16,
HIGH);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(16,
HIGH);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(16,
HIGH);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
wait(2000);
setValve(19,
LOW);
setValve(18,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(17,
LOW);
wait(2000);
setValve(19,
LOW);
setValve(18,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(17,
LOW);
wait(2000);
setValve(19,
LOW);
setValve(18,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(17,
LOW);
wait(2000);
setValve(19,
LOW);
setValve(18,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(17,
LOW);
wait(2000);
setValve(18,
HIGH);
setValve(19,
LOW);
wait(2000);
setValve(18,
HIGH);
setValve(19,
LOW);
wait(2000);
setValve(18,
HIGH);
setValve(19,
LOW);
wait(2000);
setValve(18,
HIGH);
setValve(19, LOW);
450 Valve
Operations
“Write Once, Run Anywhere”
• Example: Gradient generation
Fluid yellow = input (0);
Fluid blue = input(1);
for (int i=0; i<=4; i++) {
mix(yellow, 1-i/4, blue, i/4);
}
• Hidden from programmer:
–
–
–
–
Location of fluids
Details of mixing, I/O
Logic of valve control
Timing of chip operations
setValve(0,
HIGH);
setValve(1,
HIGH);
wait(2000);
setValve(0,
HIGH);
setValve(1,
HIGH);
wait(2000);
setValve(0,
HIGH);
setValve(1,
HIGH);
wait(2000);
setValve(0,
HIGH);
setValve(1,
HIGH);
wait(2000);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
HIGH);
setValve(1,
HIGH);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
HIGH);
setValve(1,
HIGH);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
HIGH);
setValve(1,
HIGH);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
HIGH);
setValve(1,
HIGH);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(2,
LOW);
setValve(3,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(2,
LOW);
setValve(3,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(2,
LOW);
setValve(3,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(2,
LOW);
setValve(3,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(10,
LOW);
setValve(11,
HIGH);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
wait(2000);
setValve(19,
LOW);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
wait(2000);
setValve(19,
LOW);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
wait(2000);
setValve(19,
LOW);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
wait(2000);
setValve(19,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
wait(2000);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
wait(2000);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
wait(2000);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
wait(2000);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
wait(2000);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
wait(2000);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
wait(2000);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
wait(2000);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(16,
HIGH);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(16,
HIGH);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(16,
HIGH);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(16,
HIGH);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
wait(2000);
setValve(19,
LOW);
setValve(18,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(17,
LOW);
wait(2000);
setValve(19,
LOW);
setValve(18,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(17,
LOW);
wait(2000);
setValve(19,
LOW);
setValve(18,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(17,
LOW);
wait(2000);
setValve(19,
LOW);
setValve(18,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(17,
LOW);
wait(2000);
setValve(18,
HIGH);
setValve(19,
LOW);
wait(2000);
setValve(18,
HIGH);
setValve(19,
LOW);
wait(2000);
setValve(18,
HIGH);
setValve(19,
LOW);
wait(2000);
setValve(18,
HIGH);
setValve(19, LOW);
450 Valve
Operations
“Write Once, Run Anywhere”
setValve(0,
HIGH);
setValve(1,
HIGH);
setValve(0,
HIGH);
setValve(1,
HIGH);
wait(2000);
setValve(0,
HIGH);
setValve(1,
HIGH);
wait(2000);
setValve(0,
HIGH);
setValve(1,
HIGH);
wait(2000);
setValve(0,
HIGH);
setValve(1,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
wait(2000);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
HIGH);
setValve(1,
HIGH);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
HIGH);
setValve(1,
HIGH);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
HIGH);
setValve(1,
HIGH);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
HIGH);
setValve(1,
HIGH);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(2,
LOW);
setValve(3,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(2,
LOW);
setValve(3,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(2,
LOW);
setValve(3,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(10,
LOW);
setValve(11,
HIGH);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(10,
LOW);
setValve(11,
HIGH);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
wait(2000);
setValve(19,
LOW);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
wait(2000);
setValve(19,
LOW);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
wait(2000);
setValve(19,
LOW);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
setValve(14,
LOW);
setValve(15,
HIGH);
wait(2000);
setValve(19,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
wait(2000);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
wait(2000);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
wait(2000);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(0,
LOW);
setValve(1,
LOW);
wait(2000);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
wait(2000);
setValve(4,
LOW);
setValve(5,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
wait(2000);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
wait(2000);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
wait(2000);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
wait(2000);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
wait(1000);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(19,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(16,
HIGH);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(16,
HIGH);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(16,
HIGH);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
wait(2000);
setValve(16,
HIGH);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
wait(2000);
setValve(19,
LOW);
setValve(18,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(17,
LOW);
wait(2000);
setValve(19,
LOW);
setValve(18,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(17,
LOW);
wait(2000);
setValve(19,
LOW);
setValve(18,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(17,
LOW);
wait(2000);
setValve(19,
LOW);
setValve(18,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(17,
LOW);
wait(2000);
setValve(18,
HIGH);
setValve(19,
LOW);
wait(2000);
setValve(18,
HIGH);
setValve(19,
LOW);
wait(2000);
setValve(18,
HIGH);
setValve(19,
LOW);
wait(2000);
setValve(18, HIGH); setValve(19, LOW);
Direct Control
- 450 valve actuations
- only works on 1 chip
Gradient Generation in Fluidic ISA
setValve(0,
HIGH);
setValve(1,
HIGH);
setValve(0,
HIGH);
setValve(1,
HIGH);
wait(2000);
setValve(0,
HIGH);
setValve(1,
HIGH);
wait(2000);
setValve(0,
HIGH);
setValve(1,
HIGH);
wait(2000);
setValve(0,
HIGH);
setValve(1,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
wait(2000);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
HIGH);
setValve(1,
HIGH);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
HIGH);
setValve(1,
HIGH);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
HIGH);
setValve(1,
HIGH);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
HIGH);
setValve(1,
HIGH);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(2,
LOW);
setValve(3,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(2,
LOW);
setValve(3,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(2,
LOW);
setValve(3,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(10,
LOW);
setValve(11,
HIGH);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(10,
LOW);
setValve(11,
HIGH);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
wait(2000);
setValve(19,
LOW);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
wait(2000);
setValve(19,
LOW);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
wait(2000);
setValve(19,
LOW);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(10,
LOW);
setValve(11,
HIGH);
setValve(14,
LOW);
setValve(15,
HIGH);
wait(2000);
setValve(19,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
wait(2000);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
wait(2000);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
wait(2000);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
HIGH);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(0,
LOW);
setValve(1,
LOW);
wait(2000);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(0,
LOW);
setValve(1,
LOW);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(16,
LOW);
setValve(17,
LOW);
wait(2000);
setValve(4,
LOW);
setValve(5,
HIGH);
setValve(2,
LOW);
setValve(3,
HIGH);
wait(2000);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
wait(2000);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
wait(2000);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
wait(2000);
setValve(18,
LOW);
setValve(19,
LOW);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(4,
LOW);
setValve(5,
HIGH);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
setValve(14,
HIGH);
setValve(2,
LOW);
wait(2000);
wait(1000);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(6,
HIGH);
setValve(7,
LOW);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
wait(1000);
setValve(14,
HIGH);
setValve(2,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(8,
LOW);
setValve(9,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(4,
HIGH);
setValve(12,
LOW);
wait(1000);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(10,
HIGH);
setValve(11,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(4,
HIGH);
setValve(12,
LOW);
setValve(19,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(12,
LOW);
setValve(13,
LOW);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(16,
HIGH);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(16,
HIGH);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
setValve(16,
HIGH);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(18,
HIGH);
wait(2000);
setValve(16,
HIGH);
setValve(17,
LOW);
setValve(14,
LOW);
setValve(15,
HIGH);
wait(2000);
setValve(19,
LOW);
setValve(18,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(17,
LOW);
wait(2000);
setValve(19,
LOW);
setValve(18,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(17,
LOW);
wait(2000);
setValve(19,
LOW);
setValve(18,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(17,
LOW);
wait(2000);
setValve(19,
LOW);
setValve(18,
HIGH);
setValve(19,
LOW);
setValve(16,
HIGH);
setValve(17,
LOW);
wait(2000);
setValve(18,
HIGH);
setValve(19,
LOW);
wait(2000);
setValve(18,
HIGH);
setValve(19,
LOW);
wait(2000);
setValve(18,
HIGH);
setValve(19,
LOW);
wait(2000);
setValve(18, HIGH); setValve(19, LOW);
input(0, 0);
input(1, 1);
input(0, 2);
mix(1, 2, 3);
input(0, 2);
abstraction mix(2, 3, 1);
input(1, 3);
input(0, 4);
mix(3, 4, 2);
input(1, 3);
input(0, 4);
mix(3, 4, 5);
input(1, 4);
mix(4, 5, 3);
mix(0, 4);
Direct Control
Fluidic ISA
- 450 valve actuations
- only works on 1 chip
- 15 instructions
- portable across chips
Gradient Generation in Fluidic ISA
input(0, 0);
input(1, 1);
input(0, 2);
mix(1, 2, 3);
input(0, 2);
mix(2, 3, 1);
input(1, 3);
input(0, 4);
mix(3, 4, 2);
input(1, 3);
input(0, 4);
mix(3, 4, 5);
input(1, 4);
mix(4, 5, 3);
mix(0, 4);
Abstraction 1: Managing Fluidic Storage
Fluidic
ISA
input(0, 0);
input(1, 1);
input(0, 2);
mix(1, 2, 3);
input(0, 2);
mix(2, 3, 1);
input(1, 3);
input(0, 4);
mix(3, 4, 2);
input(1, 3);
input(0, 4);
mix(3, 4, 5);
input(1, 4);
mix(4, 5, 3);
mix(0, 4);
Fluid[] out = new Fluid[8];
Fluid yellow, blue, green;
out[0] = input(0);
yellow = input(0);
blue = input(1);
green = mix(yellow, blue);
yellow = input(0);
out[1] = mix(yellow, green);
yellow = input(0);
blue = input(1);
out[2] = mix(yellow, blue);
yellow = input(0);
blue = input(1);
green = mix(yellow, blue);
blue = input(1);
out[3] = mix(blue, green);
out[4] = input(1);
1. Storage
Management
• Programmer uses location-independent Fluid variables
– Runtime system assigns & tracks location of each Fluid
– Comparable to automatic memory management (e.g., Java)
Fluid[] out = new Fluid[8];
Fluid yellow, blue, green;
out[0] = input(0);
yellow = input(0);
blue = input(1);
green = mix(yellow, blue);
yellow = input(0);
out[1] = mix(yellow, green);
yellow = input(0);
blue = input(1);
out[2] = mix(yellow, blue);
yellow = input(0);
blue = input(1);
green = mix(yellow, blue);
blue = input(1);
out[3] = mix(blue, green);
out[4] = input(1);
Abstraction 2: Fluid Re-Generation
Fluid[] out = new Fluid[8];
Fluid yellow, blue, green;
out[0] = input(0);
yellow = input(0);
blue = input(1);
green = mix(yellow, blue);
yellow = input(0);
out[1] = mix(yellow, green);
yellow = input(0);
blue = input(1);
out[2] = mix(yellow, blue);
yellow = input(0);
blue = input(1);
green = mix(yellow, blue);
blue = input(1);
out[3] = mix(blue, green);
out[4] = input(1);
Fluid[] out = new Fluid[8];
Fluid yellow = input(0);
Fluid blue = input(1);
Fluid green = mix(yellow, blue);
out[0] = yellow;
out[1] = mix(yellow, green);
out[2] = green;
out[3] = mix(blue, green);
out[4] = blue;
2. Fluid Re-Generation
• Programmer may use a Fluid variable multiple times
– Each time, a physical Fluid is consumed on-chip
– Runtime system re-generates Fluids from computation history
Fluid[] out = new Fluid[8];
Fluid yellow = input(0);
Fluid blue = input(1);
Fluid green = mix(yellow, blue);
out[0] = yellow;
out[1] = mix(yellow, green);
out[2] = green;
out[3] = mix(blue, green);
out[4] = blue;
2. Fluid Re-Generation
Abstraction 3: Arbitrary Mixing
Fluid[] out = new Fluid[8];
Fluid yellow = input(0);
Fluid blue = input(1);
Fluid green = mix(yellow, blue);
Fluid[] out = new Fluid[8];
Fluid yellow = input (0);
Fluid blue = input (1);
out[0] = yellow;
out[1] = mix(yellow, green);
out[2] = green;
out[3] = mix(blue, green);
out[4] = blue;
out[0] = yellow;
out[1] = mix(yellow, 3/4, blue, 1/4);
out[2] = mix(yellow, 1/2, blue, 1/2);
out[3] = mix(yellow, 1/4, blue, 3/4);
out[4] = blue;
2. Fluid Re-Generation
3. Arbitrary Mixing
• Allows mixing fluids in any proportion, not just 50/50
– Fluid mix (Fluid F1, float p1, Fluid f2, float F2)
 Returns Fluid that is p1 parts F1 and p2 parts F2
– Runtime system translates to 50/50 mixes in Fluidic ISA
– Note: some mixtures only reachable within error tolerance 
Abstraction 3: Arbitrary Mixing
Fluid[] out = new Fluid[8];
Fluid yellow = input(0);
Fluid blue = input(1);
Fluid green = mix(yellow, blue);
Fluid[] out = new Fluid[8];
Fluid yellow = input (0);
Fluid blue = input (1);
out[0] = yellow;
out[1] = mix(yellow, green);
out[2] = green;
out[3] = mix(blue, green);
out[4] = blue;
out[0] = yellow;
out[1] = mix(yellow, 3/4, blue, 1/4);
out[2] = mix(yellow, 1/2, blue, 1/2);
out[3] = mix(yellow, 1/4, blue, 3/4);
out[4] = blue;
2. Fluid Re-Generation
3. Arbitrary Mixing
• Allows mixing fluids in any proportion, not just 50/50
– Fluid mix (Fluid F1, float p1, Fluid f2, float F2)
 Returns Fluid that is p1 parts F1 and p2 parts F2
– Runtime system translates to 50/50 mixes in Fluidic ISA
– Note: some mixtures only reachable within error tolerance 
Abstraction 3: Arbitrary Mixing
Fluid[] out = new Fluid[8];
Fluid yellow = input (0);
Fluid blue = input (1);
Fluid[] out = new Fluid[8];
Fluid yellow = input (0);
Fluid blue = input (1);
out[0] = yellow;
out[1] = mix(yellow, 3/4, blue, 1/4);
out[2] = mix(yellow, 1/2, blue, 1/2);
out[3] = mix(yellow, 1/4, blue, 3/4);
out[4] = blue;
for (int i=0; i<=4; i++) {
out[i] = mix(yellow, 1-i/4, blue, i/4);
}
3. Arbitrary Mixing
4. Parameterized Mixing
• Allows mixing fluids in any proportion, not just 50/50
– Fluid mix (Fluid F1, float p1, Fluid f2, float F2)
 Returns Fluid that is p1 parts F1 and p2 parts F2
– Runtime system translates to 50/50 mixes in Fluidic ISA
– Note: some mixtures only reachable within error tolerance 
Algorithms for Efficient Mixing
• Mixing is fundamental operation of microfluidics
– Prepare samples for analysis
– Dilute concentrated substances
– Control reagant volumes
Analogous to ALU operations on microprocessors
• How to synthesize complex mixture using simple steps?
– Many systems support only 50/50 mixers
– Should minimize number of mixes, reagent usage
– Note: some mixtures only reachable within error tolerance 
Interesting scheduling and optimization problem
• N
Why Not Binary Search?
0
3/8
1
1/2
1/4
3/8
1/2
5 inputs, 4 mixes
Why Not Binary Search?
0
3/8
1
1/2
3/4
3/8
4 inputs, 3 mixes
1/2
1/4
3/8
1/2
5 inputs, 4 mixes
Min-Mix Algorithm
•
Simple algorithm yields minimal number of mixes
–
–
For any number of reagents, to any reachable concentration
Also minimizes reagent usage on certain chips
Min-Mix Algorithm: Key Insights
1. The mixing process can be represented by a tree.
A
B
B
A
5/8 A, 3/8 B
Min-Mix Algorithm: Key Insights
1. The mixing process can be represented by a tree.
d
2-d
3
1/8
2
1/4
1
1/2
A
B
B
A
5/8 A, 3/8 B
2. The contribution of an input sample to the overall mixture
is 2-d, where d is the depth of the sample in the tree
Min-Mix Algorithm: Key Insights
1. The mixing process can be represented by a tree.
d
2-d
3
1/8
1
2
1/4
0
1
1/2
1
A
A
5 = 101
B
1
B
1
0
3 = 011
5/8 A, 3/8 B
2. The contribution of an input sample to the overall mixture
is 2-d, where d is the depth of the sample in the tree
3. In the optimal mixing tree, a reagent appears at depths
corresponding to the binary representation of its overall
concentration.
Min-Mix Algorithm
• Example: mix 5/16 A, 7/16 B, 4/16 C
d
2-d
4
1/16
3
1/8
2
1/4
1
1/2
A
B
A
B
A
A=5
=0101
B
B=7
=0111
B
B
C
A
B
C
C=4
=0100
• To mix k fluids with precision 1/n:
– Min-mix algorithm: O(k log n) mixes
– Binary search: O(k n) mixes
[Natural Computing 2007]
Related Work
• Algorithms for microfluidic sample preparation [Sudip Roy et al.]
• Aquacore – builds on our work, ISA + architecture [Amin et al.]
• Automatic scheduling of biology protocols
– EDNAC computer for automatically solving 3-SAT [Johnson]
– Compile SAT to microfluidic chips [Landweber et al.] [van Noort]
– Mapping sequence graphs to grid-based chips [Su/Chakrabarty]
• Custom microfluidic chips for biological computation
– DNA computing [Grover & Mathies] [van Noort et al.] [McCaskill] [Livstone,
Weiss, & Landweber] [Gehani & Reif] [Farfel & Stefanovic]
– Self-assembly [Somei, Kaneda, Fujii, & Murata] [Whitesides et al.]
• General-purpose microfluidic chips
– Using electrowetting, with flexible mixing [Fair et al.]
– Using dialectrophoresis, with retargettable GUI [Gascoyne et al.]
– Using Braille displays as programmable actuators [Gu et al.]
Conclusions: Fluidic ISA
• Fluidic ISA gives flexibility to evolve underlying
hardware
– Including various device technologies
• It remains to be seen to what degree the functionality of
chips can be standardized
– May need to reconsider abstractions for analog machines
• Opportunities for future work
– Rich extensions to mixing algorithms
– Schedule separate protocols onto shared hardware,
maximizing utilization of shared resource (e.g., thermocycler)
– Parallelize single protocol across people or chips
– Dynamic optimization of slow co-processors (lazy vectorization)?
Abstraction Layers for Microfluidics
Protocol Description Language
- architecture-independent protocol description
Fluidic Instruction Set Architecture (ISA)
- primitives for I/O, storage, transport, mixing
chip 1
chip 2
chip 3
Fluidic Hardware Primitives
- valves, multiplexers, mixers, latches
“Immunological detection ... was carried out as
described in the Boehringer digoxigenin-nucleic
acid detection kit with some modifications.”
- Main paper
- References
- Ref. papers
Papers from Nature, Spring 2010
Problems with Existing
Descriptions of Protocols
• Incomplete
– Cascading references several levels deep
– Some information missing completely
• Ambiguous
– One word can refer to many things
– E.g., “inoculate” a culture
• Non-uniform
– Different words can refer to the same thing
– E.g., “harvest”, “pellet down”, “centrifuge” are equivalent
• Not suitable for automation
BioCoder: A High-Level Programming
Language for Biology Protocols
In biology publications, can we replace the textual
description of the methods used with a computer program?
1. Enable automation
via microfluidic chips
2. Improve reproducibility
of manual experiments
Related Work
• EXACT: EXperimental ACTions ontology as a formal
representation for biology protocols [Soldatova et al., 2009]
• Robot Scientist: functional genomics driven by
macroscopic laboratory automation [King et al., 2004]
• PoBol: RDF-based data exchange standard for BioBricks
The BioCoder Language
• BioCoder is a protocol language for reuse & automation
– Independent of chip or laboratory setup
– Initial focus: molecular biology
• Implemented as a C library
– Used to express 65 protocols, 5800 lines of code
– Restricted backend: automatic execution on microfluidic chips
– General backend: emit readable instructions for human
• Validation
– Used to direct actions of scientists in the lab (IISc)
– Used to control microfluidic chips (MIT)
– Standardizing online Wiki; interest from Berkeley, UW, UMN…
BioCoder Language Primitives
• Declaration / measurement / disposal
- declare_fluid
- declare_column
- measure_sample
- measure_fluid
- volume
- discard
- transfer
- transfer_column
- declare_tissue
• Combination / mixing
- combine
- mix
- combine_and_mix
- addto_column
- mixing_table
• Centrifugation
- centrifuge_pellet
- centrifuge_phases
- centrifuge_column
• Temperature
- set_temp
- use_or_store
- autoclave
• Timing
- wait
- time_constraint
- store_until
- inoculation
- invert_dry
• Detection
- ce_detect
- gas_chromatography
- nanodrop
- electrophoresis
- mount_observe_slide
- sequencing
Example: Plasmid DNA Extraction
I. Original protocol (Source: Klavins Lab)
Add 100 ul of 7X Lysis Buffer (Blue) and mix by inverting the tube
4-6 times. Proceed to step 3 within 2 minutes.
II. BioCoder code
FluidSample f1 = measure_and_add(f0, lysis_buffer, 100*uL);
FluidSample f2 = mix(f1, INVERT, 4, 6);
time_constraint(f1, 2*MINUTES, next_step);
III. Auto-generated text output
Add 100 ul of 7X Lysis Buffer (Blue).
Invert the tube 4-6 times.
NOTE: Proceed to the next step within 2 mins.
Example: Plasmid DNA Extraction
Auto-Generated
Dependence Graph
1. Data Types
conceptually infinite volume
finite volume
Stock
Sample
Fluid
declare_fluid
instruction
Solid
FluidSample
measure instruction
Can measure symbolic volume
which is resolved by compiler /
runtime system depending on
eventual uses
SolidSample
other instructions
2. Standardizing Ad-Hoc Language
• Need to convert qualitative words to quantitative scale
• Example: a common scale for mixing
–
–
–
–
–
When a protocol says “mix”, it could mean many things
Level 1: tap
Level 2: stir
Level 3: invert
Level 4: vortex / resuspend / dissolve
• Similar issues with temperature, timing, opacity, …
3. Separating Instructions from Hints
• How to translate abstract directions?
– “Remove the medium by aspiration, leaving the bacterial pellet
as dry as possible.”
Centrifuge(&medium, ...);
hint(pellet_dry)
Aspirate and remove medium.
Leave the pellet as dry as possible.
• Hints provide tutorial or self-check information
– Can be ignored if rest of protocol is executed correctly
• Separating instructions and hints keeps language
tractable
– Small number of precise instructions
– Extensible set of hints
4. Generating Readable Instructions
• In typical programming languages, aim to define the
minimal set of orthogonal primitives
• However, for generating readable protocols, separating
primitives can detract from readability
Original: “Mix the sample with 1uL restriction enzyme.”
BioStream with orthogonal primitives:
FluidSample s1 = measure(&restriction_enzyme, 1*uL);
FluidSample s2 = combine(&sample, &s1);
mix(s2, vortex);
Measure out 1uL of restriction enzyme.
Combine the sample with the restriction enzyme.
Mix the combined sample by vortexing.
4. Generating Readable Instructions
• In typical programming languages, aim to define the
minimal set of orthogonal primitives
• However, for generating readable protocols, separating
primitives can detract from readability
Original: “Mix the sample with 1uL restriction enzyme.”
BioStream with compound primitives:
combine_and_mix(&restriction_enzyme, 1*uL,
&sample, vortex);
Add 1uL restriction enzyme and mix by vortexing.
4. Generating Readable Instructions
• In typical programming languages, aim to define the
minimal set of orthogonal primitives
• However, for generating readable protocols, separating
primitives can detract from readability
Original: “Mix the sample with 1uL restriction enzyme.”
BioStream with compound primitives:
combine_and_mix(&restriction_enzyme, 1*uL,
&sample, vortex);
Add 1uL restriction enzyme and mix by vortexing.
• General approaches:
– Detect combined operations with policies (peekhole optimizer)
– Define a standard library that combines primitive operations
4. Generating Readable Instructions
mixing_table_pcr(7,20,array_pcr,initial_conc,
final_conc,vol);
5. Timing Constraints
• Precise timing is critical for many biology protocols
– Minimum delay: cell growth, enzyme digest, denaturing, etc.
– Maximum delay: avoid precipitation, photobleaching, etc.
– Exact delay: regular measurements, synchronized steps, etc.
• May require parallel execution
– Fluid f1 = mix(…); useBetween(f1, 10, 10);
– Fluid f2 = mix(…); useBetween(f2, 10, 10);
– Fluid f3 = mix(f1, f2);
f1
f2
10
10
f3
Benchmark Suite
65 protocols
5800 LOC
Plasmid DNA Extraction
214 lines
PCR
73 lines
repeat
thermocycling
Molecular Barcodes
200 lines
Preparation
+ PCR (2)
DNA Sequencing
Preparation
144 lines
PCR PCR PCR PCR
Analysis
Instruction Usage
Validating the Language
• Eventual validation: automatic execution
– But BioCoder more capable than most chips today
– Need to decouple language research from microfluidics research
• Initial validation: human execution
– In collaboration with Prof. Utpal Nath’s lab at IISc
– Target Plant DNA Isolation, common task for summer intern
Original
Lab Notes
BioCoder
Code
Auto-Generated
Protocol
Execution
in Lab
Biologist is never exposed to original lab notes
• To the best of our knowledge, first execution of a real
biology protocol from a portable programming language
Exposing Ambiguity in Original Protocols
?
3. Add 1.5 vol. CTAB to each MCT and vortex. Incubate at 65°
C for 10-30 mins
4. Add 1 vol. Phenol:chloroform:isoamylalcohol: 48:48:4 and
vortex thoroughly
5. Centrifuge at 13000g at room temperature for 5 mins
6. Transfer aqueous (upper) layer to clean MCT and
repeat the extraction using chloroform: Isoamyalcohol: 96:4
Coding protocols in precise language removes
ambiguity and enables consistency checking
Growing a Community
Growing a Community
Growing a Community
Future Work
• Backends for BioStream
– Generate graphical protocol
– Generate a microfluidic chip to perform protocol
• Reliability and troubleshooting
– Verify that protocol is safe, correct, obeys timing constraints
– If protocol fails, automatically suggest troubleshooting routine
• Building a knowledge base
– Encode experimental results in addition to protocols
– Search for a protocol based on input/output relationship
– Revision control for biology protocols
Conclusions
• Abstraction layers for
programmable microfluidics
–
–
–
–
Microfluidic CAD tools
General-purpose chips
Fluidic ISA
BioCoder language
• Vision for microfluidics:
everyone uses standard chip
• Vision for software:
a defacto language for experimental science
– Download a colleague’s code, run it on your chip
– Compose modules and libraries to enable complex experiments
that are impossible to perform today
Download