Hardware

The Physical Build

Three core hardware components work together on a NodeMCU V2 board, communicating over I²C and GPIO to detect, process, and signal posture events.

Sensor × 2

MPU6050 Gyroscope

GY-521 · I²C · Addr 0x68 / 0x69

Two MPU6050 modules are placed at opposite ends of the spine — one near the upper back, one at the lower. They share the same I²C bus but are differentiated by the AD0 pin: module 1 connects AD0 to 3V3 (address 0x69), module 2 to GND (address 0x68).

  • 6-axis IMU: 3-axis gyro + 3-axis accelerometer
  • 16-bit ADC resolution per axis
  • Gyro range: ±250 to ±2000 °/s configurable
  • Digital Motion Processor (DMP) onboard
  • 3.3V operating, I²C up to 400kHz
Microcontroller

NodeMCU V2

ESP8266 · 80MHz · 2.4GHz WiFi

The brain of the device. It reads both MPU6050 sensors via I²C, runs the posture detection logic, drives the vibration motor over GPIO, and uses its built-in ESP8266 WiFi chip to communicate with the Flask server over HTTP when bad posture is detected.

  • ESP8266 SoC — 80MHz Tensilica L106 core
  • 4MB flash, 64KB instruction RAM
  • 802.11 b/g/n WiFi (2.4GHz only)
  • 11 digital I/O pins (D0–D10)
  • Programmable via Arduino IDE + ESP8266 core
Actuator

Vibration Module

GPIO D5 · Digital Control · 5V

A simple vibration motor module that provides the first tactile alert to the user. Driven by pin D5 on the NodeMCU, it activates instantly when the posture threshold is crossed, giving the user a physical reminder before any network action is taken.

  • Digital IN control (HIGH = vibrate)
  • Powered from VIN (5V from USB)
  • Low current draw — safe for direct GPIO drive
  • Discrete, wearable form factor
MPU6050 #1 Wiring (AD0 → 3V3)
NodeMCUMPU6050
3V3VCC
GNDGND
D1SCL
D2SDA
3V3AD0
MPU6050 #2 Wiring (AD0 → GND)
NodeMCUMPU6050
3V3VCC
GNDGND
D1SCL
D2SDA
GNDAD0
Vibration Module Wiring
NodeMCUVibration Module
D5IN
VINVCC
GNDGND

Software Stack

The Server & Frontend

Three Python/web layers handle subscription management, push delivery, and public access — all running locally but exposed to the internet via ngrok.

Flask (App.py)
The core backend server. Hosts the web interface, manages push subscription registrations (/subscribe), receives posture signals from the Arduino (/signal), exposes and receives sensitivity settings (/getSensitivity, /setSensitivity), and fires Web Push notifications to all registered phones.
Python · Port 8090
pywebpush
Handles the VAPID-authenticated Web Push protocol. When the Flask /signal endpoint is triggered, pywebpush sends encrypted push payloads to each subscribed phone's push service (e.g., Google FCM, Apple APNs). Expired subscriptions (410) are automatically removed.
VAPID · RFC 8292
ngrok
Tunnels the local Flask server to a public HTTPS URL, making it reachable from phones outside the local network. Required for Web Push to work, since push service callbacks must reach a public endpoint. The URL is stable across sessions when using a reserved domain.
HTTPS Tunnel
Test.py
A command-line utility for testing the system without the physical device. Lets you manually fire a posture signal (/signal) or send a new sensitivity value to the server (/setSensitivity). Useful for debugging push notification delivery and tuning angle thresholds.
Dev Tool

Signal Path

End-to-end Data Flow

From sensors on your back to a notification on your phone — this is the complete signal journey.

📐
MPU6050 × 2
gyro data
I²C
🧠
NodeMCU
angle diff logic
GPIO D5
📳
Vibration
haptic alert
HTTP GET
⚗️
Flask
/signal endpoint
VAPID push
🔔
Your Phone
push notification

Configuration

Adjustable Sensitivity

The sensitivity slider maps a 0–100 value to an angular threshold in the Arduino firmware. Higher sensitivity = smaller angle triggers an alert faster.

Web App (Frontend)

User moves slider (0–100). App POSTs {"value": N} to Flask's /setSensitivity.

Flask Backend

Clamps the value to 100–5000, stores it in memory as the global sensitivity variable, returns confirmation JSON.

Arduino (NodeMCU)

Polls /getSensitivity every few seconds. Updates its internal xThreshold variable dynamically — no re-flashing required. The threshold directly controls how much angular deviation is tolerated before triggering the vibration and signal.