Skip to content

d3vmeh/LABKickstart

LABKickstart

An open, modular, IoT-enabled physics lab toolkit. πŸ₯‡ 1st place overall β€” IDEA Hacks 2026

LABKickstart turns a laptop and a few $10 ESP32 boards into a complete physics lab data-acquisition system. Each module reads one sensor and broadcasts over Bluetooth LE; a Python web dashboard receives the streams, runs experiment- specific derivations, plots live data, writes clean CSVs, and (optionally) uses an LLM to convert teachers' existing lab handouts into student-facing setup guides.

No proprietary base station. No proprietary file format. No vendor lock-in.


Why

Incumbents have controlled high school physics for years. A $450 base station before you buy a single sensor; locked connectors; locked file formats. A district that has spent $30k on one vendor has to keep buying that vendor β€” every locked connector is a moat.

A full LABKickstart kit costs less than one typical base station and unlocks 20+ standard physics experiments β€” Hooke's law, Atwood machines, projectile motion, free fall, pendulums, collisions, friction, buoyancy.

Every line of firmware, every Python module, every CAD file is open source. A teacher who has spent twenty years using existing tools can fork an experiment, modify it for their classroom, and share it with the teacher next door β€” in twenty minutes.


Open hardware

All mechanical designs live in OnShape and are publicly viewable:

πŸ”— LABKickstart CAD on OnShape

Includes the photogate housings, IMU mounts, the ToF stand, and the modular mounting rail that lets students reconfigure setups between experiments. Fork the workspace, modify, export STLs, print, run.

Firmware (Arduino sketches per module) lives in firmware/.


Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  BLE notify   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    WebSocket   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ ESP32 module(s) β”‚ ────────────> β”‚ Python Hub       β”‚ ─────────────> β”‚ uPlot charts β”‚
β”‚  (one sensor    β”‚   GATT char   β”‚  Β· BLE manager   β”‚                β”‚ (vanilla JS) β”‚
β”‚   per board)    β”‚               β”‚  Β· Kit derive    β”‚ ─── CSV ────>  β”‚              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜               β”‚  Β· Run + trigger β”‚                β”‚              β”‚
                                  β”‚  Β· LLM (teacher) β”‚                β”‚              β”‚
                                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  • Modules (firmware/) β€” Arduino sketches per sensor (photogate, IMU, ToF).
  • BLE manager (src/labkickstart/ble_manager.py) β€” profile registry, auto-discovery of NOTIFY characteristics, per-connection stateful decoders.
  • Hub (src/labkickstart/app.py) β€” single asyncio event loop. Fans every decoded sample to (1) the active run's CSV writer, (2) all WebSocket subscribers, and (3) the active kit's derive() function, which can emit additional physics-quantity samples back into the same fan-out.
  • Kits (src/labkickstart/kits.py) β€” one Python class per experiment. Each declares info, configure(params), derive(sample), and the BLE modules it requires. Adding an experiment = adding one class.
  • Lab-guide LLM (src/labkickstart/lab_guides.py) β€” gpt-4o-mini with schema-constrained output. Two flows: kit recommender (PDF β†’ ranked kits) and student-facing setup guide.
  • Quicklook (src/labkickstart/quicklook.py) β€” per-channel summary stats (count, mean, median, p5, p95, Οƒ, Οƒ/√N) computed from any run's CSV.
  • Frontend (src/labkickstart/static/) β€” vanilla JS, uPlot, no build step. Per-device chart cards keep different sensor scales from crushing each other on a shared y-axis.

Quickstart

Runs on macOS or a Raspberry Pi 4 (any host with Bluetooth and Python 3.11+).

# 1. Clone + install
git clone https://github.com/d3vmeh/LABKickstart
cd LABKickstart
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt

# 2. (optional) AI features
echo "OPENAI_API_KEY=sk-..." > .env

# 3. Launch the dashboard
./dev.sh
# -> open http://localhost:8000

dev.sh injects src/ onto PYTHONPATH and starts uvicorn with --reload. Override host/port via env:

HOST=127.0.0.1 PORT=8001 ./dev.sh

No hardware? Use a mock source

Set LK_SENSOR before launching to drive the UI from a built-in synthetic sensor:

LK_SENSOR=imu       ./dev.sh   # mock IMU
LK_SENSOR=photogate ./dev.sh   # mock photogate
LK_SENSOR=tof       ./dev.sh   # mock ToF

Hardware modules

Each module is an ESP32 plus one sensor, battery-powered for months between charges. Current modules:

Module Sensor Channels
IMU_Module LSM303 6-axis IMU pitch_deg, roll_deg, accel_x/y/z
BEAMBREAK_Module Dual IR photogate gate_A_break_us, gate_B_break_us
TOF_Module VL53L0X laser ToF distance_mm

Adding a new module = one entry in PROFILES (src/labkickstart/ble_manager.py)

  • one Arduino sketch in firmware/.

