SGP Official store ↗
Blog / Projects / Amplitude vs phase

Amplitude vs phase in Wi-Fi CSI

Every CSI subcarrier arrives as a complex sample, and you can split it two ways: amplitude and phase. Amplitude is the easy half you can trust almost raw. Phase is the powerful half that is useless until you clean it. This is the honest breakdown of what each one carries, why phase is so noisy, and which half to reach for.

Published 20 Oct 2026Read 11 minLevel IntermediateTopic Wi-Fi CSI
real (I) imag (Q) φ phase amplitude amplitude = √(re² + im²) how strong this subcarrier is phase = atan2(im, re) how delayed it is
FIG 1 — One CSI subcarrier is a point in the complex plane. Its distance from the origin is amplitude; its angle is phase. The two carry different information about the room.

CSI is often drawn as a row of bars, one per subcarrier, and people assume those bars are the whole story. They are only half of it. Each subcarrier is actually a complex number, and that number splits into two very different measurements. Knowing which half to use, and when, is most of the skill in working with CSI.

01The complex sample behind every subcarrier

When the ESP32 hands you CSI, each subcarrier arrives as two signed bytes: an imaginary part and a real part, often called Q and I. Together they describe a single point in the complex plane. That point is the channel's effect on that one frequency: how it scaled the signal and how it rotated it.

You can describe that same point two ways. In rectangular form it is just the real and imaginary values. In polar form it is an amplitude, the distance from the origin, and a phase, the angle. Both forms hold the same information, but they expose different things about the room, and they behave very differently when you try to use them. If the per-subcarrier structure is new, start with CSI subcarriers and OFDM explained.

02What amplitude tells you

Amplitude is the magnitude of the complex sample, the square root of the real part squared plus the imaginary part squared. Physically it tells you how strongly that subcarrier arrived, which depends on how the channel reflected, absorbed and recombined the signal at that frequency.

Its great virtue is that it is easy to use almost raw. Amplitude does not care about the absolute timing of the signal, so it is largely immune to the clock and frequency errors that wreck phase. With nothing more than light smoothing and an empty-room baseline, amplitude already reacts cleanly to a person entering the link, walking through it, or waving a hand nearby. This is why most beginner CSI projects, including our capture how-to, start by summing amplitude into a single energy number.

The trade-off is sensitivity. Amplitude responds well to movement that changes how much energy reaches the receiver, but it is less sharp for very small, fine motion where the main effect is a change in path length rather than in strength.

03What phase tells you

Phase is the angle of the complex sample, the two-argument arctangent of the imaginary part over the real part. It encodes how much the signal was delayed on its way to the receiver, and delay is directly tied to the length of the path the signal traveled.

That link to distance is what makes clean phase so valuable. A path length change of a fraction of a wavelength, roughly a few centimeters at 2.4 GHz, produces a clear, measurable phase shift. This is why phase, once sanitized, is the preferred signal for fine work: estimating distance and angle, tracking the slow rhythm of breathing, and separating movements that barely register in amplitude. The difference across multiple antennas also underpins direction and localization work.

Phase is sharper, and more fragileClean phase can see motion that amplitude barely notices. But raw phase, straight off the board, is dominated by hardware errors. You get its sensitivity only after sanitization, never before.

04Why raw phase is noisy

Raw CSI phase looks almost random because it carries several errors stacked on top of the real channel. None of them are faults in your board; they are inherent to measuring phase between two independent radios.

raw phase (across subcarriers) after sanitization hardware offsets scramble raw phase · removing the linear slope restores the real trend
FIG 2 — Raw phase (left) is scrambled by CFO, SFO and per-packet offsets. A standard linear fit removes the common slope and offset, leaving a usable trend (right).

The standard fix, phase sanitization, unwraps the phase and then removes the linear component, the slope and offset that the clock errors add, usually by fitting a straight line across the subcarriers and subtracting it. What remains is far closer to the true channel phase. We cover this step inside the wider pipeline in cleaning Wi-Fi CSI data.

05Which to use for which task

