ReBalance

The hard part was not drawing a balance meter. It was separating noisy measurement from feedback a person could trust.

ReBalance is a rehabilitation feedback prototype built around force-sensing resistors, Web Serial data, calibration, and a live dashboard. The system reads left/right pressure from a physical board and turns that stream into a stable balance score.

The product constraint was human: if the cue flickers every time the user makes a tiny correction, the interface trains them to chase noise. The software had to preserve the raw signal for debugging while presenting a calmer correction cue.

2nd place CPES Hackathon$74 Arduino rehab prototype~20 Hz Web Serial pipeline

This project appears under Projects on my resume.

ReBalance landing page and dashboard screenshot
Product dashboard: a low-cost rehab prototype turning balance data into readable feedback.

Pressure-to-feedback flow

  1. 01FSR board
  2. 02serial frames
  3. 03baseline correction
  4. 04zone scoring
  5. 05stable cue

Raw pressure becomes a calmer correction cue.

The system keeps the debugging signal visible while separating it from the feedback a patient should act on.

  1. FSR sensors
  2. Arduino
  3. Web Serial
  4. calibration model
  5. dashboard cue
  6. user correction
Before calibration

Jitter drives the cue.

Raw pressure is useful for diagnosis, but it can flicker too much for rehabilitation feedback.

After calibration

Dead zone and offset correction settle the output.

Baseline correction, an active threshold, and zone scoring make the public cue calmer than the input.

Sensor sampling around 20 HzNewline-delimited Web Serial parsingPer-side baseline calibrationDead-zone thresholdUI smoothing through zone labelsInvalid frame and idle-state handling

A neutral stance is not automatically neutral sensor data.

Calibration before presentation

The calibration pass captures 100 samples over five seconds while the user stands centered. That produces a per-side baseline, so later readings can be scaled back toward the board's true center instead of assuming both sensors are identical.

  • The calibration component samples live values on a timed loop and stores averaged left/right baselines.
  • The balance calculation applies per-side scale factors before deriving the right-side ratio.
  • The UI can show raw pressure while the score derives from corrected values.

The raw stream remains visible, but it does not directly drive the cue.

Noise is allowed internally

The scoring function starts with an active-pressure threshold, then classifies deviation from center into balanced, warning, or danger zones. That keeps the public cue stable while preserving enough diagnostic data to understand jitter.

  • Low total pressure returns an idle state instead of a misleading 50/50 score.
  • Zone color, label, and badge all derive from one balance-zone helper.
  • Demo mode injects waves, noise, and bursts to test behavior without hardware attached.

The board sends simple newline-delimited frames; the UI owns parsing and resilience.

Serial data as a contract

The serial hook buffers incoming text, splits complete lines, recognizes a readiness marker, and only updates pressure state when it sees two valid numeric values. That makes the connection layer explicit and debuggable.

  • The hook cancels readers and closes ports during disconnect.
  • Partial serial lines stay buffered until a newline arrives.
  • Invalid frames are ignored instead of poisoning the balance state.

Raw jitter becomes a stable cue

The visual keeps noisy samples visible while the calibrated output settles into a readable correction.

raw jitterbaselinecentered cue

Short excerpts that show the design choices.

Snippets are trimmed for readability and paired with the source file they came from.

balanceback/src/utils/balanceCalc.js

Baseline-corrected score

js
if (total < ACTIVE_THRESHOLD) return { ratio: 0.5, score: 0, zone: "idle" };

const baselineAvg = (baseline.left + baseline.right) / 2;
const correctedLeft = left * (baselineAvg / baseline.left);
const correctedRight = right * (baselineAvg / baseline.right);
const ratio = correctedRight / (correctedLeft + correctedRight);

This is the core thinking: detect when the board is not active, normalize asymmetric sensors, then score the corrected ratio rather than raw pressure.

balanceback/src/components/Calibration.jsx

Timed calibration capture

jsx
const SAMPLE_COUNT = 100;
const TOTAL_DURATION_S = 5;

samples.push({ left: values.left, right: values.right });
const avgLeft = average(samples.map((sample) => sample.left));
const avgRight = average(samples.map((sample) => sample.right));

The calibration flow turns a shaky live stream into a stable baseline by sampling over time instead of trusting a single reading.

What this project proves.

ReBalance shows my hardware/software bias: I do not treat the UI as separate from the physical system. The useful work was designing the translation layer between imperfect sensors and human-readable feedback.

Contact