Incoming UBC Science · Engineering transfer track

Reuben Lavin

I build with embedded electronics, code, and a soldering iron.

About

I'm a Grade 12 student at West Point Grey Academy in Vancouver, heading to the University of British Columbia this fall for Science, with a planned transfer into Engineering after first year. I'm drawn to robotics: the place where physics, mathematics, and software meet a moving piece of hardware.

Outside of academics I'm an MMA black belt and assistant instructor, a varsity tennis player, and a jazz band leader. I treat engineering the same way I treat training: precise, patient, and built up rep by rep.

Next up: taking the assistive helmet into Phase 2 (camera + computer vision) and launching Bullseye to real users.

Education

  1. Sept 2026 · incoming

    University of British Columbia

    Bachelor of Science · Engineering transfer planned after first year

    • Foundational coursework in calculus, physics, chemistry, and computer science
    • Continuing self-directed work in embedded systems and robotics
  2. 2020–2026 (graduating)

    West Point Grey Academy

    Grade 12 · Honor Roll · Graduating June 2026

    • AP Computer Science · AP Statistics · AP Calculus BC · AP English Language · AP Human Geography
    • AP Scholars Award · Merit Award · Alfred Lu Spirit Award · Citizenship Award
    • Music Program Hall of Fame · Varsity Tennis
    • Core Connectors Mental Health Literacy Certificate · Adam's Apples Foundation
  3. 2018–2023

    Kumon Math

    Graduated full program · Outstanding Academics recognition

Certifications

  • Google AI Professional certificate badge

    Google AI Professional Certificate

    Google Career Certificates · March 2026 · 7 courses + umbrella credential

Projects

In progress
Live point cloud streamed from the helmet over WiFi
BNO085 IMU wired on a breadboard during bring-up
BNO085 bring-up
First helmet rig: breadboard and sensors mounted on a batting helmet
First wearable rig
Robotics · Sensor Fusion · Case Study

Assistive Navigation Helmet

A friend built a cane that vibrates when something is ahead. This is the same idea with a far richer signal: a wearable for blind and low-vision users that turns two 8×8 depth grids and head orientation into directional vibration, so an obstacle on your left buzzes your left temple before you reach it.

An ESP32-S3 runs two ST VL53L8CX time-of-flight sensors on independent I²C buses (both ship fixed at address 0x29; separate buses sidestep the collision). The bottom sensor angles ~30° down for ground-level obstacles, with a per-row cosine table converting slant range to true forward distance; the top sensor watches for head-height overhangs. A BNO085 IMU tracks head orientation at 100 Hz, and three coin motors (forehead, left temple, right temple) render direction. Firmware ships over the air with bootloader rollback, and live data streams to a desktop 3-D point cloud and a phone heatmap viewer.

Three stacked bugs, one IMU driver

0x4B ACKed. The real address was 0x4A: an ACK can lie.

Every available BNO085 library for this setup was SPI-only, so the I²C SH-2/SHTP transport had to be built from scratch. Much of the code here is written with Claude Code; the architecture, wiring, bench debugging, and verification on real hardware are mine. Getting this chip alive meant peeling back three independent bugs, each hiding the next. The probe ACKed at 0x4B but the real address was 0x4A: an ACK can lie, and ground truth is which address returns valid protocol data. Then the handshake worked exactly once per physical power-up and never again, because the chip broadcasts its channel advertisement once, at power-on, and reflashing resets the ESP but not the IMU; the fix is forcing a hub reset on every boot. Finally, the ToF sensor's 84 KB firmware upload blocked the bus for a full second, and an unserviced BNO085 starves and stops reporting. It now gets its own 500 Hz service task and a shared-bus mutex.

Measure, don't guess: dropping the magnetometer

Motors on: heading confidence 4.8° → 39°. The magnetometer had to go.