TaskBetter signalWhy
Presence, coarse motionAmplitudeRobust and usable almost raw
Fine motion, gesturesClean phaseSensitive to small path changes
Breathing / vital signsBoth, phase after cleaningSlow path changes show in phase
Distance / rangingClean phasePhase maps to path length
Quick first prototypeAmplitudeNo sanitization needed

The practical path is clear. Prototype with amplitude because it works immediately, then add sanitized phase when you need the extra sensitivity it buys. Jumping straight to raw phase is the fastest way to get a project that does not work and a signal you cannot explain.

It is also worth knowing that amplitude and phase do not have to be used separately. Many of the strongest CSI systems feed both into a machine-learning model as two channels of the same image, with subcarriers on one axis and time on the other, and let the model learn how to combine them. That still only works if the phase has been sanitized first, so the rule holds: clean before you combine. If you are building something simple on a single board, amplitude alone will carry you a long way, and you can always layer phase on top once the amplitude version is solid.

06Computing both on an ESP32

The math is short. Inside your CSI callback, loop over the subcarriers and turn each interleaved pair into an amplitude and a phase. The snippet below does exactly that and prints one subcarrier so you can see the two numbers.

amp_phase.ino · Arduino-ESP32 3.x
// Amplitude and phase per subcarrier from ESP32 CSI bytes.
// Runs inside the CSI callback. Tested on Arduino-ESP32 3.0.x.
#include <math.h>

static void onCsi(void* ctx, wifi_csi_info_t* info) {
  if (!info || !info->buf) return;
  int8_t* d = info->buf;              // interleaved [imag, real] int8
  int  n   = info->len / 2;          // subcarrier count

  for (int i = 0; i < n; i++) {
    int im = d[i * 2];              // imaginary (Q)
    int re = d[i * 2 + 1];          // real (I)

    float amp   = sqrtf((float)(re * re + im * im));  // magnitude
    float phase = atan2f((float)im, (float)re);       // radians, -pi..pi

    // amp is usable now; phase still needs sanitizing before use.
    if (i == n / 2) {               // print one central subcarrier
      Serial.printf("sc=%d  amp=%.1f  phase=%.2f rad\n", i, amp, phase);
    }
  }
}

Watch the output and the contrast is immediate. The amp figure moves smoothly as you move. The raw phase jumps around even when the room is still, because of the offsets above. That is your cue to sanitize before trusting it. For the full capture scaffolding this drops into, see how to capture Wi-Fi CSI on an ESP32, and always test on your own network.

07FAQ

What is the difference between amplitude and phase in CSI?

Each CSI subcarrier is a complex number. Amplitude is its magnitude, how strong that subcarrier arrived, and it reflects how much the channel attenuated or reinforced that frequency. Phase is its angle, how much the signal was delayed or shifted, and it is very sensitive to tiny changes in path length. Amplitude is easy to use raw, while phase needs cleaning first.

Why is raw CSI phase so noisy?

Raw phase carries several hardware errors on top of the real channel. Carrier frequency offset between the two radios, sampling frequency offset in the clocks, and random phase offsets that change packet to packet all corrupt it. These add unknown slopes and jumps across subcarriers, so raw phase looks like noise until it is sanitized.

Which is better for motion detection, amplitude or phase?

Amplitude is the simpler and more robust starting point for motion and presence, because it is usable straight from the board with light filtering. Clean phase is more sensitive to fine motion and useful for distance and breathing, but only after sanitization. Many practical systems use amplitude first and add cleaned phase when they need the extra sensitivity.

How do I compute amplitude and phase from ESP32 CSI bytes?

The ESP32 gives interleaved signed bytes, an imaginary and a real value per subcarrier. Amplitude is the square root of real squared plus imaginary squared, and phase is the two-argument arctangent of imaginary over real. Compute both inside a loop over the subcarriers, then sanitize the phase before you use it.

SGP Lab — written by the team that designs and builds SGP hardware in Europe. We test every example on our own boards before publishing.

SGP devices are sold only at our official store.

sgpstore.net ↗