Skip to content

tudorbaranai/guardian-fall-companion

Repository files navigation

Guardian — Fall-Detection Wearable & Caregiver Companion

🏆 1st place out of 16 teams — HARD & SOFT Suceava 2026 · team Sudo (Suceava 2)

A wearable fall-detection and vital-monitoring device for elderly users, plus a real-time caregiver dashboard that streams its telemetry over Supabase. The wearable detects falls fully on-device using two TinyML models trained in Edge Impulse; the dashboard mirrors the wearer's posture on a 3D mannequin and takes over the screen with a guarded false-alarm flow the moment a fall is confirmed.

This repository contains the complete winning entry: the caregiver web app (Tudor's work), the firmware that runs on the ESP32 wearable (Gabriel's work — included as a snapshot of his upstream repo with credit), and the docs needed to replicate the system from scratch.

Team Sudo with first-prize diplomas at HARD & SOFT Suceava 2026


The competition

HARD & SOFT Suceava 2026 is an international embedded-systems competition hosted in Suceava, Romania, and sponsored by Cognizant Mobility Romania (17–24 May 2026). The 2026 topic — "Smart Fall Detection & Vital Monitoring Device for Elderly Care" — asked teams to design and build a reliable healthcare wearable that monitors vitals, detects falls in real time, and reacts autonomously under uncertain real-world conditions, without external cloud dependency.

Jury — international panel chaired by Vlad Voiculescu (Cognizant Mobility, Munich), with Peter Scharff (TU Ilmenau, Germany), Oliver Faust (Ruskin University, Cambridge, UK), Sorin Bora (Cognizant Romania) and Alexandru Iovanovici (Universitatea Politehnica Timișoara).

Judging criteria — core functionality and reliability · fall-detection performance · intelligent edge processing, security and robustness · hardware–software integration · user experience and technical documentation.

"Technology that reacts when it matters most."

The system in one diagram

flowchart LR
    subgraph Wearable["🛡️ ESP32 wearable"]
        direction TB
        Sensors["IMU · HR · SpO₂ · Temp<br/>sampled @ 100 Hz"]
        Edge["On-device Edge AI<br/>(2 Edge Impulse impulses)"]
        Local["Local alarm<br/>buzzer + red LED + OLED"]
        Sensors --> Edge --> Local
    end

    Bridge["📱 Phone bridge<br/><i>(out of scope)</i>"]
    DB[("🗄️ Supabase Postgres<br/>telemetry_readings<br/>fall_events")]
    Web["💻 Caregiver web app<br/><a href='https://guardian-companion.tech'>guardian-companion.tech</a><br/><i>(this repo)</i>"]

    Wearable -- "BLE @ 2 Hz" --> Bridge
    Bridge -- "HTTPS INSERT" --> DB
    DB -- "Realtime WebSocket" --> Web

    classDef device fill:#dfeaf6,stroke:#3a6a9c,color:#0d2238
    classDef offRepo fill:#f3eef8,stroke:#7c5fa7,color:#231541
    classDef cloud fill:#e8f1e4,stroke:#5b8a3f,color:#1f3814
    classDef ui fill:#fde9c4,stroke:#c2851b,color:#3a2a06
    class Wearable,Sensors,Edge,Local device
    class Bridge offRepo
    class DB cloud
    class Web ui
Loading

Three independent layers:

Layer What it does Where it lives
Wearable Sensor reading, on-device ML, local alarm firmware/ (snapshot of RobuGabrie/esp32-fall-detection)
Phone bridge BLE → Supabase fan-out out of scope; a thin Android app for the demo
Caregiver Live dashboard, 3D mannequin, fall-alert modal, history this repo — src/

The wearable owns the safety loop end-to-end. The caregiver app is a remote observability + response surface — not a dependency. The phone bridge is intentionally not part of the competition deliverable: any process that subscribes to the BLE FallGuard service and forwards rows to Supabase will work.

What's in this repository

.
├── firmware/              ESP32 firmware (Robu Gabriel) — full snapshot
│   ├── README.md          full firmware docs (BOM, gates, BLE, OLED UI)
│   ├── CREDITS.md         attribution + AI-training notes
│   ├── platformio.ini
│   └── src/
│       ├── main.cpp                  all firmware logic
│       ├── derived_metrics.{cpp,h}   steps, cadence, posture, sleep
│       └── merged/                   Edge Impulse multi-impulse export
│
├── src/                   Caregiver web app (Tudor Baranai)
│   ├── app/                          Next.js App Router (Overview, Motion, History, Settings)
│   ├── components/guardian/          Guardian design system
│   └── lib/
│       ├── device.ts                 DeviceSnapshot + local battery estimator
│       ├── telemetry.ts              Telemetry row shape + applyTelemetry()
│       └── supabase.ts               client, realtime, read helpers
│
├── supabase/
│   └── migrations/        Postgres schema + realtime publication
│
└── docs/
    ├── HARDWARE.md        Bill of materials + GPIO pin map + power notes
    ├── REPLICATE.md       Step-by-step rebuild guide (HW → AI → FW → web)
    ├── FALL_FLOW.md       Fall-to-reaction sequence (mermaid + code refs)
    ├── screenshots/
    └── media/

Features

On the wearable (firmware)

  • Two on-device TinyML models running entirely on the ESP32 (no cloud): a 4-class activity classifier and a binary fall detector, both exported as a multi-impulse C++ library from Edge Impulse Studio
  • Three-gate detection pipeline — hard-real-time IMU trigger (Core 1) → ML majority vote across 3 windows around the impact (Core 0) → posture and stillness confirmation after a 3-second settle. A fall is only confirmed when all three layers agree
  • 100 Hz IMU sampling on a dedicated FreeRTOS core, ring-buffered for the ML and trigger logic
  • Vitals fusion — HR, SpO₂, body temperature, HRV proxy, resting HR, stress score
  • 9-page OLED UI + status LEDs + buzzer for local feedback. Always-on dim mode for at-a-glance visibility
  • BLE telemetry — 19-byte packed packet @ 2 Hz, plus FALL event notifications
  • See firmware/README.md for the full firmware documentation