The motors sit ~5 cm from the IMU, intuitively too far to disturb a magnetometer. An A/B test said otherwise: with motors running, the chip's own heading-confidence estimate collapsed from 4.8° to 39° and threw a 60° heading jump, exactly when a real obstacle alert would fire. The physics agrees: Earth's horizontal field here is ~18 µT, and a spinning rotor magnet at 5 cm adds a few µT of time-varying field the fusion can't model. The helmet now runs the mag-free AR/VR-stabilized rotation vector, the mode the datasheet itself recommends for head tracking in disturbed fields, and calibration tuning cut dynamic yaw drift from +2.24° to +0.82° per run (~63%).

Haptics a person can actually read

Coin motors don't spin below half duty: the curve starts at a felt 51% floor.

Obstacle direction maps to motors through hard regions with a squared urgency curve and dominance weighting (the most urgent direction stays at full strength, others scale to 70%), choices taken from the vibrotactile literature rather than vibes. The first build exposed a gap the papers don't mention: coin ERM motors don't spin below roughly half duty, so a pure squared curve meant silence until 20 cm and then sudden full power. The curve now maps onto the motor's usable band, starting at a just-perceptible 51% floor the instant an alert begins.

Try the real mapping

Drag the obstacle across the sensor's view, then bring it closer with the slider. Arrow keys work too.

This is the shipped firmware computation: column regions, squared urgency curve, 51% ERM floor, 0.7 dominance weighting. Alert threshold 150 cm.

  • Also run to ground: a 2 ms task delay that compiled to zero ticks at a 100 Hz tick rate, silently starving the sensor loop on unlucky boots
  • A debug switch that bridged 3.3 V to ground mid-flip and browned out the board: logic-level switches should never carry a power rail
  • Every fix, dead end, and root cause is written up in the repo's engineering devlog

Where it stands: both depth streams and the IMU run concurrently (~30 Hz ranging, 100 Hz orientation) with directional haptics live on the bench. Phase 1 shipped; Phase 2 adds a camera; Phase 3 fuses all three.

C · ESP-IDF 5.4ESP32-S3VL53L8CX ToF ×2BNO085 IMUSH-2/SHTPFreeRTOSHaptics
In progress
A walkthrough of the build, hardware, and app
Embedded · Wearable · Case Study

Sunrise Wake-Up Mask

Loud alarms wake you with a jolt. This is a sleep mask that wakes you the way morning light does: a strip of LEDs behind the fabric fades up like a real sunrise over your chosen window, with haptic motors easing in at the end. You set the wake time, color, and length from a small desktop app over USB.

An ESP32-C6 drives a cut strip of WS2812 addressable LEDs behind a foam diffuser, with coin haptic motors switched by a 2N3904 transistor. A 1000 mAh LiPo powers it and charges over USB. The firmware takes its settings over USB serial — no reflashing to change an alarm — and a companion desktop app (a Web Serial page wrapped in Electron) sends the wake time, color, and sunrise curve. The firmware and app were written with Claude Code; the hardware, wiring, and the debugging below are mine.

The bug that reset the whole board

Motors on the logic rail browned out the MCU mid-buzz.

The haptic motors ran off the same 3.3 V rail as the ESP32-C6. At full power they pulled enough current to sag that rail past the brown-out threshold, and the chip reset mid-sequence — which froze the LED strip on its last frame, because WS2812s hold their last color the instant the data signal stops. The tell was a single serial line: Brownout detector was triggered. At low duty the motors didn't draw enough to spin at all; at high duty they crashed the board. With the case already sealed, the fix was firmware: clamp the motor duty to a ceiling that stays under the brown-out point, so the lights and motors run together without taking the brain down.

Coin motors that won't start, but will keep going

A full-power kick breaks stiction, then it settles to a low hum.

Ramping the motor's PWM up from zero never worked: a coin motor needs a sharp push to overcome static friction, and a slow ramp just creeps through values too weak to ever start it, so the motor stayed silent through the whole sunrise. The fix is a kickstart — a brief full-power pulse on the rising edge that breaks the motor free, then drops to the low level it can sustain once it's already spinning. That one trick is what lets the buzz arrive gently instead of snapping from silence to full.

