Back to projects
PrototypeNext.jsTypeScriptPWASensorBluetoothD3.js

ECG Reader

Portable ECG reader prototype: ESP32 + AD8232 streaming over Web Bluetooth into a PWA for real-time waveform display, demo mode testing, and early recording experiments.

ECG Reader mockup

Introduction

A mobile-first ECG visualization prototype exploring how far a browser-based stack can go when paired with hardware over the Web Bluetooth API.

Background

I came into biomedical engineering with an existing foundation in software development, and this project was my way of testing how far those two skill sets could be combined. The core question was straightforward: can a browser running on everyday devices handle a real biosignal pipeline? Validating that meant exploring whether phones, tablets, and laptops could act as the compute and visualization layer for sensor workflows—without dedicated monitors or platform‑specific native apps. The results shaped the direction of my thesis and later became the basis for the CPR Trainer project.

Problem

A browser‑based ECG workflow needs stable sampling, predictable timing, and smooth visualization — but the Web Bluetooth API doesn’t guarantee reliable, loss‑free streaming. The main challenges were:

  • Unreliable BLE throughput: packet drops, batching, and inconsistent notification timing.
  • Maintaining sampling integrity: preserving the original acquisition rate despite transport jitter.
  • Reconstructing a continuous signal: turning irregular BLE packets into a fluent, clinically readable stream.
  • Real‑time visualization: rendering a continuous waveform in the browser.

Solution

To overcome the transport unreliability, I designed a two‑buffer strategy that reconstructs a clean signal in the browser:

  • MCU‑side buffer: the ESP32 stores timestamped ECG samples locally, ensuring no data is lost at acquisition time.
  • Packet‑level buffer: the PWA receives samples in BLE batches and temporarily queues them.
  • Timestamp‑based reconstruction: the app reorders and interpolates samples based on MCU timestamps, recreating a fluent stream.
  • Stable visualization: React Context manages the rolling display buffer, while D3 renders the waveform at 25/50 mm/s for clinical familiarity. This approach allowed the browser to present a continuous, high‑integrity ECG trace despite the limitations of Web Bluetooth.

How it works (user flow)

  • Pick a mode: choose Connect to sensor (real hardware) or Connect demo sensor (simulated signal).
  • Pair over Bluetooth (real sensor): Web Bluetooth permission → select the custom ESP32 device.
  • Read: after connecting (real or demo), the app shows a continuous ECG trace.
  • Adjust sweep speed: toggle between 25 mm/s and 50 mm/s.
  • Record: capture a segment into memory; pause/resume or delete the recording at any time.
  • Disconnect: return to the home screen and reset device/UI state.

Architecture

  • ESP32 firmware layer: reads sensor values, attaches timestamps, publishes notifications via a BLE characteristic.
  • PWA connection layer: connect → subscribe → parse payloads → update stream buffers.
  • State model: React Context for predictable stream handling and UI stability.
  • Visualization layer: waveform rendering aligned to ECG reading conventions (25/50 mm/s).

Key engineering choices

  • Browser-first runtime: I intentionally tested the browser as the primary compute + UI surface (BLE ingestion, buffering, rendering). The goal was to validate that a web stack can sustain a continuous biosignal pipeline on commodity devices—without platform-specific native apps.
  • Demo-first accessibility: a signal generator makes the project explorable without hardware, useful for portfolio review and UI testing.
  • Clinically familiar timing: preserving sweep speed conventions (25/50 mm/s).

Calibration & display realism

True millimeter-accurate scaling isn’t reliably portable across devices due to varying pixel density and browser rendering. I treat gridlines as a reference and preserve the clinically relevant invariants:

  • timing via 25/50 mm/s sweep speed
  • amplitude reference via gridlines rather than device-calibrated mm scaling

Results

  • Developed pipeline for evaluating biosignals in web application.
  • Produced reusable building blocks that directly informed later sensor-driven work.
  • Delivered dual sweep speeds (25/50 mm/s) with continuous rolling-buffer rendering.