Choose a detector profile
Both profiles run on the ESP32 and produce the same snapshots and motion events. Choose between lower resource use and better results in our tests; your integration code stays the same.
Product comparison
| Lightweight | High Accuracy | |
|---|---|---|
| Choose it when | CPU and memory are tight | Detection quality and fewer false alarms in a quiet room come first |
| Decision input | 2 features | 8 features |
| Classifier | Fixed logistic combination of the two features | MLP: 8 → 24 → 12 → 1 |
| Persistent detector state | 2,016 B | 5,068 B |
| Startup | About 10 seconds of clean data, or up to about 30 seconds when that window holds a burst | No calibration; uses a threshold of 0.5 |
| Learned parameters | Two logistic weights, an intercept, and fitted normalization | 529 neural-network parameters |
Detector state is the detector object's sizeof plus the heap it allocates, not counting allocator overhead or the rest of the firmware. A build that can switch profiles at runtime still stores both detectors and the model weights in flash.
Lightweight's weights are fitted in advance on training recordings and built into the firmware. Calibration at startup only adapts the threshold to the room.
Current measured comparison
The generated performance report compares both profiles on the same 13 pairs of real recordings (selection + holdout), with the same simulated drift and packet loss added from the same two fixed seeds. The device columns are plain averages of the passing Native, ESPHome, and Matter runs in the per-chip reports, without Micro-ESPectre.
| Detection profile | Recall | False-positive rate | F1 | Mean detection time | Mean runtime CPU |
|---|---|---|---|---|---|
| Lightweight | 98.7% | 0.8% | 98.6% | 0.814 ms | 7.36% |
| High Accuracy | 99.4% | 0.1% | 99.5% | 2.956 ms | 10.14% |
AUTO), the runtime picks lltf20 for its own raw Wi-Fi traffic, vht20 on 5 GHz, and ht20 otherwise; the device resource reports it as csi_profile. With lltf20, missing subcarriers stay missing in raw CSI and are filled in only for the detector.How one second of CSI becomes a decision
The detector wants 100 samples per second. Time is split into 10 ms slots, and each slot keeps only the packet closest to its center. Empty slots stay empty, and a burst of packets in one slot still counts once. So bursts cannot make the detector's clock run faster than real time.
The detector becomes ready after one second with at least 70% of its slots filled. Once it is ready, coverage below 70% for less than one window still produces decisions. The runtime decides every 250 ms. A gap as long as the window clears detector history.
Which frequencies each feature uses
Both profiles follow twelve fixed subcarriers spread across the HT20 band: ±4, ±9, ±14, ±19, ±24, ±28, counted from the center. Because they are fixed, every session can be compared and nothing depends on choosing subcarriers per room.
| Signal view | Frequency input | Used by |
|---|---|---|
| Temporal turbulence | 12 fixed subcarriers across the band | Both profiles |
| Aggregated turbulence | Groups of five subcarriers around the 12 | Both profiles |
| L1 displacement | The same 12 fixed subcarriers | High Accuracy |
| Channel shape | All 56 HT20 subcarriers, grouped into 8 normalized bands | High Accuracy |
So High Accuracy also looks at the whole band for its channel-shape features, while the other trackers stay small. All features use ratios, correlations, or normalized values, so the radio's automatic gain changes affect them little.
Why the High Accuracy model stays small
The model does not read raw CSI. It gets eight features that already describe motion and the shape of the channel over real time. It has 492 weights and 37 biases: 529 parameters, or 2,116 bytes as 32-bit floats. The C++ detector computes it directly, with no neural-network library.
The size may change in future versions.
Select the profile before setup
The runtime then takes care of timing, readiness, gaps, and filtering of short spikes.
espectre::RuntimeConfig config =
espectre::make_runtime_sensing_config_from_kconfig();
config.detection_algorithm =
espectre::DetectionAlgorithm::HIGH_ACCURACY;
espectre::RuntimeFrontendController runtime;
runtime.set_config(config);
runtime.setup(listener);
Use DetectionAlgorithm::LIGHTWEIGHT for the lighter profile. An integration that uses only the core can create detectors directly, but must then handle timing, readiness, gaps, and spike filtering the same way the runtime does.
Evidence sources
The algorithm reference explains timing and frequency handling. The feature ledger lists every feature we tested and the results. The generated reports hold the full quality, timing, and resource measurements summarized here.