A clock it can't forget

It re-learns the time over WiFi, so the alarm survives a power cut.

An ESP32 loses track of time the moment it loses power, which is fatal for an alarm. The mask connects to WiFi and syncs the real time over SNTP, then stores the alarm in non-volatile memory. The app sends the wake time as an absolute timestamp, so the device itself needs no notion of time zones — the laptop already knows your local time and just hands over the exact moment to fire. Unplug it, plug it back in, and within seconds it has resynced and the alarm still goes off when it should.

  • Addressable LEDs run from the battery rail, not the regulated 3.3 V: at low voltage the blue and green channels starve and the color shifts
  • Settings are sent, not flashed: the firmware is a small state machine that takes JSON over USB, so a new alarm is one serial message, not a reflash
  • Every dead end and fix, including a 10-bit HDR export that wouldn't play and a swapped data/ground line that killed the strip, is written up in the repo's devlog

Where it stands: the full sunrise-and-haptic wake sequence runs on the bench, configured live from the desktop app, with WiFi time sync working. Next is the battery enclosure and a dedicated haptic driver.

C · ESP-IDF 5.4ESP32-C6WS2812B LEDsHapticsFreeRTOSWiFi · SNTPWeb SerialElectron
In progress
Bare-hand pinch and turn, captured in-headset on a Quest 3
AR / VR · Cultural Heritage · Case Study

Spindle Whorl AR

Coast Salish spindle whorls are carved wooden discs, but museum archives mostly hold them as flat photographs. This Meta Quest 3 mixed-reality app rebuilds them as 3-D objects floating in your real room: reach out, pinch, pick one up, and turn the carving in your hands.

Six whorls hang in a 150° arc at reach height through passthrough. Pinch thumb and index to grab the nearest disc, move and turn it freely, open your hand to release; ungrabbed discs spin slowly so the art stays visible. Each disc is gently domed with a real centre bore, so you can look through the hole at your own room.

The hand-tracking dead end

Meta's legacy hand API delivers nothing on OpenXR. Unity's XR Hands does, with 25/40 mm pinch hysteresis.

On the OpenXR backend, Meta's legacy OVRHand API silently delivers nothing: IsTracked stays false while the headset is plainly tracking hands. The working path is Unity's XRHandSubsystem, reading thumb-tip and index-tip poses directly. Pinch detection uses hysteresis (grab below 25 mm, release above 40 mm) so a disc doesn't stutter in and out of your grip at the threshold.

Geometry from code, not the modeller

A domed annulus with a real bore, generated in C#, photos aligned to it per disc.

The original Blender export had UVs on its top face only, so photos didn't wrap and the disc backs were blank. The disc is now generated procedurally in C#: a biconvex annulus with a real bore and inscribed UVs on both faces. A Python + OpenCV pipeline strips each source photo's painted-checkerboard background (keeping only background connected to the image border, so the carved interior survives), and a measured per-disc UV offset lands each artifact's painted hole exactly on the geometric bore.

Making it run on real hardware

Headless builds, and an adb launch sequence that beats the Quest's focus race.

On-device, the floor-origin setting was silently ignored, leaving discs a metre overhead; fixed at runtime through XRInputSubsystem. Builds run headless from the command line, and a scripted adb launch sequence beats the Quest's home-panel focus race that leaves sideloaded apps visible but never focused. Written with Claude Code; tested and verified end to end on borrowed school hardware.

  • One rule throughout: no AI-generated stand-in art. Placeholders are unlabeled UV grids, and AI only cleans real photographs; it never invents Coast Salish designs

Where it stands: v0.5, a working hand-tracked six-whorl gallery on a Quest 3, with headless builds and a verified deploy pipeline.

Unity 6Meta Quest 3Passthrough AROpenXRXR HandsC#Python · OpenCV

More builds

Product · Open Source

Bullseye: Marketplace Deal Scorer

