Denys Inhul

ch2: heartbeat through a wall

date: May 17 2026

the question driving this chapter: can a radar detect a person’s heartbeat through walls?

1. Why this works at all

Your chest moves out by about 5 mm with each breath, and the surface of your skin twitches by something like half a millimeter with each heartbeat. The marvelous thing is that a radar sitting across the room, on the other side of a drywall, can pick both of those up. Half a millimeter is roughly a hundred times smaller than the wavelength the radar is using, and a few hundred times smaller than its range resolution. That’s a wild gap to close with a $30 chip.

Three things stack up to make it work. First, common building materials are surprisingly transparent at radio frequencies below ~10 GHz: drywall, wood, plaster, even brick attenuate the signal by only single-digit dBs, so enough energy makes it through to bounce off a person and come back. Second, radar measures not only the strength of the return but also its precise phase, and at GHz frequencies the phase shifts visibly for motion all the way down to tens of microns. Third, breathing and heartbeats are nearly periodic, so even when their motion is buried 60 dB below the static returns from the wall and the furniture, their frequencies still stand out as sharp peaks in the FFT of the phase signal.

The constraints come straight out of those three reasons. You have to pick a frequency that the wall in front of you actually lets through. You need a phase-coherent radar with enough SNR that its phase noise stays well below the displacement you’re trying to detect. And you have to subtract the overwhelmingly large static scene before any of the small periodic motion becomes visible. The rest of this chapter is those three constraints, in detail.

2. What gets through a wall

Penetration loss depends on the wall material, its thickness, and the frequency. Approximate one-way losses for common residential materials at 20 cm thickness:

material~2.4 GHz~6 GHz~24 GHz~77 GHz
Drywall (single 1.6 cm layer)~0.5 dB~1 dB~2 dB~3 dB
Wood (interior door, 4 cm)~1 dB~2 dB~5 dB~10 dB
Brick (20 cm)~5 dB~10 dB~25 dB~60+ dB
Concrete (20 cm)~10 dB~20 dB~40+ dBopaque

Rebar mesh in concrete acts as a wavelength-dependent screen; metal grid spacing matters more than the concrete itself. A continuous metal sheet is opaque at all RF frequencies.

Numbers are order-of-magnitude. Real wall losses vary by moisture content (a wet brick wall loses ~3x more) and construction details. ITU-R P.2040 is the canonical free reference for measured complex permittivity by material and frequency.

The full two-way signal budget for a target behind a wall has four loss terms:

Prx  =  PtxGtxGrxλ2σ(4π)3R4Friis radar equationLwall2P_\text{rx} \;=\; P_\text{tx} \,\cdot\, \underbrace{\frac{G_\text{tx} G_\text{rx} \lambda^2 \sigma}{(4\pi)^3 R^4}}_\text{Friis radar equation} \,\cdot\, L_\text{wall}^2

The R4R^4 falloff dominates at long ranges. The Lwall2L_\text{wall}^2 term (wall loss applied twice, once each way) dominates at low ranges through dense walls. At 2.4 GHz through 20 cm brick at 3 m range, the wall costs ~10 dB and free space costs ~50 dB; both are non-trivial.

The frequency tradeoff for through-wall radar is direct: lower frequency means better penetration but worse range and angular resolution; higher frequency gives finer resolution and smaller antennas but the wall starts to look opaque. The band sweet spot for most published work is roughly 1 to 8 GHz.

3. The phase trick

A radar’s range resolution is set by bandwidth:

Δr  =  c2B\Delta r \;=\; \frac{c}{2B}

At 1 GHz of bandwidth, Δr=15\Delta r = 15 cm. A person’s chest is much smaller than a range bin, so the entire chest sits in one bin. Within that bin, the radar still records a complex number per chirp; its phase encodes the precise distance modulo λ/2\lambda/2.

For a target at range dd illuminated by frequency f0f_0, the round-trip phase is

ϕ  =  4πdλ  =  4πdf0c\phi \;=\; \frac{4\pi d}{\lambda} \;=\; \frac{4\pi d f_0}{c}

A motion Δd\Delta d shifts the phase by

Δϕ  =  4πΔdλ\Delta\phi \;=\; \frac{4\pi \,\Delta d}{\lambda}

Inverting:

Δd  =  λ4πΔϕ\Delta d \;=\; \frac{\lambda}{4\pi} \,\Delta\phi

Numerical example

At f0=5.6f_0 = 5.6 GHz, λ=54\lambda = 54 mm. Suppose the radar can resolve phase to 1° (about π/1800.017\pi/180 \approx 0.017 rad). Then

Δdmin  =  54 mm4ππ180    75 μm\Delta d_\text{min} \;=\; \frac{54 \text{ mm}}{4\pi} \cdot \frac{\pi}{180} \;\approx\; 75 \text{ μm}

That is 2000x finer than the 15 cm range bin. The chest sits in one bin, but its complex phase moves enough to register breathing (chest excursion ~5 mm) and heartbeat (skin surface ~0.5 mm) provided the phase noise is low enough.

How fine can the phase actually be resolved

For an additive white Gaussian noise model, phase noise on a complex measurement at signal-to-noise ratio SNR (linear) is approximately

σϕ    12SNR rad\sigma_\phi \;\approx\; \frac{1}{\sqrt{2 \cdot \text{SNR}}} \text{ rad}

At 30 dB SNR (SNR = 1000), σϕ0.022\sigma_\phi \approx 0.022 rad 1.3°\approx 1.3°, which corresponds to 100\sim 100 μm motion at 5.6 GHz. At 20 dB SNR (SNR = 100), σϕ4°\sigma_\phi \approx 4° and the minimum detectable motion grows to 300\sim 300 μm. Detecting a heartbeat through a wall requires keeping SNR high enough that the heartbeat-induced phase modulation exceeds σϕ\sigma_\phi.

Phase extraction and the breathing / heart spectrum

A synthetic chest with two simultaneous motions: slow breathing (large amplitude, low frequency) and faster heartbeat (small amplitude, higher frequency). The radar sees this as a phase signal in slow time. Below the time signal is its FFT, where the two motions appear as peaks.

0.30 5.0
1.20 0.50 2.0
Top: chest displacement reconstructed from radar phase over a 30-second observation. Bottom: FFT of the phase signal. The breathing peak sits well below 0.5 Hz; the heartbeat peak sits above. When heart amplitude or SNR is low, the cardiac peak disappears into the breathing-harmonic spectrum.

4. Clutter is the enemy, not noise

The signal coming back from a real room is overwhelmingly dominated by reflections from things that aren’t moving: the wall itself, the furniture, the floor, your own radar enclosure. These static returns sit anywhere from 30 to 60 dB above the person’s reflection, and 60 to 90 dB above the chest-motion modulation inside that person’s reflection. Phase noise is not the limiting factor in this chapter; clutter is. Almost the entire signal-processing job for through-wall radar is figuring out how to make the static part go away.

There are three standard tricks for that.

Background subtraction

The simplest move: capture a single frame when the scene is empty, then subtract that frame from every subsequent frame. Anything that didn’t move between the calibration and the measurement just vanishes. Cheap and effective when you can do the calibration step, but brittle the moment someone moves a chair or the radar drifts thermally.

Moving Target Indication (MTI)

Subtract each frame from the one just before it along slow time. Anything static cancels by construction; anything moving leaves a residual. That’s literally just a one-tap high-pass filter on the slow-time axis:

y[n]  =  x[n]    x[n1]y[n] \;=\; x[n] \;-\; x[n-1]

The nice thing about MTI is that it needs no calibration step at all. The not-so-nice thing is the notch sitting at DC and the reduced response at the very low frequencies right next to it, which chews straight into the breathing band if you’re not careful. The demo below shows exactly that failure: with fbreath/fsf_\text{breath}/f_s near DC, MTI gain on the breathing tone collapses to ~0.19 (about 14 dB of suppression) while the noise floor goes up by 2\sqrt{2}, so the target sinks below the noise. Background subtraction and SVD both keep the full breathing swing intact under the same conditions.

SVD / subspace methods

The heavier-weight option: stack all your slow-time frames into an Nrange×NslowN_\text{range} \times N_\text{slow} matrix and run an SVD on it. The first one or two singular vectors will almost always capture the static scene, because by construction those are the components that don’t change across slow time. Drop them and reconstruct from the rest:

Xmoving  =  X    i=1kσiuiviX_\text{moving} \;=\; X \;-\; \sum_{i=1}^{k} \sigma_i u_i v_i^*

More aggressive than MTI, way more compute, and noticeably more robust when the “static” scene isn’t really static (small wall vibrations, slowly drifting furniture, your radar’s own thermal expansion).

Clutter cancellation on a range-time map

Synthetic range-vs-slow-time intensity map. A bright static return at range bin 22 (the wall) dominates the raw view. A weak moving target at bin 38 (a breathing person behind the wall) is hidden underneath. Toggle the processing to see what each method removes.

5. Putting it together at 2.4 GHz

Picture a concrete setup: a 2.4 GHz FMCW radar pointed at a wall, sweeping somewhere around 50 to 100 MHz of bandwidth at maybe 50 chirps per second over a 30-second observation. This is roughly the MIT coffee-can radar regime, or any cheap FMCW board running in the 2.4 GHz ISM band. At 2.4 GHz the wavelength is 12.5 cm, so a 5 mm breathing excursion shifts the round-trip phase by about 30° and a half-millimeter heartbeat by about 5°. Range resolution is coarse (a couple of meters with 80 MHz of sweep), which means the entire person sits inside one or two range bins. That’s actually what you want here, because the chest motion you’re chasing lives in the phase of that bin, not in its range.

From there the pipeline is three conceptual blocks stacked on top of each other.

The first block is the standard FMCW range FFT. Each chirp gets FFT’d into a range profile, and the profiles are stacked along slow time into a 2D matrix: range bins on one axis, chirp index on the other. Nothing exotic, this is the same first step every FMCW radar takes regardless of what it’s being used for.

The second block is the clutter step from the previous section. Whichever method you pick (background subtraction, MTI, or SVD), it runs along the slow-time axis of that matrix. After this step the matrix is mostly empty, except for whatever in the scene was actually moving, which in our case is one person breathing.

The third block is the phase trick from earlier in the chapter, applied to whichever range bin the person sits in. You pull the complex value of that bin out chirp by chirp, take its argument, unwrap any 2π2\pi jumps, and you end up with a time series of chest displacement sampled at the chirp rate. Bandpass that into a breathing band around 0.1 to 0.6 Hz and a cardiac band around 0.8 to 2.5 Hz (the two motions sit on top of each other in the raw phase), then FFT or peak-pick to read the rate off each band.

That’s the whole thing in principle. The rest is engineering knobs: how aggressively you cancel clutter, how you decide which range bin contains the person, how to handle harmonic overlap between the third harmonic of breathing and the cardiac fundamental, and whether you exploit MIMO to filter by angle if you happen to have more than one RX.

6. Where it gets hard

Even when the pipeline above works on paper, plenty of things in a real setup can make the result harder to read than the math suggests. None of these are showstoppers on their own, but they pile up and turn vital-signs radar into a real engineering problem rather than a 50-line script:

  • Multiple people in the same range bin. Their chest motions just add together in the phase signal. Without some kind of spatial diversity (a MIMO array, two radars at different positions, or angle filtering), pulling them apart is genuinely hard.
  • Wall reverberation. RF energy bounces around inside a thick wall before coming back out, so you can get ghost copies of the real return at fake ranges. These ghosts move when the actual target moves, which means clutter cancellation won’t delete them.
  • Body motion other than chest. A small finger twitch or a posture shift creates phase swings way bigger than breathing or heartbeat. The usual workaround is to throw out windows where large motion is detected, but you lose data while the subject moves.
  • Breathing harmonics in the cardiac band. A 0.4 Hz breathing rate has a third harmonic at 1.2 Hz, sitting right where a 72 bpm heartbeat lives. You can try to subtract the breathing fundamental and its harmonics adaptively, but it never quite goes away.
  • Platform vibration. The radar itself sitting on a table that vibrates from HVAC or footsteps adds phase noise at exactly the band you care about. Mechanically isolating the radar can matter as much as the RF design.
  • Phase wrapping during gross motion. If the target moves more than λ/4\lambda/4 between two chirps, the unwrapping step has no way to know how many wraps it missed. Your chirp rate has to be fast enough that even fast motion stays under λ/4\lambda/4 per chirp.

next: ch3: EM waves in matter →