ESP32 CSI human detection: a practical, calibrated setup

2026-10-11 · 2 min read

ESP32 CSI human detection is the cheapest way to get a working Wi-Fi sensing demo. The hard part is not capture — it is calibration and gating. Here is a setup that survives a real room.

1. Capture

Path Tool Output
Minimal espressif/esp-csi examples [2] CSR/CIR data over UART or Wi-Fi
Dataset-friendly ESP32-CSI-Tool [3] CSV of amplitude/phase per subcarrier
Home Assistant ESPectre (ESPHome) [4] presence/motion entity directly

Keep one ESP32 as a sender (UDP packets at a fixed rate) and one as the receiver; independent Wi-Fi traffic makes the measurement rate jump around.

2. Features that work

import numpy as np

# H: (time, subcarriers) amplitude matrix (30-64 subcarriers on ESP32)
detail = np.abs(np.diff(H, axis=0)).mean(axis=1)      # inter-packet change
var    = H.var(axis=1)                                # per-packet variance
motion = 0.5 * detail + 0.5 * var                     # cheap fusion

Do not feed raw CSI into a threshold — normalize per subcarrier first, otherwise a single noisy subcarrier dominates. Amplitude-variance features of this kind are standard for CSI activity recognition [1].

3. Calibrate with hysteresis (the part demos skip)

ENTER, EXIT = 3.0, 1.5          # tune per room; ENTER > EXIT
state, hold = False, 0
for m in motion:
    if not state and m > ENTER:
        state, hold = True, 0
    elif state and m < EXIT:
        hold += 1
        if hold > 5:            # ~0.5 s of quiet before leaving
            state = False
    else:
        hold = 0

Record quiet and active baselines per room, then set ENTER ≈ quiet_mean + 4σ and EXIT ≈ quiet_mean + 2σ.

4. Why demos fail in real rooms

Failure Cause Fix
Works in the office, not at home different multipath baseline recalibrate per room
False positives when nobody moves HVAC, curtains, pets longer windows + higher ENTER
Misses a still person no micro-motion add respiration detection or an mmWave sensor
Random dropouts ESP32 shares the channel with home Wi-Fi fixed sender + channel planning

5. When to switch to a router

If you want whole-home coverage without scattering ESP32 boards, a CSI-capable router does the same job with 80 MHz / 256 subcarriers and 8 chains — see the router guide and the ESP32 vs router comparison.

Related: Home Assistant integration · vs mmWave radar · Wi-Fi CSI radar

References and data sources

Every external claim carries a source and an evidence grade (grading scheme). Grade E marks first-party, reproducible measurements from this project.

  1. Grade A · standard/review WiFi Sensing with Channel State Information: A Survey
    W. Ma, W. Zhou, X. Wang · ACM Computing Surveys · 2019
    doi:10.1145/3310194 · citations 857 · verified: CrossRef API, 2026-10-11 · The field's most-cited CSI sensing survey (857 citations, verified via CrossRef).
  2. Grade C · official docs espressif/esp-csi — Applications based on Wi-Fi CSI
    Espressif Systems
    github.com/espressif/esp-csi · verified: GitHub API 2026-10-11 (stars 1,679) · The official README states: "All ESP32 series support CSI, including ESP32 / ESP32-S2 / ESP32-C3 / ESP32-S3 / ESP32-C5 / ESP32-C6 / ESP32-C61."
  3. Grade C · official docs StevenMHernandez/ESP32-CSI-Tool — active/passive CSI extraction for ESP32
    S. M. Hernandez
    github.com/StevenMHernandez/ESP32-CSI-Tool · verified: GitHub API 2026-10-11 (stars 571, MIT, last push 2024-07-16)
  4. Grade C · official docs francescopace/espectre — Wi-Fi CSI motion sensing for ESP32 (ESPHome)
    F. Pace
    github.com/francescopace/espectre · verified: GitHub API 2026-10-11 (stars 9,505)

This page contains affiliate links (rel="sponsored"). Buying through them costs you nothing extra and earns this site a small commission.