Built-in kits

Kit ID Experiment Modules required
sandbox Any sensors, raw passthrough (any)
photogate Two-photogate kinematics BEAMBREAK_Module
imu IMU monitor (tilt, free-fall) IMU_Module
imu_sinusoid Band-pass smoothed oscillations IMU_Module
tof Distance monitor + auto-stop TOF_Module
shm SHM with cross-sensor verification TOF_Module, IMU_Module

Adding a new kit

class MyKit:
    info = KitInfo(
        id="my_kit",
        name="My Experiment",
        description="...",
        params=[KitParam("foo", "Foo", "m", default=1.0)],
        modules=["IMU_Module"],
    )

    def configure(self, params): ...
    def derive(self, sample) -> Iterable[Sample]: ...

Then register it in build_registry(). That's the whole framework.


AI features (opt-in)

Both require OPENAI_API_KEY. Both use gpt-4o-mini with schema-constrained output. Both cache results to disk. Cost is ~$0.001 per call.

  • Lab-guide generator β€” upload a teacher's existing PDF, get a structured materials list + numbered student steps, with a "why" sentence per step that explains the underlying physics or measurement reason.
  • Kit recommender β€” same PDF, GPT picks the best-matching kit from a closed enum of registry IDs (cannot hallucinate a kit). Returns rationale, confidence, and the physical modules required (server-injected from the registry, not LLM-generated).

If the env key is unset, both features return HTTP 503 and the rest of the dashboard runs unaffected.


API

Method Path Purpose
GET / Dashboard
GET /api/devices List connected + scanned devices
POST /api/ble/scan Trigger a BLE scan
POST /api/ble/connect/{address} Connect to a discovered device
POST /api/ble/disconnect/{address} Disconnect
GET /api/kits List kits + active selection
POST /api/kit Apply a kit
POST /api/kits/recommend LLM kit recommender (from PDF)
POST /api/kits/{id}/lab_guide Generate a student lab guide
POST /api/arm Start a run
POST /api/stop Stop the active run
GET /api/runs List runs + active state
GET /api/runs/{id}/csv Download a run's CSV
GET /api/runs/{id}/quicklook Per-channel summary stats
WS /ws/stream Live sample stream

Every WebSocket message is a JSON object: {"device_id", "t", "channel", "value"}, or {"type": "run_state", "active": ...} for run lifecycle events.


Repository layout

LABKickstart/
β”œβ”€β”€ firmware/                  # ESP32 Arduino sketches (one per module)
β”‚   β”œβ”€β”€ device_interfaces/
β”‚   └── photogate_test/
β”œβ”€β”€ src/labkickstart/
β”‚   β”œβ”€β”€ app.py                 # FastAPI app + Hub (asyncio fan-out)
β”‚   β”œβ”€β”€ ble_manager.py         # BLE profile registry + connection manager
β”‚   β”œβ”€β”€ kits.py                # Kit registry (each experiment is a class)
β”‚   β”œβ”€β”€ lab_guides.py          # LLM: lab-guide generator + kit recommender
β”‚   β”œβ”€β”€ quicklook.py           # Per-run summary stats
β”‚   β”œβ”€β”€ runs.py                # Run/CSV lifecycle + auto-stop triggers
β”‚   β”œβ”€β”€ sensors.py             # Sample dataclass + mock sources
β”‚   └── static/                # Dashboard (HTML + vanilla JS + uPlot)
β”œβ”€β”€ docs/
β”œβ”€β”€ data/                      # Run CSVs (gitignored)
β”œβ”€β”€ dev.sh
β”œβ”€β”€ requirements.txt
└── pyproject.toml

Roadmap

  • Force, optical, and magnetic-field modules (open-hardware spec, same kit framework)
  • Kit marketplace β€” teachers publish their own Kit classes
  • Firmware OTA from the dashboard so teachers don't touch the Arduino IDE
  • Classroom pilot, fall 2026

License

  • Software (everything under src/, firmware/): Apache License 2.0
  • Hardware designs (OnShape document linked above + future exports): CERN-OHL-S v2

Apache 2.0 is permissive: you can use, modify, and redistribute the software freely, including commercially, with an explicit patent grant from contributors. CERN-OHL-S is the hardware analog of GPL: forks of the CAD can be manufactured freely, but modified designs that are redistributed must remain open under the same license β€” improvements flow back to the community.

See LICENSE (Apache 2.0) for software, LICENSE-HARDWARE (CERN-OHL-S v2) for hardware designs.


Acknowledgements

Built at IDEA Hacks 2026. Thanks to the organizers, mentors, and every teacher who has worked around proprietary lab equipment for the past forty years.

About

IoT-enabled Physics Experiments

Resources

License

Apache-2.0, CERN-OHL-S-2.0 licenses found

Licenses found

Apache-2.0
LICENSE
CERN-OHL-S-2.0
LICENSE-HARDWARE

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors