Merge pull request 'Finished ross content, added skill matrix, li, and ul, and improved many existing components, created and refactored to unified layouts and grid, visual improvements with proper column to row collapsing' (#13) from website-content-updates into main
Reviewed-on: #13
This commit was merged in pull request #13.
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
ADCP
|
||||
Altium
|
||||
ASSEM
|
||||
astrojs
|
||||
Atmel
|
||||
barebones
|
||||
Candian
|
||||
caperren
|
||||
CEOAS
|
||||
@@ -10,6 +13,7 @@ CONSERV
|
||||
Corwin
|
||||
dangerousthings
|
||||
Dechorionator
|
||||
ebox
|
||||
fhhs
|
||||
flowbite
|
||||
HDFS
|
||||
@@ -19,10 +23,13 @@ hwupload
|
||||
iceops
|
||||
ITAR
|
||||
Jetson
|
||||
KFSK
|
||||
leconte
|
||||
Loctite
|
||||
luxon
|
||||
MGMT
|
||||
Mokai
|
||||
Multimeters
|
||||
nixos
|
||||
offroad
|
||||
Onshape
|
||||
@@ -30,6 +37,7 @@ OSSM
|
||||
OSURC
|
||||
Perren
|
||||
Perren's
|
||||
Pixhawk
|
||||
pubpath
|
||||
RFID
|
||||
RSSI
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
@@ -2,4 +2,4 @@
|
||||
|
||||
---
|
||||
|
||||
<h1 class="text-xl font-extrabold md:text-3xl"><slot /></h1>
|
||||
<h1 class="text-xl font-extrabold sm:text-2xl md:text-3xl"><slot /></h1>
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
---
|
||||
|
||||
<h2 class="my-4 font-bold md:text-2xl"><slot /></h2>
|
||||
<h2 class="text-lg font-bold sm:text-xl md:text-2xl"><slot /></h2>
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
---
|
||||
|
||||
<h3 class="mt-4 mb-2 font-bold md:text-lg"><slot /></h3>
|
||||
<h3 class="text-md font-semibold sm:text-lg md:text-xl"><slot /></h3>
|
||||
|
||||
9
src/components/Li.astro
Normal file
9
src/components/Li.astro
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
<>
|
||||
<li>
|
||||
<slot />
|
||||
</li>
|
||||
</>
|
||||
@@ -9,10 +9,12 @@ interface Props {
|
||||
const { title, href, target = "_blank" } = Astro.props;
|
||||
---
|
||||
|
||||
<a
|
||||
class="text-caperren-green border-caperren-green hover:border-caperren-green-light hover:text-caperren-green-light rounded-2xl border-2 bg-black p-2"
|
||||
href={href}
|
||||
target={target}
|
||||
>
|
||||
{title}
|
||||
</a>
|
||||
<div class="mx-auto">
|
||||
<a
|
||||
class="text-caperren-green border-caperren-green hover:border-caperren-green-light hover:text-caperren-green-light rounded-2xl border-2 bg-black p-2"
|
||||
href={href}
|
||||
target={target}
|
||||
>
|
||||
{title}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -39,7 +39,7 @@ import { Image } from "astro:assets";
|
||||
</svg>
|
||||
</button>
|
||||
<div
|
||||
class="z-40 mt-1 hidden w-full lg:block lg:w-auto"
|
||||
class="z-40 mt-6 hidden w-full lg:mt-0 lg:block lg:w-auto"
|
||||
id="navbar-multi-level"
|
||||
>
|
||||
<NestedNavbarEntry items={siteLayout} />
|
||||
|
||||
@@ -19,29 +19,34 @@ const { pathname } = Astro.url;
|
||||
---
|
||||
|
||||
<ul
|
||||
class={"flex flex-col p-4 bg-black border-caperren-green " +
|
||||
(depth ? "space-y-2" : "items-start lg:flex-row lg:space-x-8 lg:mt-0 ")}
|
||||
class:list={[
|
||||
"border-caperren-green flex flex-col space-y-4 space-x-8 bg-black",
|
||||
depth
|
||||
? "space-y-4 py-4"
|
||||
: "items-start lg:mt-0 lg:flex-row lg:space-y-0 lg:space-x-8",
|
||||
]}
|
||||
>
|
||||
{
|
||||
items.map(
|
||||
(entry) =>
|
||||
(entry.enabled ?? true) && (
|
||||
<li>
|
||||
<li class="">
|
||||
{Array.isArray(entry.children) && entry.children.length ? (
|
||||
<div
|
||||
class={
|
||||
pathname.startsWith(getHrefPath(entry))
|
||||
? "border-caperren-green border-b-2"
|
||||
: ""
|
||||
}
|
||||
>
|
||||
<div>
|
||||
<button
|
||||
id={"dropdownNavbarLink" + getNavLinkSuffix(entry)}
|
||||
data-dropdown-toggle={
|
||||
"dropdownNavbar" + getNavLinkSuffix(entry)
|
||||
}
|
||||
data-dropdown-placement="bottom"
|
||||
class="hover:text-caperren-green-light lg:hover:text-caperren-green-light flex w-full items-center justify-between px-3 py-2 lg:p-0 lg:hover:bg-transparent"
|
||||
data-dropdown-placement="bottom-start"
|
||||
data-dropdown-offset-distance="5"
|
||||
data-dropdown-offset-skidding="12"
|
||||
class:list={[
|
||||
"hover:text-caperren-green-light lg:hover:text-caperren-green-light flex w-full items-center justify-between lg:p-0 lg:hover:bg-transparent",
|
||||
pathname.startsWith(getHrefPath(entry))
|
||||
? "border-caperren-green border-b-2"
|
||||
: false,
|
||||
]}
|
||||
>
|
||||
{entry.navText}
|
||||
<svg
|
||||
@@ -61,7 +66,7 @@ const { pathname } = Astro.url;
|
||||
</button>
|
||||
<div
|
||||
id={"dropdownNavbar" + getNavLinkSuffix(entry)}
|
||||
class="border-caperren-green z-10 hidden w-screen border bg-black shadow-sm lg:w-max"
|
||||
class="border-caperren-green z-10 hidden w-max max-w-screen border bg-black px-6 shadow-sm"
|
||||
>
|
||||
<Astro.self
|
||||
items={entry.children}
|
||||
@@ -71,17 +76,16 @@ const { pathname } = Astro.url;
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
class={
|
||||
pathname === getHrefPath(entry)
|
||||
? "border-caperren-green border-b-2"
|
||||
: ""
|
||||
}
|
||||
>
|
||||
<div>
|
||||
<a
|
||||
href={getHrefPath(entry)}
|
||||
target={getHrefPath(entry).startsWith("/") ? "" : "_blank"}
|
||||
class="hover:text-caperren-green-light ring-caperren-green-dark block bg-transparent px-3 py-2 lg:p-0"
|
||||
class:list={[
|
||||
"hover:text-caperren-green-light ring-caperren-green-dark block bg-transparent lg:p-0",
|
||||
pathname === getHrefPath(entry)
|
||||
? "border-caperren-green border-b-2"
|
||||
: false,
|
||||
]}
|
||||
aria-current={
|
||||
pathname === getHrefPath(entry) ? "page" : undefined
|
||||
}
|
||||
|
||||
36
src/components/Ol.astro
Normal file
36
src/components/Ol.astro
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
import Li from "@components/Li.astro";
|
||||
import type { ComponentPropsBase } from "@interfaces/components.ts";
|
||||
|
||||
import type { lineItem } from "@interfaces/ul-li.ts";
|
||||
|
||||
interface Props extends ComponentPropsBase {
|
||||
lineItems?: lineItem[];
|
||||
depth?: number;
|
||||
}
|
||||
|
||||
const { class: className, lineItems, depth = 0 } = Astro.props;
|
||||
---
|
||||
|
||||
<ol
|
||||
class:list={["list-inside list-disc", className, depth > 0 ? "ps-3" : false]}
|
||||
>
|
||||
{
|
||||
lineItems ? (
|
||||
lineItems.map((line) => (
|
||||
<Li>
|
||||
{line.item}
|
||||
{line.subItems ? (
|
||||
<Astro.self
|
||||
class={className}
|
||||
lineItems={line.subItems}
|
||||
depth={depth + 1}
|
||||
/>
|
||||
) : undefined}
|
||||
</Li>
|
||||
))
|
||||
) : (
|
||||
<slot />
|
||||
)
|
||||
}
|
||||
</ol>
|
||||
21
src/components/PageGroup.astro
Normal file
21
src/components/PageGroup.astro
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
const hasHeader = Astro.slots.has("header");
|
||||
const hasDefault = Astro.slots.has("default");
|
||||
---
|
||||
|
||||
<div class="grid grid-cols-1 gap-3">
|
||||
{
|
||||
Astro.slots.has("header") && (
|
||||
<div>
|
||||
<slot name="header" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{
|
||||
Astro.slots.has("default") && (
|
||||
<div class="grid grid-cols-1 gap-3">
|
||||
<slot />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
@@ -1,7 +1,13 @@
|
||||
---
|
||||
import type { ComponentPropsBase } from "@interfaces/components.ts";
|
||||
|
||||
interface Props extends ComponentPropsBase {
|
||||
initialTab?: boolean;
|
||||
}
|
||||
|
||||
const { class: className, initialTab = true } = Astro.props;
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
<div class="">
|
||||
<slot />
|
||||
<div class:list={className}>
|
||||
{initialTab && <> </>}<slot />
|
||||
</div>
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
|
||||
---
|
||||
|
||||
<div class="space-y-2">
|
||||
<div class="grid grid-cols-1 gap-2">
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
@@ -7,6 +7,10 @@ const keys: { [key: string]: string } = {
|
||||
ADCP: "Acoustic doppler current profiler",
|
||||
COTS: "Consumer off-the-shelf",
|
||||
CTD: "Conductivity, temperature, and depth sensor",
|
||||
GUI: "Graphical user interface",
|
||||
NUC: "A small and low-power computer made by Intel",
|
||||
PCBs: "Printed circuit boards",
|
||||
UPS: "Uninterruptible power supply",
|
||||
};
|
||||
|
||||
const key: string | undefined = Astro.props.key;
|
||||
|
||||
30
src/components/SkillMatrix/SkillMatrix.astro
Normal file
30
src/components/SkillMatrix/SkillMatrix.astro
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
import H3 from "@components/H3.astro";
|
||||
import PageGroup from "@components/PageGroup.astro";
|
||||
import Ul from "@components/Ul.astro";
|
||||
|
||||
import type { categorySkills } from "@interfaces/skill-matrix.ts";
|
||||
|
||||
interface Props {
|
||||
categorizedSkills: categorySkills[];
|
||||
}
|
||||
|
||||
const { categorizedSkills } = Astro.props;
|
||||
---
|
||||
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H3>Relevant Skills</H3></Fragment>
|
||||
<div
|
||||
class="border-caperren-green grid grid-flow-row gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4"
|
||||
>
|
||||
{
|
||||
categorizedSkills.map((categorySkills) => (
|
||||
<div>
|
||||
<div class="text-sm font-extrabold">{categorySkills.category}</div>
|
||||
<hr class="text-caperren-green" />
|
||||
<Ul class="text-sm" lineItems={categorySkills.skills} />
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</PageGroup>
|
||||
36
src/components/Ul.astro
Normal file
36
src/components/Ul.astro
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
import Li from "@components/Li.astro";
|
||||
import type { ComponentPropsBase } from "@interfaces/components.ts";
|
||||
|
||||
import type { lineItem } from "@interfaces/ul-li.ts";
|
||||
|
||||
interface Props extends ComponentPropsBase {
|
||||
lineItems?: lineItem[];
|
||||
depth?: number;
|
||||
}
|
||||
|
||||
const { class: className, lineItems, depth = 0 } = Astro.props;
|
||||
---
|
||||
|
||||
<ul
|
||||
class:list={["list-inside list-disc", className, depth > 0 ? "ps-3" : false]}
|
||||
>
|
||||
{
|
||||
lineItems ? (
|
||||
lineItems.map((line) => (
|
||||
<Li>
|
||||
{line.item}
|
||||
{line.subItems ? (
|
||||
<Astro.self
|
||||
class={className}
|
||||
lineItems={line.subItems}
|
||||
depth={depth + 1}
|
||||
/>
|
||||
) : undefined}
|
||||
</Li>
|
||||
))
|
||||
) : (
|
||||
<slot />
|
||||
)
|
||||
}
|
||||
</ul>
|
||||
@@ -4,7 +4,7 @@ export const siteLayout: navLink[] = [
|
||||
{ navText: "About", path: "" },
|
||||
{ navText: "Education", path: "education" },
|
||||
{
|
||||
navText: "Experiences",
|
||||
navText: "Experience",
|
||||
path: "experience",
|
||||
children: [
|
||||
{
|
||||
@@ -29,7 +29,6 @@ export const siteLayout: navLink[] = [
|
||||
path: "osu-ceoas-ocean-mixing-group",
|
||||
children: [
|
||||
{
|
||||
enabled: false,
|
||||
navText: "Robotics Oceanographic Surface Sampler",
|
||||
path: "robotic-oceanographic-surface-sampler",
|
||||
},
|
||||
|
||||
6
src/interfaces/skill-matrix.ts
Normal file
6
src/interfaces/skill-matrix.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import type { lineItem } from "@interfaces/ul-li.ts";
|
||||
|
||||
export interface categorySkills {
|
||||
category: string;
|
||||
skills: lineItem[];
|
||||
}
|
||||
4
src/interfaces/ul-li.ts
Normal file
4
src/interfaces/ul-li.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export interface lineItem {
|
||||
item: string;
|
||||
subItems?: lineItem[];
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import "@styles/global.css";
|
||||
import Footer from "@components/Footer.astro";
|
||||
import H1 from "@components/H1.astro";
|
||||
import Navbar from "@components/Navbar.astro";
|
||||
import PageGroup from "@components/PageGroup.astro";
|
||||
|
||||
import { pathToMetadata } from "@data/site-layout.ts";
|
||||
|
||||
@@ -39,28 +40,32 @@ const pageEnabled = pathToMetadata(Astro.url.pathname).enabled ?? true;
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>{pageEnabled ? pageTitle : "Corwin Perren"}</title>
|
||||
</head>
|
||||
<body class="flex h-dvh w-full max-w-full flex-col bg-black text-white">
|
||||
<body
|
||||
class="grid h-dvh w-full max-w-full grid-cols-1 gap-0 bg-black text-white"
|
||||
>
|
||||
<div
|
||||
id="content-body-scrolling"
|
||||
class="grow overflow-x-hidden overflow-y-scroll"
|
||||
>
|
||||
<Navbar />
|
||||
<main class="mx-6 my-6">
|
||||
<div class="mb-2 md:mb-6">
|
||||
{
|
||||
title && showTitle && pageEnabled && (
|
||||
<H1 bottomMargin={!subTitles}>{title}</H1>
|
||||
)
|
||||
}
|
||||
{
|
||||
showTitle &&
|
||||
pageEnabled &&
|
||||
subTitles?.map((subTitle) => (
|
||||
<p class="text-sm font-bold md:text-xl">{subTitle}</p>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
<div>
|
||||
<main class="mx-6 my-2">
|
||||
{
|
||||
showTitle && pageEnabled && (
|
||||
<PageGroup>
|
||||
<Fragment slot="header">
|
||||
<div class="leading-3">
|
||||
<H1>{title}</H1>
|
||||
{subTitles?.map((subTitle) => (
|
||||
<p class="md:text-md text-sm font-bold italic">
|
||||
{subTitle}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
</Fragment>
|
||||
</PageGroup>
|
||||
)
|
||||
}
|
||||
<div class="grid grid-cols-1 gap-4">
|
||||
{pageEnabled ? <slot /> : <H1>Under Construction</H1>}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
---
|
||||
import PdfViewer from "@components/Media/PdfViewer.astro";
|
||||
import BaseLayout from "@layouts/BaseLayout.astro";
|
||||
|
||||
import PdfViewer from "@components/Media/PdfViewer.astro";
|
||||
---
|
||||
|
||||
<BaseLayout {...Astro.props}>
|
||||
<div class="h-dvh">
|
||||
<PdfViewer class="mx-auto" pdf={Astro.props.resume} />
|
||||
<div class="mt-2 h-dvh">
|
||||
<PdfViewer pdf={Astro.props.resume} />
|
||||
</div>
|
||||
</BaseLayout>
|
||||
|
||||
@@ -5,6 +5,7 @@ import H2 from "@components/H2.astro";
|
||||
import H3 from "@components/H3.astro";
|
||||
import InlineLink from "@components/InlineLink.astro";
|
||||
import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro";
|
||||
import PageGroup from "@components/PageGroup.astro";
|
||||
import Table from "@components/Table.astro";
|
||||
import Timeline from "@components/Timeline/Timeline.astro";
|
||||
|
||||
@@ -108,16 +109,24 @@ const courseTable: tableData = {
|
||||
|
||||
<BaseLayout title="Education">
|
||||
<Carousel carouselGroup={diplomaCarouselGroup} />
|
||||
<H2>Timeline</H2>
|
||||
<Timeline timeline={timeline} />
|
||||
<H2>Oregon State University</H2>
|
||||
<H3>
|
||||
<InlineLink
|
||||
class="font-bold md:text-lg"
|
||||
href="https://github.com/caperren/school_archives/tree/master/OSU%20Coursework"
|
||||
>Coursework Archives</InlineLink
|
||||
>
|
||||
</H3>
|
||||
<H3>Course Listing</H3>
|
||||
<Table data={courseTable} />
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H2>Timeline</H2></Fragment>
|
||||
<Timeline timeline={timeline} />
|
||||
</PageGroup>
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H2>Oregon State University</H2></Fragment>
|
||||
<PageGroup>
|
||||
<Fragment slot="header">
|
||||
<InlineLink
|
||||
class="font-bold md:text-lg"
|
||||
href="https://github.com/caperren/school_archives/tree/master/OSU%20Coursework"
|
||||
><H3>Coursework Archives</H3></InlineLink
|
||||
>
|
||||
</Fragment>
|
||||
</PageGroup>
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H3>Course Listing</H3></Fragment>
|
||||
<Table data={courseTable} />
|
||||
</PageGroup>
|
||||
</PageGroup>
|
||||
</BaseLayout>
|
||||
|
||||
@@ -3,8 +3,13 @@ import ExperienceLayout from "@layouts/ExperienceLayout.astro";
|
||||
|
||||
import H2 from "@components/H2.astro";
|
||||
import H3 from "@components/H3.astro";
|
||||
import InlineLink from "@components/InlineLink.astro";
|
||||
import Carousel 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 Timeline from "@components/Timeline/Timeline.astro";
|
||||
|
||||
import type { carouselGroup } from "@interfaces/image-carousel.ts";
|
||||
@@ -56,83 +61,89 @@ const headerCarouselGroup: carouselGroup = {
|
||||
],
|
||||
};
|
||||
|
||||
import InlineLink from "@components/InlineLink.astro";
|
||||
import Video from "@components/Media/Video.astro";
|
||||
import Paragraphs from "@components/Paragraphs.astro";
|
||||
import PopoverWordDefinition from "@components/PopoverWordDefinition.astro";
|
||||
import { subTitles } from "./osu-ceoas-ocean-mixing-group.ts";
|
||||
---
|
||||
|
||||
<ExperienceLayout title="LeConte Glacier Deployments" subTitles={subTitles}>
|
||||
<Carousel carouselGroup={headerCarouselGroup} />
|
||||
<H2>Summary</H2>
|
||||
<H3>Timeline</H3>
|
||||
<Timeline timeline={deploymentTimeline} />
|
||||
<H3>Location</H3>
|
||||
<iframe
|
||||
class="w-full"
|
||||
width="600"
|
||||
height="450"
|
||||
src="https://maps.google.com/maps?q=leconte%20glacier&t=k&z=11&ie=UTF8&iwloc=B&output=embed"
|
||||
></iframe>
|
||||
<H2>Details</H2>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
As part of my time working on the
|
||||
<InlineLink
|
||||
href="/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler"
|
||||
>
|
||||
Robotic Oceanographic Surface Sampler</InlineLink
|
||||
>, I had the fantastic opportunity to be deployed at the LeConte Glacier
|
||||
in Alaska! This started in early 2017 with setup and ocean trials in
|
||||
nearby Petersburg. The team had sent multiple shipping containers with our
|
||||
robotic platforms and most equipment to assemble, test, and debug them a
|
||||
few months prior, allowing us to get to work the moment we arrived. We
|
||||
spent multiple weeks at the docks with our makeshift workstations built
|
||||
from plywood and pelican cases, validating the hardware we'd sent, and
|
||||
making adjustments with improved hardware we'd hand-carried on our
|
||||
flights. This also provided a great opportunity to work out any final
|
||||
firmware and/or software bugs while the vehicles were still relatively
|
||||
easy to retrieve. After a short trip back home to recover, and prep any
|
||||
last minute items we'd forgotten, our research team flew back and headed
|
||||
for the glacier!
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
The towering mountain of ice sits roughly 30 miles from Petersburg, so
|
||||
we'd commissioned an off-season fishing vessel, Steller, and it's crew, to
|
||||
take us as close to it as was reasonably safe. The team worked 24 hours a
|
||||
day, on two shifts, deploying and retrieving the ROSS platforms,
|
||||
performing repairs (as needed), recovering/processing collected data,
|
||||
manually deploying the ship's <PopoverWordDefinition key="CTD" />, and
|
||||
occasionally spending considerable time pushing icebergs the size of
|
||||
houses away from an <PopoverWordDefinition key="ADCP" /> mounted to Steller
|
||||
using fiberglass poles. Many hardware failures had to be solved during these
|
||||
long days, and it was a very rewarding and creative experience to work around
|
||||
the limitations of this isolated (and salty) environment.
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
On top of being a unique engineering and team building experience, LeConte
|
||||
lives among the most beautiful places I've yet to experience in this life.
|
||||
There's something special about being somewhere so incredibly remote and
|
||||
untouched by humans. The pristine evergreen forests, eerie blue-green hues
|
||||
of the glacier and icebergs, ancient towering mountains, and genuinely
|
||||
curious looks from local land and marine life unfamiliar with human
|
||||
presence made it humbly clear that for once we as humans were the odd ones
|
||||
out. These trips were ones that I will treasure and think back on fondly
|
||||
on for the rest of my life.
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<H2>Videos</H2>
|
||||
<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>
|
||||
<Fragment slot="header"><H2>Summary</H2></Fragment>
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H3>Timeline</H3></Fragment>
|
||||
<Timeline timeline={deploymentTimeline} />
|
||||
</PageGroup>
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H3>Location</H3></Fragment>
|
||||
<iframe
|
||||
class="w-full"
|
||||
width="600"
|
||||
height="450"
|
||||
src="https://maps.google.com/maps?q=leconte%20glacier&t=k&z=11&ie=UTF8&iwloc=B&output=embed"
|
||||
></iframe>
|
||||
</PageGroup>
|
||||
</PageGroup>
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H2>Details</H2></Fragment>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
As part of my time working on the
|
||||
<InlineLink
|
||||
href="/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler"
|
||||
>
|
||||
Robotic Oceanographic Surface Sampler</InlineLink
|
||||
>, I had the fantastic opportunity to be deployed at the LeConte Glacier
|
||||
in Alaska! This started in early 2017 with setup and ocean trials in
|
||||
nearby Petersburg. The team had sent multiple shipping containers with
|
||||
our robotic platforms and most equipment to assemble, test, and debug
|
||||
them a few months prior, allowing us to get to work the moment we
|
||||
arrived. We spent multiple weeks at the docks with our makeshift
|
||||
workstations built from plywood and pelican cases, validating the
|
||||
hardware we'd sent, and making adjustments with improved hardware we'd
|
||||
hand-carried on our flights. This also provided a great opportunity to
|
||||
work out any final firmware and/or software bugs while the vehicles were
|
||||
still relatively easy to retrieve. After a short trip back home to
|
||||
recover, and prep any last minute items we'd forgotten, our research
|
||||
team flew back and headed for the glacier!
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
The towering mountain of ice sits roughly 30 miles from Petersburg, so
|
||||
we'd commissioned an off-season fishing vessel, Steller, and it's crew,
|
||||
to take us as close to it as was reasonably safe. The team worked 24
|
||||
hours a day, on two shifts, deploying and retrieving the ROSS platforms,
|
||||
performing repairs (as needed), recovering/processing collected data,
|
||||
manually deploying the ship's <PopoverWordDefinition key="CTD" />, and
|
||||
occasionally spending considerable time pushing icebergs the size of
|
||||
houses away from an <PopoverWordDefinition key="ADCP" /> mounted to Steller
|
||||
using fiberglass poles. Many hardware failures had to be solved during these
|
||||
long days, and it was a very rewarding and creative experience to work around
|
||||
the limitations of this isolated (and salty) environment.
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
On top of being a unique engineering and team building experience,
|
||||
LeConte lives among the most beautiful places I've yet to experience in
|
||||
this life. There's something special about being somewhere so incredibly
|
||||
remote and untouched by humans. The pristine evergreen forests, eerie
|
||||
blue-green hues of the glacier and icebergs, ancient towering mountains,
|
||||
and genuinely curious looks from local land and marine life unfamiliar
|
||||
with human presence made it humbly clear that for once we as humans were
|
||||
the odd ones out. These trips were ones that I will treasure and think
|
||||
back on fondly on for the rest of my life.
|
||||
</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>
|
||||
</ExperienceLayout>
|
||||
|
||||
@@ -26,4 +26,5 @@ export const deploymentTimeline: timelineEntry[] = [
|
||||
export const subTitles = [
|
||||
"Oregon State University",
|
||||
"College of Earth, Ocean, and Atmospheric Sciences",
|
||||
"Ocean Mixing Group",
|
||||
];
|
||||
|
||||
@@ -3,17 +3,26 @@ import ExperienceLayout from "@layouts/ExperienceLayout.astro";
|
||||
|
||||
import H2 from "@components/H2.astro";
|
||||
import H3 from "@components/H3.astro";
|
||||
import InlineLink from "@components/InlineLink.astro";
|
||||
import Li from "@components/Li.astro";
|
||||
import LinkButton from "@components/LinkButton.astro";
|
||||
import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro";
|
||||
import PdfViewer from "@components/Media/PdfViewer.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 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 type { categorySkills } from "@interfaces/skill-matrix.ts";
|
||||
import type { timelineEntry } from "@interfaces/timeline.ts";
|
||||
|
||||
import electronics_box from "@assets/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler/electronics-box.jpg";
|
||||
import jet_drive from "@assets/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler/jet-drive.jpg";
|
||||
import ross_ebox_4p0 from "@assets/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler/ross-ebox-4p0.jpg";
|
||||
import ross_on_vessel_at_night from "@assets/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler/ross-on-vessel-at-night.jpg";
|
||||
import ross_on_vessel from "@assets/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler/ross-on-vessel.jpg";
|
||||
import publication from "@assets/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler/ross-publication.pdf";
|
||||
@@ -31,6 +40,7 @@ const headerCarouselGroup: carouselGroup = {
|
||||
ross_team,
|
||||
ross_on_vessel,
|
||||
ross_on_vessel_at_night,
|
||||
ross_ebox_4p0,
|
||||
electronics_box,
|
||||
jet_drive,
|
||||
ui,
|
||||
@@ -50,6 +60,72 @@ const timeline: timelineEntry[] = [
|
||||
date: "May 2018",
|
||||
},
|
||||
];
|
||||
|
||||
const categorizedSkills: categorySkills[] = [
|
||||
{
|
||||
category: "Electrical",
|
||||
skills: [
|
||||
{
|
||||
item: "Schematic & PCB Design",
|
||||
subItems: [{ item: "Altium Designer" }],
|
||||
},
|
||||
{
|
||||
item: "PCB Assembly & Rework",
|
||||
subItems: [
|
||||
{ item: "Handheld Soldering" },
|
||||
{ item: "Handheld Hot-Air Reflow" },
|
||||
{ item: "Oven Reflow" },
|
||||
],
|
||||
},
|
||||
{
|
||||
item: "Electrical Diagnostics",
|
||||
subItems: [
|
||||
{ item: "Multimeters" },
|
||||
{ item: "Oscilloscopes" },
|
||||
{ item: "Logic Analyzers" },
|
||||
],
|
||||
},
|
||||
{
|
||||
item: "Harnessing Fabrication",
|
||||
subItems: [
|
||||
{ item: "DC Power & Signal" },
|
||||
{ item: "Low Frequency RF (<1GHz)" },
|
||||
{ item: "Waterproofing" },
|
||||
],
|
||||
},
|
||||
{
|
||||
item: "Simulation",
|
||||
subItems: [{ item: "LTspice" }],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
category: "Software & Environments",
|
||||
skills: [
|
||||
{ item: "Git" },
|
||||
{
|
||||
item: "Programming Languages",
|
||||
subItems: [
|
||||
{ item: "Python 2/3" },
|
||||
{ item: "Bash Shell Scripting" },
|
||||
{ item: "Low-Level Embedded C/C++ (Atmel Studio)" },
|
||||
{ item: "High-Level Embedded C/C++ (Arduino/Teensy)" },
|
||||
{ item: "Matlab" },
|
||||
],
|
||||
},
|
||||
{
|
||||
item: "Operating Systems",
|
||||
subItems: [
|
||||
{
|
||||
item: "Linux",
|
||||
subItems: [{ item: "Ubuntu" }, { item: "Raspbian" }],
|
||||
},
|
||||
{ item: "Microsoft Windows" },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
---
|
||||
|
||||
<ExperienceLayout
|
||||
@@ -57,56 +133,158 @@ const timeline: timelineEntry[] = [
|
||||
subTitles={subTitles}
|
||||
>
|
||||
<Carousel carouselGroup={headerCarouselGroup} />
|
||||
<div class="mt-4 flex items-center justify-center">
|
||||
<div class="grid grid-flow-row place-content-center gap-4 md:grid-flow-col">
|
||||
<LinkButton
|
||||
href="https://tos.org/oceanography/article/autonomous-ctd-profiling-from-the-robotic-oceanographic-surface-sampler"
|
||||
title="Official Scientific Publication"
|
||||
/>
|
||||
<LinkButton
|
||||
href="https://www.kfsk.org/2017/04/19/remote-controlled-kayaks-ready-research-leconte-glacier/"
|
||||
title="KFSK Petersburg Feature / Interview"
|
||||
/>
|
||||
</div>
|
||||
<H2>Summary</H2>
|
||||
<H3>Timeline</H3>
|
||||
<Timeline timeline={timeline} />
|
||||
<H3>Key Takeaways</H3>
|
||||
<ul class="list-inside list-disc">
|
||||
<li>
|
||||
<div class="inline-block">
|
||||
Assembled, fabricated, and debugged both custom and
|
||||
<PopoverWordDefinition key="COTS" />
|
||||
hardware and electronics.
|
||||
</div>
|
||||
</li>
|
||||
<li>Two</li>
|
||||
<li>Three</li>
|
||||
</ul>
|
||||
<h3 class="my-4 font-bold md:text-lg">Skills Used</h3>
|
||||
<div
|
||||
class="border-caperren-green relative grid grid-flow-row gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4"
|
||||
>
|
||||
<div>
|
||||
<div class="text-sm font-extrabold">Software</div>
|
||||
<hr class="text-caperren-green" />
|
||||
<ul class="list-inside list-disc text-sm">
|
||||
<li>One</li>
|
||||
<li>Two</li>
|
||||
</ul>
|
||||
<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
|
||||
>Hand assembled and validated dozens of custom <PopoverWordDefinition
|
||||
key="PCBs"
|
||||
/>, wiring harnesses, and electronics boxes</Li
|
||||
>
|
||||
<Li
|
||||
>Wrote, debugged, and assisted with development of embedded firmware</Li
|
||||
>
|
||||
<Li
|
||||
>Accompanied the team on two deployments to the LeConte glacier in
|
||||
Alaska to gather ice-water melt and mixing data</Li
|
||||
>
|
||||
</Ul>
|
||||
</PageGroup>
|
||||
<SkillMatrix categorizedSkills={categorizedSkills} />
|
||||
</PageGroup>
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H2>Details</H2></Fragment>
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H3>ROSS Overview</H3></Fragment>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
ROSS was a gasoline-powered water-sampling robotics platform built
|
||||
around a Mokai jet-drive kayak. It's purpose was to continuously, and
|
||||
often autonomously, gather water data over extremely long distances
|
||||
and/or in locations where human-safety concerns would make gathering
|
||||
it manually too risky. There were a variety of sensors it could be
|
||||
outfitted with depending on the needs of the exact research project
|
||||
and destination, but some common ones were an <PopoverWordDefinition
|
||||
key="ADCP"
|
||||
/> for gathering 3D water current vector data, a <PopoverWordDefinition
|
||||
key="CTD"
|
||||
/> for measuring water conductivity/temperature/depth, and a high-precision
|
||||
GPS for generating meaningful 3D plots of the sensor data. These kayaks
|
||||
have been deployed to places like the Indian/Pacific Ocean mixing line,
|
||||
and along the active LeConte glacier terminus in Alaska, gathering novel
|
||||
data on how vastly different bodies of water act when mixing.
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
In its original configuration, the Mokai kayak's throttle and steering
|
||||
were already drive-by-wire, which made it an excellent starting point
|
||||
for automating. It was also designed for easy transport, breaking down
|
||||
into three major compartments that could easily fit in the back of a
|
||||
short-bed pickup. For our custom hulls, Mokai also thickened the
|
||||
plastic significantly and provided a bare minimum of electronics. This
|
||||
barebones platform was then modified by our team to include a
|
||||
storm-surge-rated intake and exhaust for the engine, a keel to improve
|
||||
rough sea stability, a large alternator, and a plethora of mount
|
||||
points the electronics, batteries, fuel, sensors, and radios.
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
In terms of the electronics and software for this project, the kayak
|
||||
itself was centered around a Pixhawk flight controller flashed with a
|
||||
modified Rover variant (this was before a dedicated boat option
|
||||
existed). One pelican-case electronics box housed this controller, a
|
||||
small <PopoverWordDefinition key="NUC" /> with <PopoverWordDefinition
|
||||
key="UPS"
|
||||
/>, wifi router, radio control receiver, satellite modem, and quite a
|
||||
few custom <PopoverWordDefinition key="PCBs" /> for interfacing with external
|
||||
electronics and implementing glue logic/safety overrides. A second box housed
|
||||
nothing but sealed lead-acid batteries, which were charged by the alternator
|
||||
on later revisions of the platform. The PC ran a custom python script, which
|
||||
interfaced with a Matlab GUI over a remote radio link. The kayak could also
|
||||
be overridden with an FrSky RC controller, when at close range, and additionally
|
||||
allowed for direct control without the PC needing to be in-the-loop. To
|
||||
see some of the custom hardware inside of these boxes, check out Nick McComb's
|
||||
design pages for them
|
||||
<InlineLink
|
||||
href="https://nickmccomb.net/college/printed-circuit-boards#omg"
|
||||
>here</InlineLink
|
||||
>! For even more context on ROSS, and history from before I joined the
|
||||
project, check out his <InlineLink
|
||||
href="https://nickmccomb.net/college/ross">summary page</InlineLink
|
||||
>.
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
</PageGroup>
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H3>My Experience</H3></Fragment>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
I first started on this project by doing what I thought was a one-off
|
||||
help session for Nick, working on an issue he was having getting
|
||||
ROSS's engine to start and shut down properly. I had more experience
|
||||
with engines, and engine control, so I quickly realized that a beefier
|
||||
and high-voltage-rated relay was needed to avoid arc-welding the
|
||||
contacts closed during shutdown. He rolled out a <InlineLink
|
||||
href="https://nickmccomb.net/college/printed-circuit-boards/ross-ebox-auxillary"
|
||||
>new board revision</InlineLink
|
||||
> with those changes and it was the final version used for the rest of ROSS's
|
||||
lifetime. This little taste of the project, and some wishful prodding from
|
||||
Nick, was enough for me to join the team part-time.
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
While the original plan for me was to re-write the <PopoverWordDefinition
|
||||
key="GUI"
|
||||
/> for ROSS in Python using Qt, it turns out they needed my help on the
|
||||
electrical and firmware side more than anything, so most of my time at the
|
||||
lab was focused on that. I hand-assembled so many of Nick's circuit boards
|
||||
at this lab that I still can pick his out of a lot from design aesthetic
|
||||
alone! I also helped with plenty of wiring harness builds, electrical box
|
||||
fabrication, embedded firmware development, and of course, plenty of electrical
|
||||
and software debugging. One thing that this project taught me very quickly
|
||||
was how difficult it was to make reliable hardware in a high vibration,
|
||||
electrically noisy, and salt-laden environments. The number of PCBs we went
|
||||
through, alongside wiring harnesses, was pretty incredible considering the
|
||||
lengths we went to in order to protect them.
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
A very unique aspect of this team/project, and a large part of why I
|
||||
was drawn to it, was that it was about as hands-on as you could
|
||||
possibly get. Doubly so for an undergraduate student! Not only did I
|
||||
get to design and repair a real robot, but it was actually being used
|
||||
for proper scientific research! We would regularly go to Newport, OR
|
||||
for testing and have to make crazy additions and repairs on the fly.
|
||||
This got even more extreme during my deployments to the <InlineLink
|
||||
href="http://localhost:4321/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler"
|
||||
>LeConte glacier</InlineLink
|
||||
>, as you had to get creative and fix things with what you had on-hand
|
||||
due to how remote we were. These are experiences that graduate
|
||||
students rarely even get to have, so I'm extremely thankful and fond
|
||||
of the time I spent here. Huge shout out to <InlineLink
|
||||
href="https://nickmccomb.net">Nick</InlineLink
|
||||
>, again, who made it possible in the first place! Also be sure to
|
||||
check out the scientific paper on this project below!
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
</PageGroup>
|
||||
</PageGroup>
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H2>Official Scientific Publication</H2></Fragment>
|
||||
<div class="h-334">
|
||||
<PdfViewer pdf={publication} />
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-sm font-extrabold">Electrical</div>
|
||||
<hr class="text-caperren-green" />
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-sm font-extrabold">Mechanical</div>
|
||||
<hr class="text-caperren-green" />
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-sm font-extrabold">Other</div>
|
||||
<hr class="text-caperren-green" />
|
||||
</div>
|
||||
</div>
|
||||
<H2>Details</H2>
|
||||
power and voltage logging
|
||||
<H2>Official Scientific Publication</H2>
|
||||
<div class="h-334">
|
||||
<PdfViewer pdf={publication} />
|
||||
</div>
|
||||
</PageGroup>
|
||||
</ExperienceLayout>
|
||||
|
||||
@@ -5,6 +5,7 @@ import H2 from "@components/H2.astro";
|
||||
import H3 from "@components/H3.astro";
|
||||
import InlineLink from "@components/InlineLink.astro";
|
||||
import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro";
|
||||
import PageGroup from "@components/PageGroup.astro";
|
||||
import Paragraph from "@components/Paragraph.astro";
|
||||
import Paragraphs from "@components/Paragraphs.astro";
|
||||
|
||||
@@ -27,42 +28,49 @@ const rfidImplantCarouselGroup: carouselGroup = {
|
||||
---
|
||||
|
||||
<HobbyLayout title="Body Mods">
|
||||
<H2>RFID Implant</H2>
|
||||
<Carousel carouselGroup={rfidImplantCarouselGroup} />
|
||||
<H3>Details</H3>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
Back when I was in college, a few of my friends and I got this crazy idea
|
||||
to all get RFID implants together. They are essentially the same things
|
||||
you'd use to microchip a pet, but with a slightly different firmware
|
||||
configuration, allowing scans with any 125KHz-compatible reader. The
|
||||
implants came from <InlineLink
|
||||
href="https://dangerousthings.com/product/xem/"
|
||||
>dangerousthings.com</InlineLink
|
||||
>, and we were lucky enough to have a vet-med student as a friend who made
|
||||
the installation a quick and painless process! I'm glad that I'm not
|
||||
afraid of needles, as the 16 gauge injector the kit came with was nothing
|
||||
to scoff at. Since healing, you would never know the implant was there,
|
||||
with the site leaving no scar or visible indication of its presence.
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
With that out of the way, our group began work on hardware which would
|
||||
support the new implants. The goal was to have a generic usb-keyboard
|
||||
emulator for typing passwords with a valid scan, a car off-acc-on ignition
|
||||
replacement, and a fairly specialized modification to the OSU Robotics
|
||||
Club's doorway scanning system so they would support these on top of the
|
||||
official OSU ID cards. As tends to happen, life got busy, and only the
|
||||
usb-keyboard emulator actually came to fruition. The electronics and
|
||||
primary firmware were handled by <InlineLink href="https://nickmccomb.net"
|
||||
>Nick McComb</InlineLink
|
||||
>, enclosure by <InlineLink href="https://dylanthrush.com"
|
||||
>Dylan Thrush</InlineLink
|
||||
>, and I supported some minor firmware development and debugging. If you
|
||||
want to see an example of the keyboard emulator unlocking a PC, check out
|
||||
the video on <InlineLink
|
||||
href="https://nickmccomb.net/college/printed-circuit-boards/computer-access-module"
|
||||
>Nick's website</InlineLink
|
||||
>!
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H2>RFID Implant</H2></Fragment>
|
||||
|
||||
<Carousel carouselGroup={rfidImplantCarouselGroup} />
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H3>Details</H3></Fragment>
|
||||
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
Back when I was in college, a few of my friends and I got this crazy
|
||||
idea to all get RFID implants together. They are essentially the same
|
||||
things you'd use to microchip a pet, but with a slightly different
|
||||
firmware configuration, allowing scans with any 125KHz-compatible
|
||||
reader. The implants came from <InlineLink
|
||||
href="https://dangerousthings.com/product/xem/"
|
||||
>dangerousthings.com</InlineLink
|
||||
>, and we were lucky enough to have a vet-med student as a friend who
|
||||
made the installation a quick and painless process! I'm glad that I'm
|
||||
not afraid of needles, as the 16 gauge injector the kit came with was
|
||||
nothing to scoff at. Since healing, you would never know the implant
|
||||
was there, with the site leaving no scar or visible indication of its
|
||||
presence.
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
With that out of the way, our group began work on hardware which would
|
||||
support the new implants. The goal was to have a generic usb-keyboard
|
||||
emulator for typing passwords with a valid scan, a car off-acc-on
|
||||
ignition replacement, and a fairly specialized modification to the OSU
|
||||
Robotics Club's doorway scanning system so they would support these on
|
||||
top of the official OSU ID cards. As tends to happen, life got busy,
|
||||
and only the usb-keyboard emulator actually came to fruition. The
|
||||
electronics and primary firmware were handled by <InlineLink
|
||||
href="https://nickmccomb.net">Nick McComb</InlineLink
|
||||
>, enclosure by <InlineLink href="https://dylanthrush.com"
|
||||
>Dylan Thrush</InlineLink
|
||||
>, and I supported some minor firmware development and debugging. If
|
||||
you want to see an example of the keyboard emulator unlocking a PC,
|
||||
check out the video on <InlineLink
|
||||
href="https://nickmccomb.net/college/printed-circuit-boards/computer-access-module"
|
||||
>Nick's website</InlineLink
|
||||
>!
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
</PageGroup>
|
||||
</PageGroup>
|
||||
</HobbyLayout>
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
---
|
||||
import HobbyLayout from "@layouts/HobbyLayout.astro";
|
||||
|
||||
import H2 from "@components/H2.astro";
|
||||
import LinkButton from "@components/LinkButton.astro";
|
||||
import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro";
|
||||
import HobbyLayout from "@layouts/HobbyLayout.astro";
|
||||
import PageGroup from "@components/PageGroup.astro";
|
||||
import Paragraph from "@components/Paragraph.astro";
|
||||
import Paragraphs from "@components/Paragraphs.astro";
|
||||
|
||||
import type { carouselGroup } from "@interfaces/image-carousel.ts";
|
||||
|
||||
@@ -31,44 +36,53 @@ const headerCarouselGroup: carouselGroup = {
|
||||
};
|
||||
---
|
||||
|
||||
<HobbyLayout title="Motorcycling - Chubby Buttons 2 Mount">
|
||||
<HobbyLayout
|
||||
title="Chubby Buttons 2 Mount"
|
||||
subTitles={["Hobbies", "Motorcycling"]}
|
||||
>
|
||||
<Carousel carouselGroup={headerCarouselGroup} />
|
||||
<div class="mt-4 flex items-center justify-center">
|
||||
<div class="flex items-center justify-center">
|
||||
<LinkButton
|
||||
href="https://cad.onshape.com/documents/816b0b1bef7883d4dc25c66c/v/e11fe68753e080b72015cfb8/e/3802abbd9d7b7c4d2c7ebad3"
|
||||
title="Onshape CAD Design Files"
|
||||
/>
|
||||
</div>
|
||||
<p class="mt-4">
|
||||
Having ridden motorcycles since I was sixteen, and being an avid music
|
||||
enjoyer, I'd been looking for a way to improve my music listening experience
|
||||
while on-the-go. One large pain-point I'd always had was with controlling
|
||||
track selection and volume levels while my gloves were on, as smartphones
|
||||
don't respond very well to this, if at all. In 2023 I found out about chubby
|
||||
buttons, a low-power and highly water-resistant media controller
|
||||
specifically designed for use with gloves! The only problem was that it was
|
||||
designed to be worn on your arm using a strap, which isn't very practical on
|
||||
a motorcycle.
|
||||
</p>
|
||||
<p class="mt-4">
|
||||
When starting this project, I'd recently gotten a 3D Printer, so having some
|
||||
baseline modelling skills I took some measurements, and began designing a
|
||||
proper mount. I already owned and used many 1" RAM compatible mounts and
|
||||
gear on my bikes, so I decided to make this one natively support the ball
|
||||
size to use an existing clamp I had stored away. This design was the first
|
||||
where I decided to use heat-set inserts in the plastic, along with some
|
||||
medium-strength Loctite on the fasteners, due to the high-vibration
|
||||
environment the mount would see. The print was also done using a UV
|
||||
resistant, high-temp rated, and non-water-absorbing ASA filament, as the
|
||||
direct expose to the elements would not allow something like cheap PLA to
|
||||
last very long.
|
||||
</p>
|
||||
<p class="mt-4">
|
||||
While my first iteration was sized appropriately and went together with no
|
||||
issues, the ball mount neck ended up snapping due to a low infill
|
||||
percentage. After changing that area to 100% infill, including a handful of
|
||||
the rear mount layers that it attached to, a second iteration has worked
|
||||
perfectly for a few years now! If you're interested in printing this
|
||||
yourself, feel free to download the model using the button under the photos!
|
||||
</p>
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H2>Details</H2></Fragment>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
Having ridden motorcycles since I was sixteen, and being an avid music
|
||||
enjoyer, I'd been looking for a way to improve my music listening
|
||||
experience while riding. One large pain-point I'd always had was
|
||||
controlling track selection and volume levels while my gloves were on,
|
||||
as smartphones don't respond very well to this, if at all. In 2023 I
|
||||
found out about chubby buttons, a low-power and highly water-resistant
|
||||
media controller specifically designed for use with gloves! The only
|
||||
problem was that it was designed to be worn on your arm using a strap,
|
||||
which isn't very practical on a motorcycle.
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
When starting this project, I'd recently gotten a 3D printer, so having
|
||||
some baseline modelling skills I took some measurements, and began
|
||||
designing a proper mount. I already owned and used many 1" RAM
|
||||
compatible mounts and gear on my bikes, so I decided to make this one
|
||||
natively support the ball size to use an existing clamp I had stored
|
||||
away. This design was the first where I decided to use heat-set inserts
|
||||
in the plastic, along with some medium-strength Loctite on the
|
||||
fasteners, due to the high-vibration environment the mount would see.
|
||||
The print was also done using a UV resistant, high-temp rated, and
|
||||
non-water-absorbing ASA filament, as the direct exposure to the elements
|
||||
would not allow something like cheap PLA to last very long.
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
While my first iteration was sized appropriately and went together with
|
||||
no issues, the ball mount neck ended up snapping due to a low infill
|
||||
percentage. After changing that area to 100% infill, including a handful
|
||||
of the layers at the rear mounting face where the neck attaches, a
|
||||
second iteration has worked perfectly for a few years now! If you're
|
||||
interested in printing this yourself, feel free to download the model
|
||||
using the button under the photos!
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
</PageGroup>
|
||||
</HobbyLayout>
|
||||
|
||||
@@ -4,6 +4,7 @@ import HobbyLayout from "@layouts/HobbyLayout.astro";
|
||||
import H2 from "@components/H2.astro";
|
||||
import H3 from "@components/H3.astro";
|
||||
import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro";
|
||||
import PageGroup from "@components/PageGroup.astro";
|
||||
|
||||
import type { carouselGroup } from "@interfaces/image-carousel.ts";
|
||||
|
||||
@@ -39,26 +40,35 @@ const kz750CarouselGroup: carouselGroup = {
|
||||
};
|
||||
---
|
||||
|
||||
<HobbyLayout title="Motorcycling - Lineup">
|
||||
<H2>Current Lineup</H2>
|
||||
<H3>2015 Yamaha FJR 1300</H3>
|
||||
<Carousel carouselGroup={fjrCarouselGroup} />
|
||||
|
||||
<H3>2021 CSC SG400</H3>
|
||||
<Carousel carouselGroup={cscCarouselGroup} />
|
||||
|
||||
<H2>Prior Lineup</H2>
|
||||
<H3>2005 Suzuki DRZ 400</H3>
|
||||
<Carousel carouselGroup={drzCarouselGroup} />
|
||||
|
||||
<h3 class="my-4 font-bold underline md:text-lg">
|
||||
1991 Kawasaki Concours ZG1000
|
||||
</h3>
|
||||
<Carousel carouselGroup={concoursCarouselGroup} />
|
||||
|
||||
<H3>1979 Kawasaki KZ750</H3>
|
||||
<Carousel carouselGroup={kz750CarouselGroup} />
|
||||
|
||||
<H3>1991 Kawasaki Ninja 600R</H3>
|
||||
<Carousel carouselGroup={ninjaCarouselGroup} />
|
||||
<HobbyLayout title="Lineup" subTitles={["Hobbies", "Motorcycling"]}>
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H2>Current Lineup</H2></Fragment>
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H3>2015 Yamaha FJR 1300</H3></Fragment>
|
||||
<Carousel carouselGroup={fjrCarouselGroup} />
|
||||
</PageGroup>
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H3>2021 CSC SG400</H3></Fragment>
|
||||
<Carousel carouselGroup={cscCarouselGroup} />
|
||||
</PageGroup>
|
||||
</PageGroup>
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H2>Prior Lineup</H2></Fragment>
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H3>2005 Suzuki DRZ 400</H3></Fragment>
|
||||
<Carousel carouselGroup={drzCarouselGroup} />
|
||||
</PageGroup>
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H3>1991 Kawasaki Concours ZG1000</H3></Fragment>
|
||||
<Carousel carouselGroup={concoursCarouselGroup} />
|
||||
</PageGroup>
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H3>1979 Kawasaki KZ750</H3></Fragment>
|
||||
<Carousel carouselGroup={kz750CarouselGroup} />
|
||||
</PageGroup>
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H3>1991 Kawasaki Ninja 600R</H3></Fragment>
|
||||
<Carousel carouselGroup={ninjaCarouselGroup} />
|
||||
</PageGroup>
|
||||
</PageGroup>
|
||||
</HobbyLayout>
|
||||
|
||||
@@ -4,6 +4,7 @@ import BaseLayout from "@layouts/BaseLayout.astro";
|
||||
import H2 from "@components/H2.astro";
|
||||
import InlineLink from "@components/InlineLink.astro";
|
||||
import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro";
|
||||
import PageGroup from "@components/PageGroup.astro";
|
||||
import Paragraph from "@components/Paragraph.astro";
|
||||
import Paragraphs from "@components/Paragraphs.astro";
|
||||
|
||||
@@ -21,76 +22,81 @@ const headerCarouselGroup: carouselGroup = {
|
||||
|
||||
<BaseLayout title="About" showTitle={false}>
|
||||
<Carousel carouselGroup={headerCarouselGroup} />
|
||||
<H2>Who Am I</H2>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
My name is Corwin Perren, and I'm a multi-disciplinary engineer with a <InlineLink
|
||||
href="/education">degree in computer science</InlineLink
|
||||
> from Oregon State University. For as long as I can remember, I've been fascinated
|
||||
by how things work, never being shy about taking them apart to learn the gritty
|
||||
details. At a young age, I began tinkering, adding lights and fans and doorbells
|
||||
to the pretend cardboard box houses my brother and I would play in. Later, I
|
||||
learned to solder, work on vehicles and engines, install and run Linux, manage
|
||||
enterprise computing infrastructure, build and repair computers, write scripts,
|
||||
and by the end of high school set out with a clear goal for my college years.
|
||||
I wanted to learn and teach myself enough to be able to think up almost any
|
||||
project, encompassing all facets of engineering, and be capable of driving it
|
||||
to completion with my own skill set.
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
I think young me would be very pleased by how well I managed to achieve
|
||||
that goal! Through college, I learned electronics and PCB design, embedded
|
||||
and pc programming, basic mechanical design and fabrication, on top of
|
||||
learning how to work well with others in a team. I quickly realized that
|
||||
robotics was an ideal focus due to its inherent multi-disciplinary nature,
|
||||
and joined the OSU Robotics Club, which introduced me to people who are
|
||||
still my best friends today. Through student engineering jobs, I had the
|
||||
unique opportunity to work on some incredible projects such as the
|
||||
<InlineLink
|
||||
href="/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler"
|
||||
>robotic oceanographic surface sampler</InlineLink
|
||||
>
|
||||
and an <InlineLink
|
||||
href="/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate"
|
||||
>embryo pick-and-plate machine</InlineLink
|
||||
>. One my my proudest moments was when our club's mars rover took first
|
||||
place at the Candian International Rover Challenge in 2018, for which I
|
||||
was the <InlineLink
|
||||
href="/experience/osu-robotics-club/mars-rover-software-team-lead"
|
||||
>software lead</InlineLink
|
||||
>!
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
After a short three-month <InlineLink
|
||||
href="/experience/spacex/avionics-test-engineering-internship"
|
||||
>internship</InlineLink
|
||||
> at SpaceX in Hawthorne at the end of college, I applied for a <InlineLink
|
||||
href="/experience/spacex/hardware-test-engineer-i-ii"
|
||||
>test engineering</InlineLink
|
||||
> position with the company's Starlink team and was hired in mid-2019. For six
|
||||
years, I developed test system hardware, software, harnesses, mechanical fixtures,
|
||||
devops infrastructure, websites, and tooling to ensure that Starlink, Falcon,
|
||||
Dragon, and Starship component tests were producing well-validated and reliable
|
||||
hardware. Through it all, I got to apply and hone every skill I had developed,
|
||||
while learning countless more. Now though, it's on to the next adventure, whatever
|
||||
that may be!
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
To learn more about my experiences, hobbies, interests, and skills, feel
|
||||
free to explore the site! While the short summary above provides some
|
||||
insight into who I am, it leaves out plenty! For example, I've been an
|
||||
avid <InlineLink href="/hobby/motorcycling/lineup"
|
||||
>motorcycle rider</InlineLink
|
||||
> since I was sixteen, and have an <InlineLink href="/hobby/body-mods"
|
||||
>rfid implant</InlineLink
|
||||
> in my hand!
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
If you're interested in contacting me, feel free to message on <InlineLink
|
||||
href="https://github.com/caperren">LinkedIn</InlineLink
|
||||
>, or via the primary contact methods on my <InlineLink
|
||||
href="/resume/2025-11-10-infrastructure-engineer">resume</InlineLink
|
||||
>.
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
<PageGroup>
|
||||
<Fragment slot="header"><H2>Who Am I</H2></Fragment>
|
||||
<Paragraphs>
|
||||
<Paragraph>
|
||||
My name is Corwin Perren, and I'm a multi-disciplinary engineer with a <InlineLink
|
||||
href="/education">degree in computer science</InlineLink
|
||||
> from Oregon State University. For as long as I can remember, I've been fascinated
|
||||
by how things work, never being shy about taking them apart to learn the gritty
|
||||
details. At a young age, I began tinkering, adding lights and fans and doorbells
|
||||
to the pretend cardboard box houses my brother and I would play in. Later,
|
||||
I learned to solder, work on vehicles and engines, install and run Linux,
|
||||
manage enterprise computing infrastructure, build and repair computers, write
|
||||
scripts, and by the end of high school set out with a clear goal for my college
|
||||
years. I wanted to learn and teach myself enough to be able to think up almost
|
||||
any project, encompassing all facets of engineering, and be capable of driving
|
||||
it to completion with my own skill set.
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
I think young me would be very pleased by how well I managed to achieve
|
||||
that goal! Through college, I learned electronics and PCB design,
|
||||
embedded and pc programming, basic mechanical design and fabrication, on
|
||||
top of learning how to work well with others in a team. I quickly
|
||||
realized that robotics was an ideal focus due to its inherent
|
||||
multi-disciplinary nature, and joined the OSU Robotics Club, which
|
||||
introduced me to people who are still my best friends today. Through
|
||||
student engineering jobs, I had the unique opportunity to work on some
|
||||
incredible projects such as the
|
||||
<InlineLink
|
||||
href="/experience/osu-ceoas-ocean-mixing-group/robotic-oceanographic-surface-sampler"
|
||||
>robotic oceanographic surface sampler</InlineLink
|
||||
>
|
||||
and an <InlineLink
|
||||
href="/experience/osu-sinnhuber-aquatic-research-laboratory/zebrafish-embryo-pick-and-plate"
|
||||
>embryo pick-and-plate machine</InlineLink
|
||||
>. One my my proudest moments was when our club's mars rover took first
|
||||
place at the Candian International Rover Challenge in 2018, for which I
|
||||
was the <InlineLink
|
||||
href="/experience/osu-robotics-club/mars-rover-software-team-lead"
|
||||
>software lead</InlineLink
|
||||
>!
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
After a short three-month <InlineLink
|
||||
href="/experience/spacex/avionics-test-engineering-internship"
|
||||
>internship</InlineLink
|
||||
> at SpaceX in Hawthorne at the end of college, I applied for a <InlineLink
|
||||
href="/experience/spacex/hardware-test-engineer-i-ii"
|
||||
>test engineering</InlineLink
|
||||
> position with the company's Starlink team and was hired in mid-2019. For
|
||||
six years, I developed test system hardware, software, harnesses, mechanical
|
||||
fixtures, devops infrastructure, websites, and tooling to ensure that Starlink,
|
||||
Falcon, Dragon, and Starship component tests were producing well-validated
|
||||
and reliable hardware. Through it all, I got to apply and hone every skill
|
||||
I had developed, while learning countless more. Now though, it's on to the
|
||||
next adventure, whatever that may be!
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
To learn more about my experiences, hobbies, interests, and skills, feel
|
||||
free to explore the site! While the short summary above provides some
|
||||
insight into who I am, it leaves out plenty! For example, I've been an
|
||||
avid <InlineLink href="/hobby/motorcycling/lineup"
|
||||
>motorcycle rider</InlineLink
|
||||
> since I was sixteen, and have an <InlineLink href="/hobby/body-mods"
|
||||
>rfid implant</InlineLink
|
||||
> in my hand!
|
||||
</Paragraph>
|
||||
<Paragraph class="mt-8 flex flex-col items-center" initialTab={false}>
|
||||
<div>
|
||||
If you're interested in contacting me, feel free to message on <InlineLink
|
||||
href="https://github.com/caperren">LinkedIn</InlineLink
|
||||
>, or via the primary contact methods on my <InlineLink
|
||||
href="/resume/2025-11-10-infrastructure-engineer">resume</InlineLink
|
||||
>.
|
||||
</div>
|
||||
</Paragraph>
|
||||
</Paragraphs>
|
||||
</PageGroup>
|
||||
</BaseLayout>
|
||||
|
||||
Reference in New Issue
Block a user