In the caregiver web app

  • Live telemetry dashboard — HR, SpO₂, body temperature, stress, battery, posture, sleep state, step count, HRV, resting HR. Each card holds the last good value when a partial row lands instead of blanking
  • 3D mannequin that mirrors the wearer's posture in real time from the IMU gravity vector, with auto-calibration on the first reading so the device's mounting tilt is treated as the new zero
  • Animated activity states — Walking / Running / Stationary / Falling — debounced over consecutive rows so a single noisy classification doesn't flicker the animation
  • Fall-alert modal, mounted in the root layout so it takes over any page the caregiver is on. Configurable false-alarm countdown; guarded "Mark as false alarm" confirmation; re-latches automatically after page refresh if a fall is still open
  • Local runtime estimation — battery time-left computed from a rolling 3-hour window of voltage samples (smoother than the firmware's chunky integer percent)
  • Daily activity donut — minutes per activity since local midnight, with a 5-minute gap cap so a writer outage isn't counted as one big block
  • Accessibility-first — Atkinson Hyperlegible font, body ≥ 18 px, CTA ≥ 20 px, 1.6× line height, ≥ 56 px touch targets, WCAG 2.1 AAA contrast on body text. Every status uses icon + colour + text label. Motion respects prefers-reduced-motion
  • Best-effort email notifications via Resend (/api/notify); logs and returns success in demo mode when no API key is set

The AI — trained on the actual wearable

Both Edge Impulse impulses were trained by Tudor Baranai on data captured on the production wearable (same MPU6050, same strap, same ±16 g range used at runtime). Sampling on the deployed device — not on a phone or breadboard — is what made the models work in the field: mounting geometry, strap tightness, and the IMU's full-scale range are all baked into the training distribution.

Fall classifier (Model B)
Accuracy (validation) 94.2 %
Weighted F1 0.94
AUC 0.93
Confusion matrix 88.9 % true positive on FALL, 97.1 % true negative on NORMAL
On-device inference 2 ms · 3.2 KB RAM · 50.7 KB flash · 80 MHz ESP32

Edge Impulse training metrics — Model B (fall classifier)

Short demo of the training session — recorded while the dataset was being labelled in Edge Impulse Studio:

If your viewer doesn't render the inline player above, the file is at docs/media/ai-training.mp4 — download or open the raw URL.

Full dataset recipe, impulse design and tuning notes are in docs/REPLICATE.md → Section 2.

Tech stack

Firmware — C/C++ · Arduino framework on PlatformIO · FreeRTOS dual-core · Bluedroid BLE · Edge Impulse SDK · MPU6050 / SSD1306 / MAX30205 / MAX32664 drivers ML — Edge Impulse Studio · spectral DSP + fully-connected NN (activity) · DSP + 1-D ConvNet (fall) · multi-impulse C++ export Web app — Next.js 16 (App Router, TypeScript, React 19) · Tailwind CSS v4 · shadcn/ui + Radix · Atkinson Hyperlegible Backend — Supabase (Postgres + Realtime) · Resend (optional, email notifications) Hosting — Vercel · custom domain (guardian-companion.tech)

Rebuild this project from scratch

Full step-by-step guide: docs/REPLICATE.md (hardware → AI training → firmware → web app → phone bridge).

For just the web app:

cp .env.example .env.local            # then set NEXT_PUBLIC_SUPABASE_*
npm install
npm run dev                           # http://localhost:3000

For just the firmware:

cd firmware
pio run                               # build
pio run -t upload                     # flash to ESP32
pio device monitor                    # serial @ 115200

Further documentation

Team — Sudo (Suceava 2)

🏆 1st place out of 16 teams at HARD & SOFT Suceava 2026.

Two teammates per cross-cutting concern — nothing single-bus-factor.

Member Primary role Also worked on
Tudor Baranai Caregiver web app · 3D mannequin UI · Supabase data layer Edge Impulse model training (with Gabi) · Supabase schema (with Stas)
Robu Gabriel-Lucian Firmware (firmware/ · upstream repo) — three-gate detection pipeline, FreeRTOS architecture, BLE protocol, OLED UI Edge Impulse model training (with Tudor)
Casciuc Stanislav ("Stas") Hardware — wiring, sensor integration, electrical bring-up Supabase schema (with Tudor)
Victor Covaliov Industrial design — 3D-printed wearable enclosure Hardware assembly

Cross-cutting work

  • AI training (both Edge Impulse impulses): Tudor + Gabi
  • Supabase (schema + RLS + realtime config): Tudor + Stas
  • Hardware build (wiring, enclosure fit, on-bench bring-up): Stas + Victor

Security model — this is a portfolio / demo build

This project was built to win a hardware competition and ship as a public portfolio piece. It is not a production medical device. A few intentional trade-offs are worth calling out so a reader doesn't draw the wrong conclusion:

  • The Supabase publishable (anon) key is shipped to the browser. Row-Level Security restricts writes to a single known device_id, but anyone who reads the repo can spoof telemetry / fall events for that device. This is acceptable for a single-device demo; a production fleet would move ingestion behind a service-role key on a server route, or scope RLS by a per-device JWT claim.
  • /api/notify only accepts requests with a same-origin Origin header and caps recipients per call. That's good enough to block casual scripted abuse, but Origin is spoofable from curl. The endpoint is currently safe because no RESEND_API_KEY is set in production — it runs in logged-only mode. Don't set the Resend key without first adding real auth (CSRF token, server-issued nonce, or a dedicated phone-bridge service role).
  • The firmware's BLE service is unpaired and unauthenticated. Any device within ~10 m can connect, read vitals, and write the alert_off command to silence a real alarm. The README inside firmware/ warns about the demo UUID; the lack of pairing / encryption is the same kind of demo trade-off and any production build must add BLESecurity bonding.
  • Security headers (CSP, X-Frame-Options, etc.) are configured in next.config.ts. They're reasonable defaults; tighten CSP further if you add third-party embeds.

License

MIT © 2026 Tudor Baranai and the Sudo team — applies to the caregiver web app, schema, and documentation in this repository.

The firmware in firmware/ is the work of Robu Gabriel and is all-rights-reserved (the upstream repo carries no licence); it is included as part of the team's competition deliverable. See firmware/CREDITS.md for the full attribution.

The Edge Impulse SDK vendored under firmware/src/merged/edge-impulse-sdk/ ships under its own Apache 2.0 licence — see headers inside that folder.

Security note — the BLE service UUID in firmware/src/main.cpp (f00dbabe-…) is a demo identifier. Any device rebuilt from this snapshot must change it before a real deployment so a stranger's app can't latch on.

About

The Guardian — caregiver companion app for a wearable fall-detection device (HARD&SOFT 2026)

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors