Why Not a Wearable?
Elderly residents often forget to wear smartwatches or fall detectors. An FSR network in the floor works passively — no wearing, no charging, no configuration. Just walking through collects data.
The Science: Center of Pressure (COP)
During normal walking, bilateral foot pressure should be roughly balanced (~50:50). A persistent shift — e.g., right foot bearing 65%+ over 3+ days — indicates pain avoidance or muscle weakness leading to elevated fall risk.
COP_x = Σ(F_i × x_i) / Σ(F_i) # left-right axis COP_y = Σ(F_i × y_i) / Σ(F_i) # front-back axis Asymmetry = |F_left - F_right| / (F_left + F_right) × 100%
Hardware: FSR Matrix on ESP32
Core components: - FSR402 or FSR406 (round/square, 0–100N range) - CD74HC4067 16-channel analog multiplexer - ESP32 DevKit (12-bit ADC) - 10mm EVA foam housing for FSR embedding - 3mm polycarbonate top plate (waterproof + step-resistant)
Circuit: FSR + 10kΩ resistor voltage divider → CD74HC4067 → ESP32 ADC.
c // ESP32 firmware — read 16 FSR sensors via multiplexer #include <Arduino.h> #include <PubSubClient.h> const int MUX_S0 = 12, MUX_S1 = 13, MUX_S2 = 14, MUX_S3 = 15; const int MUX_SIG = 34; const int NUM_SENSORS = 16; float readings[NUM_SENSORS]; void selectChannel(int ch) { digitalWrite(MUX_S0, ch & 1); digitalWrite(MUX_S1, (ch >> 1) & 1); digitalWrite(MUX_S2, (ch >> 2) & 1); digitalWrite(MUX_S3, (ch >> 3) & 1); } void readAllFSR() { for (int i = 0; i < NUM_SENSORS; i++) { selectChannel(i); delayMicroseconds(10); int raw = analogRead(MUX_SIG); readings[i] = (raw / 4095.0) * 100.0; // calibrate against reference weight } }
Python: Gait Asymmetry Analysis
python import numpy as np from datetime import datetime def compute_cop_and_asymmetry(left_sensors: list, right_sensors: list) -> dict: """ left_sensors: Newton readings from 8 FSRs on left side right_sensors: Newton readings from 8 FSRs on right side """ F_left = sum(left_sensors) F_right = sum(right_sensors) F_total = F_left + F_right if F_total < 10: # nobody standing return {"standing": False} asymmetry = abs(F_left - F_right) / F_total * 100 cop_x = (F_right - F_left) / F_total # +1 = all right, -1 = all left return { "standing": True, "f_left": round(F_left, 2), "f_right": round(F_right, 2), "asymmetry_pct": round(asymmetry, 1), "cop_x": round(cop_x, 3), "fall_risk": asymmetry > 20 or F_total < 30, "timestamp": datetime.now().isoformat() } def compute_weekly_fall_risk(daily_asymmetries: list) -> str: avg = np.mean(daily_asymmetries) trend = np.polyfit(range(len(daily_asymmetries)), daily_asymmetries, 1)[0] if avg > 25 and trend > 1.0: return "HIGH" elif avg > 15: return "MEDIUM" return "LOW"
Floor Layout: Bilateral FSR Mat
[FSR 1-8: Left side] | [FSR 9-16: Right side] ← 30cm → | ← 30cm → ┌────────────────────────────────────────┐ │ ● ● ● ● │ ● ● ● ● │ Front row │ ● ● ● ● │ ● ● ● ● │ Back row └────────────────────────────────────────┘ ↑ 60cm total — install at bathroom corridor
The optimal location is the bathroom corridor — elderly residents pass through at least 4–6 times daily, providing adequate baseline data.
HA Integration via MQTT
yaml mqtt: sensor: - name: Floor Pressure Left state_topic: home/floor_mat/left_force unit_of_measurement: N - name: Floor Pressure Right state_topic: home/floor_mat/right_force unit_of_measurement: N - name: Gait Asymmetry state_topic: home/floor_mat/asymmetry unit_of_measurement: "%" - name: Fall Risk Level state_topic: home/floor_mat/fall_risk
Caregiver LINE Alert
yaml alias: Fall Risk — High Alert trigger: - platform: state entity_id: sensor.fall_risk_level to: "HIGH" action: - service: notify.line_notify data: message: >- ⚠️ High fall risk detected Gait asymmetry: {{ states('sensor.gait_asymmetry') }}% Please check resident — {{ now().strftime('%d/%m %H:%M') }}
Summary
An FSR floor mat system costing under THB 3,000 in components detects gait asymmetry continuously without disrupting daily life — ideal for elderly residents who resist wearing monitoring devices.
