317 lines
14 KiB
Plaintext
317 lines
14 KiB
Plaintext
---
|
|
import ExperienceLayout from "@layouts/ExperienceLayout.astro";
|
|
|
|
import H2 from "@components/H2.astro";
|
|
import H3 from "@components/H3.astro";
|
|
import Li from "@components/Li.astro";
|
|
import CustomCarousel from "@components/Media/CustomCarousel/CustomCarousel.astro";
|
|
import Video from "@components/Media/Video.astro";
|
|
import PageGroup from "@components/PageGroup.astro";
|
|
import Paragraph from "@components/Paragraph.astro";
|
|
import Paragraphs from "@components/Paragraphs.astro";
|
|
import PopoverWordDefinition from "@components/PopoverWordDefinition.astro";
|
|
import PrintedCircuitBoard from "@components/PrintedCircuitBoard.astro";
|
|
import SkillMatrix from "@components/SkillMatrix/SkillMatrix.astro";
|
|
import Timeline from "@components/Timeline/Timeline.astro";
|
|
import Ul from "@components/Ul.astro";
|
|
|
|
import type { carouselGroup } from "@interfaces/image-carousel.ts";
|
|
import { timelineFromPrintedCircuitBoard } from "@interfaces/printed-circuit-board.ts";
|
|
import type { categorySkills } from "@interfaces/skill-matrix.ts";
|
|
import type { timelineEntry } from "@interfaces/timeline.ts";
|
|
|
|
import {
|
|
subTitles,
|
|
workingTimeline,
|
|
} from "./osu-sinnhuber-aquatic-research-laboratory.ts";
|
|
|
|
import {
|
|
pnpControl,
|
|
pnpLights,
|
|
} from "./zebrafish-embryo-pick-and-plate-pcbs.ts";
|
|
|
|
import installation_and_tuning from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/installation-and-tuning.jpg";
|
|
import interface_tuning_and_detection from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/interface-tuning-and-detection.png";
|
|
import off_controls_lid_overview from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/off-controls-lid-overview.jpg";
|
|
import off_controls_syringe_overview from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/off-controls-syringe-overview.jpg";
|
|
import off_controls_top_overview from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/off-controls-top-overview.jpg";
|
|
import off_front_working_area_overview from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/off-front-working-area-overview.jpg";
|
|
import off_front from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/off-front.jpg";
|
|
import off_left from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/off-left.jpg";
|
|
import off_lighting from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/off-lighting.jpg";
|
|
import off_rear from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/off-rear.jpg";
|
|
import off_right from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/off-right.jpg";
|
|
import off_touchoff from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/off-touchoff.jpg";
|
|
import on_dishes_lighting_reflection from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/on-dishes-lighting-reflection.jpg";
|
|
import on_front_dishes_beakers from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/on-front-dishes-beakers.jpg";
|
|
import on_front_overview from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/on-front-overview.jpg";
|
|
import on_front from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/on-front.jpg";
|
|
import on_screen from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/on-screen.jpg";
|
|
import on_touchoff_block_isometric from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/on-touchoff-block-isometric.jpg";
|
|
|
|
import pick_and_placing from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/pick-and-placing.mp4";
|
|
import precision_homing from "@assets/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate/precision-homing.mp4";
|
|
import InlineLink from "@components/InlineLink.astro";
|
|
import { DateTime } from "luxon";
|
|
|
|
const headerCarouselGroup: carouselGroup = {
|
|
animation: "slide",
|
|
images: [
|
|
installation_and_tuning,
|
|
on_front_overview,
|
|
interface_tuning_and_detection,
|
|
on_front,
|
|
on_front_dishes_beakers,
|
|
on_screen,
|
|
off_touchoff,
|
|
on_touchoff_block_isometric,
|
|
off_controls_top_overview,
|
|
off_controls_syringe_overview,
|
|
off_controls_lid_overview,
|
|
off_front,
|
|
off_front_working_area_overview,
|
|
off_left,
|
|
off_rear,
|
|
off_right,
|
|
off_lighting,
|
|
on_dishes_lighting_reflection,
|
|
],
|
|
};
|
|
|
|
const timeline: timelineEntry[] = [
|
|
...workingTimeline,
|
|
...timelineFromPrintedCircuitBoard(pnpLights),
|
|
...timelineFromPrintedCircuitBoard(pnpControl),
|
|
{
|
|
event: "Project Started",
|
|
eventDetail: "Initial Requirements Given",
|
|
date: DateTime.fromISO("2013-12-01"),
|
|
},
|
|
{
|
|
event: "Project Finished",
|
|
eventDetail: "Delivered Units to Lab",
|
|
date: DateTime.fromISO("2016-09-01"),
|
|
},
|
|
];
|
|
|
|
const categorizedSkills: categorySkills[] = [
|
|
{
|
|
category: "Software & Environments",
|
|
skills: [
|
|
{
|
|
item: "Version Control",
|
|
subItems: [{ item: "Git" }],
|
|
},
|
|
{
|
|
item: "Programming",
|
|
subItems: [
|
|
{
|
|
item: "Languages",
|
|
subItems: [
|
|
{ item: "Python 2" },
|
|
{ item: "Bash Shell Scripting" },
|
|
{ item: "Low-Level Embedded C/C++ (Atmel Studio)" },
|
|
],
|
|
},
|
|
{
|
|
item: "Frameworks",
|
|
subItems: [{ item: "OpenCV" }, { item: "Qt" }],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
item: "Operating Systems",
|
|
subItems: [
|
|
{
|
|
item: "Linux",
|
|
subItems: [{ item: "Debian" }],
|
|
},
|
|
{ item: "Microsoft Windows" },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
category: "Electrical",
|
|
skills: [
|
|
{
|
|
item: "Schematic & PCB Design",
|
|
subItems: [
|
|
{
|
|
item: "Software",
|
|
subItems: [
|
|
{ item: "Altium Designer" },
|
|
{ item: "Mentor Graphics PADS" },
|
|
],
|
|
},
|
|
{
|
|
item: "Manufacturing",
|
|
subItems: [
|
|
{ item: "Gerber Export" },
|
|
{ item: "BOM Management" },
|
|
{ item: "In-House Assembly" },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
item: "Electrical Diagnostics",
|
|
subItems: [
|
|
{ item: "Multimeters" },
|
|
{ item: "Electronic Loads" },
|
|
{ item: "Oscilloscopes" },
|
|
],
|
|
},
|
|
{
|
|
item: "Harnessing Fabrication",
|
|
subItems: [{ item: "DC Low-Power & Signal" }],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
category: "Mechanical",
|
|
skills: [
|
|
{
|
|
item: "Fabrication",
|
|
subItems: [{ item: "CNC" }, { item: "Hand Tools" }],
|
|
},
|
|
],
|
|
},
|
|
];
|
|
|
|
const videos: string[] = [pick_and_placing, precision_homing];
|
|
---
|
|
|
|
<ExperienceLayout title="Zebrafish Embryo Pick and Plate" subTitles={subTitles}>
|
|
<CustomCarousel carouselGroup={headerCarouselGroup} />
|
|
<PageGroup>
|
|
<Fragment slot="header"><H2>Summary</H2></Fragment>
|
|
<PageGroup>
|
|
<Fragment slot="header"><H3>Timeline</H3></Fragment>
|
|
<Timeline timeline={timeline} />
|
|
</PageGroup>
|
|
<PageGroup>
|
|
<Fragment slot="header"><H3>Key Takeaways</H3></Fragment>
|
|
<Ul>
|
|
<Li
|
|
>Delivered a design, and multiple built units, of a custom embryo
|
|
pick-and-plate machine</Li
|
|
>
|
|
<Li>Reduced cost from ~$150,000 for previous generation to ~$10,000</Li>
|
|
<Li
|
|
>Reduced the size from 4.5'x4.5'x8' for previous generation to
|
|
1'x1'x1.5'</Li
|
|
>
|
|
</Ul>
|
|
</PageGroup>
|
|
<SkillMatrix categorizedSkills={categorizedSkills} />
|
|
</PageGroup>
|
|
<PageGroup>
|
|
<Fragment slot="header"><H2>Details</H2></Fragment>
|
|
<Paragraphs>
|
|
<Paragraph>
|
|
For some quick context on why such a machine was even needed, the
|
|
Sinnhuber Aquatic Research Lab performs toxicology research using
|
|
Zebrafish. This means tha the lab is also a breeding facility,
|
|
generating a few thousand eggs a day, which need to be processed and
|
|
isolated prior to being introduced to experimental conditions. At one
|
|
point in time, these processes were done by hand, with all researchers
|
|
spending a significant portion of their day simply prepping the embryos.
|
|
Later on, they hired a contractor to design an automated solution to the
|
|
isolation problem, and while they delivered, the units were industrial
|
|
overkill, using massive <PopoverWordDefinition key="SCARA" /> arms and enclosures
|
|
to pick up embryos which were roughly half a millimeter in diameter. They
|
|
were also very expensive, costing around $150k per machine, and the lab had
|
|
four installed. Thus, the engineering team was tasked with cost and size reducing
|
|
them so that more could fit in the same space and throughput could be higher.
|
|
</Paragraph>
|
|
<Paragraph>
|
|
My coworker, <InlineLink href="https://dylanthrush.com"
|
|
>Dylan Thrush</InlineLink
|
|
>, and I got to work. He focussed on the mechanical side, while I worked
|
|
on electrical and software. I had recently been learning PCB design
|
|
after becoming more familiar with it through the OSU robotics club, and
|
|
decided that a good place to start would be to create a motion
|
|
controller. Dylan and I had already landed on a simple stepper-motor
|
|
based system to more than meet the needs of a task like this, and both
|
|
of us already had experience with stepper-based CNC machines, making it
|
|
a great jumpoff point. My first PCB was unfortunately a massive failure,
|
|
because while I did include a quad stepper motor driver,
|
|
microcontroller, general purpose I/O, and usb to serial interface, I
|
|
failed to export the gerbers correctly. This resulted in a PCB with no
|
|
drills, making it completely useless (outside of a good learning
|
|
experience)! It was also just a poor layout overall, which isn't
|
|
surprising considering it was my first ever PCB design. If you want to
|
|
see this embarrassing result, check out the PCB section at the end of
|
|
this page!
|
|
</Paragraph>
|
|
<Paragraph>
|
|
For the second revision, we'd made some progress in other places, but
|
|
most importantly had decided that we would use a <InlineLink
|
|
href="https://www.beagleboard.org/boards/beaglebone-black"
|
|
>Beaglebone Black</InlineLink
|
|
> single-board-computer to run the whole system. In an effort to simplify
|
|
the assembly, I decided that the next revision would include headers to directly
|
|
mount the Beaglebone to the unit, providing power and a serial interface over
|
|
those pins. This version actually worked as expected, with only a few very
|
|
minor bodges to the microcontroller's crystal, and some bulk capacitance on
|
|
the power input. Since things were working, I began writing embedded C to
|
|
control motion through some higher-level interfaces. Not long into this process,
|
|
I realized I might have bitten off more than I could chew. Not only was I
|
|
having to learn the deep ins and outs of microcontroller programming, kinematics,
|
|
and serial interfaces, but I would still have to greatly improve my Python
|
|
skills, learn to create graphical user interfaces, and figure out how to detect
|
|
embryos using a camera and computer vision. While I was sad to scrap this,
|
|
we decided to fall back on a motion controller called <InlineLink
|
|
href="https://synthetos.com/project/tinyg">TinyG</InlineLink
|
|
>, which would simply require gcode to be sent over serial to function.
|
|
</Paragraph>
|
|
<Paragraph>
|
|
Dylan built up a mechanical testbed, which we could mount a camera to,
|
|
and I began to focus on embryo detection. I was relatively new to
|
|
Python, but quickly found the Qt framework for building decent-looking
|
|
interfaces, and OpenCV for providing generic detection capabilities via
|
|
webcams. Over the next few years (remember, we were students doing this
|
|
part time, and working on other projects simultaneously), I eventually
|
|
created a fairly comprehensive user interface that would allow
|
|
researchers to tune detection and motion parameters on-the-fly. This was
|
|
shown on a touchscreen that the beaglebone plugged into, making it quite
|
|
intuitive. Dylan had also created a mechanical foundation providing
|
|
repeatable alignment for a petri dish with embryos, the 96-well plate
|
|
for placement, and a waste container to get rid of extra water in our
|
|
metal pipette tip that would be used to pick up the embryos. I'd also
|
|
created some very bright lighting boards to mount to the unit's
|
|
extrusion, illuminating the embryos from the side, something that was
|
|
absolutely required for consistent detection with the camera. After a
|
|
long journey, we finally delivered multiple units to the lab! Seeing
|
|
such small devices performing the same task next to the behemoths which
|
|
were the prior versions was quite amusing. You could easily fit a two by
|
|
two grid of these in the working area of each of those machines.
|
|
Overall, this was a highly ambitious project, but it developed some of
|
|
my most successful skills I gained while at OSU while accelerating the
|
|
research at the lab!
|
|
</Paragraph>
|
|
</Paragraphs>
|
|
</PageGroup>
|
|
<PageGroup>
|
|
<Fragment slot="header"><H2>Videos</H2></Fragment>
|
|
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
|
|
{
|
|
videos.map((video) => (
|
|
<Video
|
|
videoPath={video}
|
|
autoPlay={true}
|
|
loop={true}
|
|
playsInline={true}
|
|
/>
|
|
))
|
|
}
|
|
</div>
|
|
</PageGroup>
|
|
<PageGroup>
|
|
<Fragment slot="header"><H2>Printed Circuit Boards</H2></Fragment>
|
|
<PrintedCircuitBoard pcb={pnpLights} />
|
|
<PrintedCircuitBoard pcb={pnpControl} />
|
|
</PageGroup>
|
|
</ExperienceLayout>
|