Open-source Windows app that scores Facebook Marketplace listings against real eBay sold comps in real time.

View project →
Claude Monitor CRT dashboard
Embedded · Dashboards

Claude Monitor: Live Pi Usage Dashboard

Wall-mounted 7" Raspberry Pi screen showing live Claude Code usage scraped from the CLI dialog.

View project →
Sentinel occupancy dashboard
AI · Computer Vision

Sentinel: AI Occupancy Monitor

Real-time people counting via YOLOv8-Pose tripwire over an IP camera, with a live Streamlit dashboard.

View project →
Sensor Fusion course homepage
Learning · Experiment

Sensor Fusion: A Personalized Learning Experiment

Self-paced CV / calibration / fusion course built around AI as a first-class learning collaborator.

View project →
Robotics

Autonomous RC Car

Self-navigating car using ultrasonic sensors: a full end-to-end hardware and firmware build.

View project →
Aerospace · Hardware

RC Plane Build

Designed and assembled an RC airplane from scratch: airframe, control surfaces, and radio tuning.

View project →
cc-discord-remote on phone
Automation · Windows API

cc-discord-remote: Drive Claude Code from Discord

Phone-controlled Claude Code: a Discord bot that attaches to a live terminal via Win32 console APIs and tails session JSONL for responses.

View project →

Skills

Programming

  • Java · fundamentals (AP CS)
  • Python · intermediate
  • SQL / SQLite

Hardware & Build

  • Microcontrollers (ESP32, Arduino, ESP-IDF)
  • Soldering & breadboarding
  • Sensor wiring (I²C devices)
  • RC platforms · servos · ESCs
  • Foam-board airframe construction

Tools & Libraries

  • Git & GitHub
  • VS Code
  • OpenCV · YOLOv8 · OpenVINO
  • Streamlit · Pandas
  • Windows & basic terminal

Activities & Leadership

Black Belt & Assistant Instructor

Ken Shin Dojo · Kerrisdale Community Centre

Five years of kickboxing; youngest black belt and assistant instructor in Ken Shin Dojo's history (founded 2006). For the past year, lead 20+ students across three weekly kickboxing and jiu-jitsu classes, including students with physical and mental disabilities, work that demands additional patience and compassion.

Grad Committee Treasurer

Class of 2026 · West Point Grey Academy

Managed the budget, vendor payments, and fundraising bookkeeping for the graduating class.

Music Hall of Fame · Jazz Combo Founder

WPGA Music Program · Self-taught multi-instrumentalist

Inducted into the WPGA Music Hall of Fame for 12 years of commitment. Self-taught on drums, bass, piano, saxophone, and guitar. Founded the WPGA Jazz Combo (2023) and grew it from four to seven members across 10+ performances. Co-founder and rhythm-section leader of the WPGA R&B band. Performed for Special Olympics Canada.

Varsity Tennis

WPGA · Vancouver Lawn Tennis Club

Competitive player on WPGA's varsity team and member of Vancouver Lawn Tennis & Badminton Club.

UBC Physics Olympics · Bronze Medal

2026 · WPGA

Bronze medal in the lab event at the 2026 UBC Physics Olympics, a one-day inter-school competition covering physics theory and hands-on apparatus design.

Euclid Mathematics Contest

2026 · University of Waterloo CEMC

Participated in the 2026 Euclid Contest, the Centre for Education in Mathematics and Computing's senior-level Canadian math competition focused on proof-style problem solving.

Head of Technical Maintenance · Windsor Market

2021–2024

Primary on-call technician for a small commercial grocer for three years. Repaired industrial refrigeration, HVAC, electrical circuitry, and structural systems: hands-on STEM applied to facility infrastructure and operational safety. Also ran till, stock, and back-office operations.

Volunteer Work

Community

Kerrisdale Community Centre, Camp Jubilee restoration, WPGA productions, and concert venue merch sales.

Get in touch

Looking for an intern, collaborator, or just want to talk robots? My inbox is open.